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)); }