示例#1
0
        private static unsafe SafeLocalAllocHandle EncodePublicKey(PublicKey key)
        {
            SafeLocalAllocHandle publicKeyInfo = SafeLocalAllocHandle.InvalidHandle;

            CAPI.CERT_PUBLIC_KEY_INFO2 *pPublicKeyInfo = null;
            string objId = key.Oid.Value;

            byte[] encodedParameters = key.EncodedParameters.RawData;
            byte[] encodedKeyValue   = key.EncodedKeyValue.RawData;

            uint cbPublicKeyInfo = (uint)(Marshal.SizeOf(typeof(CAPI.CERT_PUBLIC_KEY_INFO2)) +
                                          X509Utils.AlignedLength((uint)(objId.Length + 1)) +
                                          X509Utils.AlignedLength((uint)encodedParameters.Length) +
                                          encodedKeyValue.Length);

            publicKeyInfo  = CAPI.LocalAlloc(CAPI.LPTR, new IntPtr(cbPublicKeyInfo));
            pPublicKeyInfo = (CAPI.CERT_PUBLIC_KEY_INFO2 *)publicKeyInfo.DangerousGetHandle();
            IntPtr pszObjId     = new IntPtr((long)pPublicKeyInfo + Marshal.SizeOf(typeof(CAPI.CERT_PUBLIC_KEY_INFO2)));
            IntPtr pbParameters = new IntPtr((long)pszObjId + X509Utils.AlignedLength(((uint)(objId.Length + 1))));
            IntPtr pbPublicKey  = new IntPtr((long)pbParameters + X509Utils.AlignedLength((uint)encodedParameters.Length));

            pPublicKeyInfo->Algorithm.pszObjId = pszObjId;
            byte[] szObjId = new byte[objId.Length + 1];
            Encoding.ASCII.GetBytes(objId, 0, objId.Length, szObjId, 0);
            Marshal.Copy(szObjId, 0, pszObjId, szObjId.Length);
            if (encodedParameters.Length > 0)
            {
                pPublicKeyInfo->Algorithm.Parameters.cbData = (uint)encodedParameters.Length;
                pPublicKeyInfo->Algorithm.Parameters.pbData = pbParameters;
                Marshal.Copy(encodedParameters, 0, pbParameters, encodedParameters.Length);
            }
            pPublicKeyInfo->PublicKey.cbData = (uint)encodedKeyValue.Length;
            pPublicKeyInfo->PublicKey.pbData = pbPublicKey;
            Marshal.Copy(encodedKeyValue, 0, pbPublicKey, encodedKeyValue.Length);
            return(publicKeyInfo);
        }
示例#2
0
        private static unsafe byte[] EncodePublicKey(PublicKey key, X509SubjectKeyIdentifierHashAlgorithm algorithm)
        {
            if (key == null)
            {
                throw new ArgumentNullException("key");
            }

            // Construct CERT_PUBLIC_KEY_INFO2 in unmanged memory from given encoded blobs.
            SafeLocalAllocHandle publicKeyInfo = EncodePublicKey(key);

            CAPI.CERT_PUBLIC_KEY_INFO2 *pPublicKeyInfo = (CAPI.CERT_PUBLIC_KEY_INFO2 *)publicKeyInfo.DangerousGetHandle();

            byte [] buffer     = new byte[20];
            byte [] identifier = null;

            fixed(byte *pBuffer = buffer)
            {
                uint   cbData = (uint)buffer.Length;
                IntPtr pbData = new IntPtr(pBuffer);

                try {
                    if ((X509SubjectKeyIdentifierHashAlgorithm.Sha1 == algorithm) ||
                        (X509SubjectKeyIdentifierHashAlgorithm.ShortSha1 == algorithm))
                    {
                        //+=================================================================
                        // (1) The keyIdentifier is composed of the 160-bit SHA-1 hash of
                        // the value of the BIT STRING subjectPublicKey (excluding the tag,
                        // length, and number of unused bits).
                        if (!CAPI.CryptHashCertificate(
                                IntPtr.Zero,            // hCryptProv
                                CAPI.CALG_SHA1,
                                0,                      // dwFlags,
                                pPublicKeyInfo->PublicKey.pbData,
                                pPublicKeyInfo->PublicKey.cbData,
                                pbData,
                                new IntPtr(&cbData)))
                        {
                            throw new CryptographicException(Marshal.GetHRForLastWin32Error());
                        }
                    }
                    //+=================================================================
                    // Microsoft convention: The keyIdentifier is composed of the
                    // 160-bit SHA-1 hash of the encoded subjectPublicKey BITSTRING
                    // (including the tag, length, and number of unused bits).
                    else if (X509SubjectKeyIdentifierHashAlgorithm.CapiSha1 == algorithm)
                    {
                        if (!CAPI.CryptHashPublicKeyInfo(
                                IntPtr.Zero,            // hCryptProv
                                CAPI.CALG_SHA1,
                                0,                      // dwFlags,
                                CAPI.X509_ASN_ENCODING,
                                new IntPtr(pPublicKeyInfo),
                                pbData,
                                new IntPtr(&cbData)))
                        {
                            throw new CryptographicException(Marshal.GetHRForLastWin32Error());
                        }
                    }
                    else
                    {
                        throw new ArgumentException("algorithm");
                    }

                    //+=================================================================
                    // (2) The keyIdentifier is composed of a four bit type field with
                    //  the value 0100 followed by the least significant 60 bits of the
                    //  SHA-1 hash of the value of the BIT STRING subjectPublicKey
                    // (excluding the tag, length, and number of unused bit string bits)
                    if (X509SubjectKeyIdentifierHashAlgorithm.ShortSha1 == algorithm)
                    {
                        identifier = new byte[8];
                        Array.Copy(buffer, buffer.Length - 8, identifier, 0, identifier.Length);
                        identifier[0] &= 0x0f;
                        identifier[0] |= 0x40;
                    }
                    else
                    {
                        identifier = buffer;
                        // return the meaningful part only
                        if (buffer.Length > (int)cbData)
                        {
                            identifier = new byte[cbData];
                            Array.Copy(buffer, 0, identifier, 0, identifier.Length);
                        }
                    }
                } finally {
                    publicKeyInfo.Dispose();
                }
            }

            return(EncodeExtension(identifier));
        }