/// <summary> /// Find a typed extension in a extension collection. /// </summary> /// <typeparam name="T">The type of the extension.</typeparam> /// <param name="extensions">The extensions to search.</param> public static T FindExtension <T>(this X509ExtensionCollection extensions) where T : X509Extension { if (extensions == null) { throw new ArgumentNullException(nameof(extensions)); } lock (extensions.SyncRoot) { // search known custom extensions if (typeof(T) == typeof(X509AuthorityKeyIdentifierExtension)) { var extension = extensions.Cast <X509Extension>().FirstOrDefault(e => ( e.Oid.Value == X509AuthorityKeyIdentifierExtension.AuthorityKeyIdentifierOid || e.Oid.Value == X509AuthorityKeyIdentifierExtension.AuthorityKeyIdentifier2Oid) ); if (extension != null) { return(new X509AuthorityKeyIdentifierExtension(extension, extension.Critical) as T); } } if (typeof(T) == typeof(X509SubjectAltNameExtension)) { var extension = extensions.Cast <X509Extension>().FirstOrDefault(e => ( e.Oid.Value == X509SubjectAltNameExtension.SubjectAltNameOid || e.Oid.Value == X509SubjectAltNameExtension.SubjectAltName2Oid) ); if (extension != null) { return(new X509SubjectAltNameExtension(extension, extension.Critical) as T); } } if (typeof(T) == typeof(X509CrlNumberExtension)) { var extension = extensions.Cast <X509Extension>().FirstOrDefault(e => ( e.Oid.Value == X509CrlNumberExtension.CrlNumberOid) ); if (extension != null) { return(new X509CrlNumberExtension(extension, extension.Critical) as T); } } // search builtin extension return(extensions.OfType <T>().FirstOrDefault()); } }
public static byte[] GetAppleAttestationExtensionValue(X509ExtensionCollection exts) { var appleExtension = exts.Cast <X509Extension>().FirstOrDefault(e => e.Oid.Value == "1.2.840.113635.100.8.2"); if (appleExtension == null || appleExtension.RawData == null || appleExtension.RawData.Length < 0x26) { throw new VerificationException("Extension with OID 1.2.840.113635.100.8.2 not found on Apple attestation credCert"); } try { var appleAttestationASN = AsnElt.Decode(appleExtension.RawData); appleAttestationASN.CheckConstructed(); appleAttestationASN.CheckTag(AsnElt.SEQUENCE); appleAttestationASN.CheckNumSub(1); var sequence = appleAttestationASN.GetSub(0); sequence.CheckConstructed(); sequence.CheckNumSub(1); var context = sequence.GetSub(0); context.CheckPrimitive(); context.CheckTag(AsnElt.OCTET_STRING); return(context.GetOctetString()); } catch (Exception ex) { throw new VerificationException("Apple attestation extension has invalid data", ex); } }
internal static byte U2FTransportsFromAttnCert(X509ExtensionCollection exts) { var u2ftransports = new byte(); var ext = exts.Cast <X509Extension>().FirstOrDefault(e => e.Oid.Value is "1.3.6.1.4.1.45724.2.1.1"); if (ext != null) { var decodedU2Ftransports = Asn1Element.Decode(ext.RawData); decodedU2Ftransports.CheckPrimitive(); // some certificates seem to have this encoded as an octet string // instead of a bit string, attempt to correct if (decodedU2Ftransports.Tag == Asn1Tag.PrimitiveOctetString) { ext.RawData[0] = (byte)UniversalTagNumber.BitString; decodedU2Ftransports = Asn1Element.Decode(ext.RawData); } decodedU2Ftransports.CheckTag(Asn1Tag.PrimitiveBitString); u2ftransports = decodedU2Ftransports.GetBitString()[0]; } return(u2ftransports); }
public static byte[] GetAppleAttestationExtensionValue(X509ExtensionCollection exts) { var appleExtension = exts.Cast <X509Extension>().FirstOrDefault(e => e.Oid !.Value is "1.2.840.113635.100.8.2"); if (appleExtension is null || appleExtension.RawData is null || appleExtension.RawData.Length < 0x26) { throw new Fido2VerificationException("Extension with OID 1.2.840.113635.100.8.2 not found on Apple attestation credCert"); } try { var appleAttestationASN = Asn1Element.Decode(appleExtension.RawData); appleAttestationASN.CheckTag(new Asn1Tag(UniversalTagNumber.Sequence, isConstructed: true)); appleAttestationASN.CheckExactSequenceLength(1); var appleAttestationASNSequence = appleAttestationASN[0]; appleAttestationASNSequence.CheckConstructed(); appleAttestationASNSequence.CheckExactSequenceLength(1); appleAttestationASNSequence[0].CheckTag(Asn1Tag.PrimitiveOctetString); return(appleAttestationASNSequence[0].GetOctetString()); } catch (Exception ex) { throw new Fido2VerificationException("Apple attestation extension has invalid data", ex); } }
public static X509Extension[] ToArray(this X509ExtensionCollection exts) { if (exts == null) { return(null); } List <X509Extension> e = new List <X509Extension>(exts.Cast <X509Extension>()); return(e.ToArray()); }
internal static bool IsAttnCertCACert(X509ExtensionCollection exts) { var ext = exts.Cast <X509Extension>().FirstOrDefault(e => e.Oid.Value is "2.5.29.19"); if (ext is X509BasicConstraintsExtension baseExt) { return(baseExt.CertificateAuthority); } return(true); }
internal static void RemoveAt(this X509ExtensionCollection exts, Int32 index) { if (exts == null || index >= exts.Count) { return; } List <X509Extension> e = new List <X509Extension>(exts.Cast <X509Extension>()); e.RemoveAt(index); exts = new X509ExtensionCollection(); foreach (X509Extension ext in e) { exts.Add(ext); } }
internal static byte[] AaguidFromAttnCertExts(X509ExtensionCollection exts) { byte[] aaguid = null; var ext = exts.Cast <X509Extension>().FirstOrDefault(e => e.Oid.Value is "1.3.6.1.4.1.45724.1.1.4"); // id-fido-gen-ce-aaguid if (ext != null) { var decodedAaguid = Asn1Element.Decode(ext.RawData); decodedAaguid.CheckTag(Asn1Tag.PrimitiveOctetString); aaguid = decodedAaguid.GetOctetString(); // The extension MUST NOT be marked as critical if (ext.Critical) { throw new Fido2VerificationException("extension MUST NOT be marked as critical"); } } return(aaguid); }
public static void Insert(this X509ExtensionCollection exts, Int32 index, X509Extension extension) { if (extension == null) { throw new ArgumentNullException(nameof(extension)); } if (exts == null) { return; } if (index < 0 || index >= exts.Count) { throw new OverflowException(); } List <X509Extension> e = new List <X509Extension>(exts.Cast <X509Extension>()); e.Insert(index, extension); exts = new X509ExtensionCollection(); exts.AddRange(e); }
internal static byte U2FTransportsFromAttnCert(X509ExtensionCollection exts) { var u2ftransports = new byte(); var ext = exts.Cast <X509Extension>().FirstOrDefault(e => e.Oid.Value == "1.3.6.1.4.1.45724.2.1.1"); if (null != ext) { var decodedU2Ftransports = AsnElt.Decode(ext.RawData); decodedU2Ftransports.CheckPrimitive(); // some certificates seem to have this encoded as an octet string // instead of a bit string, attempt to correct if (AsnElt.OCTET_STRING == decodedU2Ftransports.TagValue) { ext.RawData[0] = AsnElt.BIT_STRING; decodedU2Ftransports = AsnElt.Decode(ext.RawData); } decodedU2Ftransports.CheckTag(AsnElt.BIT_STRING); u2ftransports = decodedU2Ftransports.GetBitString()[0]; } return(u2ftransports); }
/// <summary> /// Create a new certificate /// </summary> /// <param name="issuer">Issuer certificate, if null then self-sign</param> /// <param name="subjectName">Subject name</param> /// <param name="serialNumber">Serial number of certificate, if null then will generate a new one</param> /// <param name="signature">If true create an AT_SIGNATURE key, otherwise AT_EXCHANGE</param> /// <param name="keySize">Size of RSA key</param> /// <param name="notBefore">Start date of certificate</param> /// <param name="notAfter">End date of certificate</param> /// <param name="extensions">Array of extensions, if null then no extensions</param> /// <param name="hashAlgorithm">Specify the signature hash algorithm</param> /// <returns>The created X509 certificate</returns> public X509Certificate2 CreateCert(X509Certificate2 issuer, X500DistinguishedName subjectName, byte[] serialNumber, bool signature, int keySize, CertificateHashAlgorithm hashAlgorithm, DateTime notBefore, DateTime notAfter, X509ExtensionCollection extensions) { CryptoApiMethods.CERT_INFO certInfo = new CryptoApiMethods.CERT_INFO(); RSACryptoServiceProvider key = CreateRSAKey(keySize, signature); IntPtr publicKeyInfoPtr = IntPtr.Zero; X509Certificate2 cert = null; List <X509Extension> newExts = null; if (extensions != null) { foreach (X509Extension ext in extensions) { if (ext.RawData == null) { throw new ArgumentException(Properties.Resources.CreateCert_NeedEncodedData); } } } try { if (serialNumber == null) { serialNumber = Guid.NewGuid().ToByteArray(); } certInfo.dwVersion = (uint)CryptoApiMethods.CertVersion.CERT_V3; certInfo.SerialNumber = new CryptoApiMethods.CRYPTOAPI_BLOB(serialNumber); certInfo.Subject = new CryptoApiMethods.CRYPTOAPI_BLOB(subjectName.RawData); if (issuer == null) { // Self-signed certInfo.Issuer = new CryptoApiMethods.CRYPTOAPI_BLOB(subjectName.RawData); } else { certInfo.Issuer = new CryptoApiMethods.CRYPTOAPI_BLOB(issuer.SubjectName.RawData); } // Never seems to need these set to anything valid? certInfo.SubjectUniqueId = new CryptoApiMethods.CRYPT_BIT_BLOB(); certInfo.IssuerUniqueId = new CryptoApiMethods.CRYPT_BIT_BLOB(); certInfo.NotBefore = DateTimeToFileTime(notBefore); certInfo.NotAfter = DateTimeToFileTime(notAfter); certInfo.SignatureAlgorithm = new CryptoApiMethods.CRYPT_ALGORITHM_IDENTIFIER(); // Doesn't seem to work properly with standard szOID_RSA_SHA1RSA //certInfo.SignatureAlgorithm.pszObjId = CryptoApiMethods.szOID_OIWSEC_sha1RSASign; //certInfo.SignatureAlgorithm.pszObjId = CryptoApiMethods.szOID_RSA_SHA1RSA; //certInfo.SignatureAlgorithm.pszObjId = CryptoApiMethods.szOID_RSA_SHA512RSA; certInfo.SignatureAlgorithm.pszObjId = HashAlgorithmToOID(hashAlgorithm); // Add extension fields publicKeyInfoPtr = ExportPublicKeyInfo(key); certInfo.SubjectPublicKeyInfo = (CryptoApiMethods.CERT_PUBLIC_KEY_INFO)Marshal.PtrToStructure(publicKeyInfoPtr, typeof(CryptoApiMethods.CERT_PUBLIC_KEY_INFO)); newExts = new List <X509Extension>(); if (extensions != null) { // Filter out some extensions we don't want newExts.AddRange( extensions.Cast <X509Extension>().Where( x => !x.Oid.Value.Equals(CryptoApiMethods.szOID_AUTHORITY_KEY_IDENTIFIER) && !x.Oid.Value.Equals(CryptoApiMethods.szOID_SUBJECT_KEY_IDENTIFIER) && !x.Oid.Value.Equals(CryptoApiMethods.szOID_AUTHORITY_KEY_IDENTIFIER2))); } if (issuer != null) { newExts.Add(CreateAuthorityKeyInfo2(issuer.GetSerialNumber(), issuer.SubjectName, (RSACryptoServiceProvider)issuer.PrivateKey)); } else { newExts.Add(CreateAuthorityKeyInfo2(serialNumber, subjectName, key)); } newExts.Add(new X509SubjectKeyIdentifierExtension(HashPublicKeyInfo(key), false)); certInfo.rgExtension = MarshalExtensions(newExts.ToArray()); certInfo.cExtension = (uint)newExts.Count; byte[] certData = EncodeAndSignCertInfo(issuer != null ? issuer.PrivateKey as RSACryptoServiceProvider : key, certInfo, hashAlgorithm); cert = new X509Certificate2(certData, (string)null, X509KeyStorageFlags.Exportable); cert.PrivateKey = key; } finally { if (certInfo.rgExtension != IntPtr.Zero) { Marshal.FreeHGlobal(certInfo.rgExtension); } if (certInfo.Subject != null) { certInfo.Subject.Release(); } if (certInfo.Issuer != null) { certInfo.Issuer.Release(); } if (publicKeyInfoPtr != IntPtr.Zero) { Marshal.FreeHGlobal(publicKeyInfoPtr); } } return(cert); }