private static void EncodeDecode( byte[] certBytes, X509SubjectKeyIdentifierHashAlgorithm algorithm, bool critical, byte[] expectedDer, string expectedIdentifier) { PublicKey pk; using (var cert = new X509Certificate2(certBytes)) { pk = cert.PublicKey; } X509SubjectKeyIdentifierExtension ext = new X509SubjectKeyIdentifierExtension(pk, algorithm, critical); byte[] rawData = ext.RawData; Assert.Equal(expectedDer, rawData); ext = new X509SubjectKeyIdentifierExtension(new AsnEncodedData(rawData), critical); Assert.Equal(expectedIdentifier, ext.SubjectKeyIdentifier); Assert.Equal(expectedIdentifier, Convert.ToHexString(ext.SubjectKeyIdentifierBytes.Span)); ReadOnlyMemory <byte> ski1 = ext.SubjectKeyIdentifierBytes; ReadOnlyMemory <byte> ski2 = ext.SubjectKeyIdentifierBytes; Assert.True(ski1.Span == ski2.Span, "Two calls to SubjectKeyIdentifierBytes return the same buffer"); }
public X509SubjectKeyIdentifierExtension(PublicKey key, X509SubjectKeyIdentifierHashAlgorithm algorithm, bool critical) { Contract.Requires(key.EncodedKeyValue != null); Contract.Requires(key.EncodedKeyValue.RawData != null); Contract.Requires(key.EncodedParameters != null); Contract.Requires(key.EncodedParameters.RawData != null); Contract.Ensures(key.EncodedParameters.RawData != null); }
private static byte[] EncodeExtension(PublicKey key, X509SubjectKeyIdentifierHashAlgorithm algorithm) { if (key == null) { throw new ArgumentNullException(nameof(key)); } byte[] subjectKeyIdentifier = GenerateSubjectKeyIdentifierFromPublicKey(key, algorithm); return(EncodeExtension(subjectKeyIdentifier)); }
public X509SubjectKeyIdentifierExtension(PublicKey key, X509SubjectKeyIdentifierHashAlgorithm algorithm, bool critical) { if (key == null) { throw new ArgumentNullException("key"); } byte[] pkraw = key.EncodedKeyValue.RawData; // compute SKI switch (algorithm) { // hash of the public key, excluding Tag, Length and unused bits values case X509SubjectKeyIdentifierHashAlgorithm.Sha1: _subjectKeyIdentifier = SHA1.Create().ComputeHash(pkraw); break; // 0100 bit pattern followed by the 60 last bit of the hash case X509SubjectKeyIdentifierHashAlgorithm.ShortSha1: byte[] hash = SHA1.Create().ComputeHash(pkraw); _subjectKeyIdentifier = new byte [8]; Buffer.BlockCopy(hash, 12, _subjectKeyIdentifier, 0, 8); _subjectKeyIdentifier [0] = (byte)(0x40 | (_subjectKeyIdentifier [0] & 0x0F)); break; // hash of the public key, including Tag, Length and unused bits values case X509SubjectKeyIdentifierHashAlgorithm.CapiSha1: // CryptoAPI does that hash on the complete subjectPublicKeyInfo (unlike PKIX) // http://groups.google.ca/groups?selm=e7RqM%24plCHA.1488%40tkmsftngp02&oe=UTF-8&output=gplain ASN1 subjectPublicKeyInfo = new ASN1(0x30); ASN1 algo = subjectPublicKeyInfo.Add(new ASN1(0x30)); algo.Add(new ASN1(CryptoConfig.EncodeOID(key.Oid.Value))); algo.Add(new ASN1(key.EncodedParameters.RawData)); // add an extra byte for the unused bits (none) byte[] full = new byte [pkraw.Length + 1]; Buffer.BlockCopy(pkraw, 0, full, 1, pkraw.Length); subjectPublicKeyInfo.Add(new ASN1(0x03, full)); _subjectKeyIdentifier = SHA1.Create().ComputeHash(subjectPublicKeyInfo.GetBytes()); break; default: throw new ArgumentException("algorithm"); } _oid = new Oid(oid, friendlyName); base.Critical = critical; RawData = Encode(); }
private static void TestSubjectKeyIdentifierExtension( byte[] certBytes, X509SubjectKeyIdentifierHashAlgorithm algorithm, bool critical, byte[] expectedDer, string expectedIdentifier) { PublicKey pk = new X509Certificate2(certBytes).PublicKey; X509SubjectKeyIdentifierExtension ext = new X509SubjectKeyIdentifierExtension(pk, algorithm, critical); byte[] rawData = ext.RawData; Assert.Equal(expectedDer, rawData); ext = new X509SubjectKeyIdentifierExtension(new AsnEncodedData(rawData), critical); Assert.Equal(expectedIdentifier, ext.SubjectKeyIdentifier); }
/// <summary>Initializes a new instance of the <see cref="T:System.Security.Cryptography.X509Certificates.X509SubjectKeyIdentifierExtension" /> class using a public key, a hash algorithm identifier, and a value indicating whether the extension is critical. </summary> /// <param name="key">A <see cref="T:System.Security.Cryptography.X509Certificates.PublicKey" /> object to create a subject key identifier (SKI) from.</param> /// <param name="algorithm">One of the <see cref="T:System.Security.Cryptography.X509Certificates.X509SubjectKeyIdentifierHashAlgorithm" /> values that identifies which hash algorithm to use.</param> /// <param name="critical">true if the extension is critical; otherwise, false.</param> public X509SubjectKeyIdentifierExtension(PublicKey key, X509SubjectKeyIdentifierHashAlgorithm algorithm, bool critical) { if (key == null) { throw new ArgumentNullException("key"); } byte[] rawData = key.EncodedKeyValue.RawData; switch (algorithm) { case X509SubjectKeyIdentifierHashAlgorithm.Sha1: this._subjectKeyIdentifier = SHA1.Create().ComputeHash(rawData); break; case X509SubjectKeyIdentifierHashAlgorithm.ShortSha1: { byte[] src = SHA1.Create().ComputeHash(rawData); this._subjectKeyIdentifier = new byte[8]; Buffer.BlockCopy(src, 12, this._subjectKeyIdentifier, 0, 8); this._subjectKeyIdentifier[0] = (64 | (this._subjectKeyIdentifier[0] & 15)); break; } case X509SubjectKeyIdentifierHashAlgorithm.CapiSha1: { ASN1 asn = new ASN1(48); ASN1 asn2 = asn.Add(new ASN1(48)); asn2.Add(new ASN1(CryptoConfig.EncodeOID(key.Oid.Value))); asn2.Add(new ASN1(key.EncodedParameters.RawData)); byte[] array = new byte[rawData.Length + 1]; Buffer.BlockCopy(rawData, 0, array, 1, rawData.Length); asn.Add(new ASN1(3, array)); this._subjectKeyIdentifier = SHA1.Create().ComputeHash(asn.GetBytes()); break; } default: throw new ArgumentException("algorithm"); } this._oid = new Oid("2.5.29.14", "Subject Key Identifier"); base.Critical = critical; base.RawData = this.Encode(); }
public X509SubjectKeyIdentifierExtension (PublicKey key, X509SubjectKeyIdentifierHashAlgorithm algorithm, bool critical) : base (CAPI.szOID_SUBJECT_KEY_IDENTIFIER, EncodePublicKey(key, algorithm), critical) {}
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); }
public X509SubjectKeyIdentifierExtension(PublicKey key, X509SubjectKeyIdentifierHashAlgorithm algorithm, bool critical);
public X509SubjectKeyIdentifierExtension(PublicKey key, X509SubjectKeyIdentifierHashAlgorithm algorithm, bool critical) : base("2.5.29.14", EncodePublicKey(key, algorithm), critical) { }
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)); }
public X509SubjectKeyIdentifierExtension (PublicKey key, X509SubjectKeyIdentifierHashAlgorithm algorithm, bool critical) { if (key == null) throw new ArgumentNullException ("key"); byte[] pkraw = key.EncodedKeyValue.RawData; // compute SKI switch (algorithm) { // hash of the public key, excluding Tag, Length and unused bits values case X509SubjectKeyIdentifierHashAlgorithm.Sha1: _subjectKeyIdentifier = SHA1.Create ().ComputeHash (pkraw); break; // 0100 bit pattern followed by the 60 last bit of the hash case X509SubjectKeyIdentifierHashAlgorithm.ShortSha1: byte[] hash = SHA1.Create ().ComputeHash (pkraw); _subjectKeyIdentifier = new byte [8]; Buffer.BlockCopy (hash, 12, _subjectKeyIdentifier, 0, 8); _subjectKeyIdentifier [0] = (byte) (0x40 | (_subjectKeyIdentifier [0] & 0x0F)); break; // hash of the public key, including Tag, Length and unused bits values case X509SubjectKeyIdentifierHashAlgorithm.CapiSha1: // CryptoAPI does that hash on the complete subjectPublicKeyInfo (unlike PKIX) // http://groups.google.ca/groups?selm=e7RqM%24plCHA.1488%40tkmsftngp02&oe=UTF-8&output=gplain ASN1 subjectPublicKeyInfo = new ASN1 (0x30); ASN1 algo = subjectPublicKeyInfo.Add (new ASN1 (0x30)); algo.Add (new ASN1 (CryptoConfig.EncodeOID (key.Oid.Value))); algo.Add (new ASN1 (key.EncodedParameters.RawData)); // add an extra byte for the unused bits (none) byte[] full = new byte [pkraw.Length + 1]; Buffer.BlockCopy (pkraw, 0, full, 1, pkraw.Length); subjectPublicKeyInfo.Add (new ASN1 (0x03, full)); _subjectKeyIdentifier = SHA1.Create ().ComputeHash (subjectPublicKeyInfo.GetBytes ()); break; default: throw new ArgumentException ("algorithm"); } _oid = new Oid (oid, friendlyName); base.Critical = critical; RawData = Encode (); }
public X509SubjectKeyIdentifierExtension(PublicKey key, X509SubjectKeyIdentifierHashAlgorithm algorithm, bool critical) : base(Oids.SubjectKeyIdentifier, EncodeExtension(key, algorithm), critical) { }
private static unsafe byte[] EncodePublicKey(PublicKey key, X509SubjectKeyIdentifierHashAlgorithm algorithm) { if (key == null) { throw new ArgumentNullException("key"); } SafeLocalAllocHandle handle = EncodePublicKey(key); CAPIBase.CERT_PUBLIC_KEY_INFO2* cert_public_key_infoPtr = (CAPIBase.CERT_PUBLIC_KEY_INFO2*) handle.DangerousGetHandle(); byte[] sourceArray = new byte[20]; byte[] destinationArray = null; fixed (byte* numRef = sourceArray) { uint length = (uint) sourceArray.Length; IntPtr pbComputedHash = new IntPtr((void*) numRef); try { if ((algorithm == X509SubjectKeyIdentifierHashAlgorithm.Sha1) || (X509SubjectKeyIdentifierHashAlgorithm.ShortSha1 == algorithm)) { if (!CAPISafe.CryptHashCertificate(IntPtr.Zero, 0x8004, 0, cert_public_key_infoPtr->PublicKey.pbData, cert_public_key_infoPtr->PublicKey.cbData, pbComputedHash, new IntPtr((void*) &length))) { throw new CryptographicException(Marshal.GetHRForLastWin32Error()); } } else { if (X509SubjectKeyIdentifierHashAlgorithm.CapiSha1 != algorithm) { throw new ArgumentException("algorithm"); } if (!CAPISafe.CryptHashPublicKeyInfo(IntPtr.Zero, 0x8004, 0, 1, new IntPtr((void*) cert_public_key_infoPtr), pbComputedHash, new IntPtr((void*) &length))) { throw new CryptographicException(Marshal.GetHRForLastWin32Error()); } } if (X509SubjectKeyIdentifierHashAlgorithm.ShortSha1 == algorithm) { destinationArray = new byte[8]; Array.Copy(sourceArray, sourceArray.Length - 8, destinationArray, 0, destinationArray.Length); destinationArray[0] = (byte) (destinationArray[0] & 15); destinationArray[0] = (byte) (destinationArray[0] | 0x40); } else { destinationArray = sourceArray; if (sourceArray.Length > length) { destinationArray = new byte[length]; Array.Copy(sourceArray, 0, destinationArray, 0, destinationArray.Length); } } } finally { handle.Dispose(); } } return EncodeExtension(destinationArray); }
public X509SubjectKeyIdentifierExtension(PublicKey key, X509SubjectKeyIdentifierHashAlgorithm algorithm, bool critical) { }
public X509SubjectKeyIdentifierExtension(PublicKey key, X509SubjectKeyIdentifierHashAlgorithm algorithm, bool critical) : base(Oids.SubjectKeyIdentifierOid, EncodeExtension(key, algorithm), critical) { }
private static byte[] GenerateSubjectKeyIdentifierFromPublicKey(PublicKey key, X509SubjectKeyIdentifierHashAlgorithm algorithm) { switch (algorithm) { case X509SubjectKeyIdentifierHashAlgorithm.Sha1: return(SHA1.HashData(key.EncodedKeyValue.RawData)); case X509SubjectKeyIdentifierHashAlgorithm.ShortSha1: { byte[] sha1 = SHA1.HashData(key.EncodedKeyValue.RawData); // ShortSha1: 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) byte[] shortSha1 = new byte[8]; Buffer.BlockCopy(sha1, sha1.Length - 8, shortSha1, 0, shortSha1.Length); shortSha1[0] &= 0x0f; shortSha1[0] |= 0x40; return(shortSha1); } case X509SubjectKeyIdentifierHashAlgorithm.CapiSha1: return(X509Pal.Instance.ComputeCapiSha1OfPublicKey(key)); default: throw new ArgumentException(SR.Format(SR.Arg_EnumIllegalVal, algorithm), nameof(algorithm)); } }
private static byte[] EncodeExtension(PublicKey key, X509SubjectKeyIdentifierHashAlgorithm algorithm) { if (key == null) throw new ArgumentNullException(nameof(key)); byte[] subjectKeyIdentifier = GenerateSubjectKeyIdentifierFromPublicKey(key, algorithm); return EncodeExtension(subjectKeyIdentifier); }
public X509SubjectKeyIdentifierExtension(PublicKey key, X509SubjectKeyIdentifierHashAlgorithm algorithm, bool critical) : base(CAPI.szOID_SUBJECT_KEY_IDENTIFIER, EncodePublicKey(key, algorithm), critical) { }
private static byte[] GenerateSubjectKeyIdentifierFromPublicKey(PublicKey key, X509SubjectKeyIdentifierHashAlgorithm algorithm) { switch (algorithm) { case X509SubjectKeyIdentifierHashAlgorithm.Sha1: return ComputeSha1(key.EncodedKeyValue.RawData); case X509SubjectKeyIdentifierHashAlgorithm.ShortSha1: { byte[] sha1 = ComputeSha1(key.EncodedKeyValue.RawData); // ShortSha1: 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) byte[] shortSha1 = new byte[8]; Buffer.BlockCopy(sha1, sha1.Length - 8, shortSha1, 0, shortSha1.Length); shortSha1[0] &= 0x0f; shortSha1[0] |= 0x40; return shortSha1; } case X509SubjectKeyIdentifierHashAlgorithm.CapiSha1: return X509Pal.Instance.ComputeCapiSha1OfPublicKey(key); default: throw new ArgumentException(SR.Format(SR.Arg_EnumIllegalVal, algorithm), nameof(algorithm)); } }
public X509SubjectKeyIdentifierExtension (PublicKey key, X509SubjectKeyIdentifierHashAlgorithm algorithm, bool critical) { if (key == null) throw new ArgumentNullException ("key"); }
private static unsafe byte[] EncodePublicKey(PublicKey key, X509SubjectKeyIdentifierHashAlgorithm algorithm) { if (key == null) { throw new ArgumentNullException("key"); } SafeLocalAllocHandle handle = EncodePublicKey(key); CAPIBase.CERT_PUBLIC_KEY_INFO2 *cert_public_key_infoPtr = (CAPIBase.CERT_PUBLIC_KEY_INFO2 *)handle.DangerousGetHandle(); byte[] sourceArray = new byte[20]; byte[] destinationArray = null; fixed(byte *numRef = sourceArray) { uint length = (uint)sourceArray.Length; IntPtr pbComputedHash = new IntPtr((void *)numRef); try { if ((algorithm == X509SubjectKeyIdentifierHashAlgorithm.Sha1) || (X509SubjectKeyIdentifierHashAlgorithm.ShortSha1 == algorithm)) { if (!CAPISafe.CryptHashCertificate(IntPtr.Zero, 0x8004, 0, cert_public_key_infoPtr->PublicKey.pbData, cert_public_key_infoPtr->PublicKey.cbData, pbComputedHash, new IntPtr((void *)&length))) { throw new CryptographicException(Marshal.GetHRForLastWin32Error()); } } else { if (X509SubjectKeyIdentifierHashAlgorithm.CapiSha1 != algorithm) { throw new ArgumentException("algorithm"); } if (!CAPISafe.CryptHashPublicKeyInfo(IntPtr.Zero, 0x8004, 0, 1, new IntPtr((void *)cert_public_key_infoPtr), pbComputedHash, new IntPtr((void *)&length))) { throw new CryptographicException(Marshal.GetHRForLastWin32Error()); } } if (X509SubjectKeyIdentifierHashAlgorithm.ShortSha1 == algorithm) { destinationArray = new byte[8]; Array.Copy(sourceArray, sourceArray.Length - 8, destinationArray, 0, destinationArray.Length); destinationArray[0] = (byte)(destinationArray[0] & 15); destinationArray[0] = (byte)(destinationArray[0] | 0x40); } else { destinationArray = sourceArray; if (sourceArray.Length > length) { destinationArray = new byte[length]; Array.Copy(sourceArray, 0, destinationArray, 0, destinationArray.Length); } } } finally { handle.Dispose(); } } return(EncodeExtension(destinationArray)); }
public X509SubjectKeyIdentifierExtension(PublicKey key, X509SubjectKeyIdentifierHashAlgorithm algorithm, bool critical) { throw new NotImplementedException(); }