private static bool HasECDsaKeyUsage(X509Certificate2 certificate) { foreach (X509Extension extension in certificate.Extensions) { if (extension.Oid !.Value == Oids.KeyUsage) { X509KeyUsageExtension ext = (X509KeyUsageExtension)extension; if ((ext.KeyUsages & X509KeyUsageFlags.KeyAgreement) == 0) { // If this does not have KeyAgreement flag present, it cannot be ECDH // or ECMQV key as KeyAgreement is mandatory flag for ECDH or ECMQV (RFC 5480 Section 3). // // In that case, at this point, it is safe to assume it is ECDSA return(true); } // Even if KeyAgreement was specified, if any of the signature uses was // specified then ECDSA is a valid usage. const X509KeyUsageFlags ecdsaFlags = X509KeyUsageFlags.DigitalSignature | X509KeyUsageFlags.NonRepudiation | X509KeyUsageFlags.KeyCertSign | X509KeyUsageFlags.CrlSign; return((ext.KeyUsages & ecdsaFlags) != 0); } } // If the key usage extension is not present in the certificate it is // considered valid for all usages, so we can use it for ECDSA. return(true); }
public void ConstructorAsnEncodedData_BadAsn () { AsnEncodedData aed = new AsnEncodedData ("1.2.3", new byte[0]); X509KeyUsageExtension ku = new X509KeyUsageExtension (aed, true); Assert.AreEqual (String.Empty, ku.Format (true), "Format(true)"); Assert.AreEqual (String.Empty, ku.Format (false), "Format(false)"); X509KeyUsageFlags kuf = ku.KeyUsages; }
internal X509ExtensionCollection(MX.X509Certificate cert) { _list = new ArrayList(cert.Extensions.Count); if (cert.Extensions.Count == 0) { return; } #if !MOONLIGHT object[] parameters = new object [2]; #endif foreach (MX.X509Extension ext in cert.Extensions) { bool critical = ext.Critical; string oid = ext.Oid; byte[] raw_data = null; // extension data is embedded in an octet stream (4) ASN1 value = ext.Value; if ((value.Tag == 0x04) && (value.Count > 0)) { raw_data = value [0].GetBytes(); } X509Extension newt = null; #if MOONLIGHT // non-extensible switch (oid) { case "2.5.29.14": newt = new X509SubjectKeyIdentifierExtension(new AsnEncodedData(oid, raw_data), critical); break; case "2.5.29.15": newt = new X509KeyUsageExtension(new AsnEncodedData(oid, raw_data), critical); break; case "2.5.29.19": newt = new X509BasicConstraintsExtension(new AsnEncodedData(oid, raw_data), critical); break; case "2.5.29.37": newt = new X509EnhancedKeyUsageExtension(new AsnEncodedData(oid, raw_data), critical); break; } #else parameters [0] = new AsnEncodedData(oid, raw_data); parameters [1] = critical; newt = (X509Extension)CryptoConfig.CreateFromName(oid, parameters); #endif if (newt == null) { // not registred in CryptoConfig, using default newt = new X509Extension(oid, raw_data, critical); } _list.Add(newt); } }
public void ConstructorEmpty () { X509KeyUsageExtension ku = new X509KeyUsageExtension (); Assert.IsFalse (ku.Critical , "Critical"); Assert.IsNull (ku.RawData, "RawData"); Assert.AreEqual (oid, ku.Oid.Value, "Oid.Value"); Assert.AreEqual (fname, ku.Oid.FriendlyName, "Oid.FriendlyName"); Assert.AreEqual (String.Empty, ku.Format (true), "Format(true)"); Assert.AreEqual (String.Empty, ku.Format (false), "Format(false)"); }
public void ConstructorEmpty () { X509KeyUsageExtension ku = new X509KeyUsageExtension (); Assert.IsFalse (ku.Critical , "Critical"); Assert.IsNull (ku.RawData, "RawData"); Assert.AreEqual (oid, ku.Oid.Value, "Oid.Value"); // FIXME: Don't expect that FriendlyName is English. This test fails under non-English Windows. //Assert.AreEqual (fname, ku.Oid.FriendlyName, "Oid.FriendlyName"); Assert.AreEqual (String.Empty, ku.Format (true), "Format(true)"); Assert.AreEqual (String.Empty, ku.Format (false), "Format(false)"); Assert.AreEqual (0, (int)ku.KeyUsages, "KeyUsages"); }
public void ConstructorAsnEncodedData () { AsnEncodedData aed = new AsnEncodedData ("1.2.3", new byte[] { 0x03, 0x01, 0x00 }); X509KeyUsageExtension ku = new X509KeyUsageExtension (aed, true); Assert.IsTrue (ku.Critical, "Critical"); Assert.AreEqual (3, ku.RawData.Length, "RawData"); // original Oid ignored Assert.AreEqual (oid, ku.Oid.Value, "Oid.Value"); Assert.AreEqual (fname, ku.Oid.FriendlyName, "Oid.FriendlyName"); Assert.AreEqual ("Information Not Available", ku.Format (true), "Format(true)"); Assert.AreEqual ("Information Not Available", ku.Format (false), "Format(false)"); Assert.AreEqual (0, (int)ku.KeyUsages, "KeyUsages"); }
/// <summary> /// Check if the certificate contains ECDsa key or ECDH / ECMQV key. /// </summary> /// <param name="certificate">Certificate object</param> /// <returns>true if ECDsa key. False otherwise</returns> private static bool IsECDsa(X509Certificate2 certificate) { string algName = certificate.PublicKey.Oid.FriendlyName; string value = certificate.PublicKey.Oid.Value; //At this point check OID. If it matches for ECC certs //then go to extensions and find out difference between ECDSA and ECDH certs if (value != X509Native.szOID_ECC_PUBLIC_KEY) { return(false); } else { //Following section is built based on RFC //http://www.ietf.org/rfc/rfc5280.txt and //http://www.rfc-archive.org/getrfc.php?rfc=5480. This RFC, section 3 describes when // key can be ECDSA or ECDH or ECMQV. foreach (X509Extension extension in certificate.Extensions) { //Check Key Usage OID value if (extension.Oid.Value == "2.5.29.15") { X509KeyUsageExtension ext = (X509KeyUsageExtension)extension; if (!(ext.KeyUsages.HasFlag(X509KeyUsageFlags.KeyAgreement))) { //If this does not have KeyAgreement flag present, it cannot be ECDH or ECMQV key as KeyAgreement // is mandatory flag for ECDH or ECMQV. In that case, at this point, it is safe to assume it is ECDSA return(true); } //If key has any of the following flag then it cannot be ECDH or ECMQV. Assume //it is ECDSA. if (ext.KeyUsages.HasFlag(X509KeyUsageFlags.DigitalSignature) || ext.KeyUsages.HasFlag(X509KeyUsageFlags.NonRepudiation) || ext.KeyUsages.HasFlag(X509KeyUsageFlags.KeyCertSign) || ext.KeyUsages.HasFlag(X509KeyUsageFlags.CrlSign)) { return(true); } else { return(false); } } } } //If key usage extension is not present in the certificate assume ECDSA return(true); }
internal string KeyUsageExtension(bool multiLine) { string result; try { System.Security.Cryptography.X509Certificates.X509KeyUsageExtension x509KeyUsageExtension = new System.Security.Cryptography.X509Certificates.X509KeyUsageExtension(this, false); result = x509KeyUsageExtension.ToString(multiLine); } catch { result = string.Empty; } return(result); }
private void PrepareForNextCertificate(int n) { X509ChainElement x509ChainElement = this.elements[n]; X509Certificate2 certificate = x509ChainElement.Certificate; this.working_issuer_name = certificate.SubjectName; this.working_public_key = certificate.PublicKey.Key; X509BasicConstraintsExtension x509BasicConstraintsExtension = (X509BasicConstraintsExtension)certificate.Extensions["2.5.29.19"]; if (x509BasicConstraintsExtension != null) { if (!x509BasicConstraintsExtension.CertificateAuthority) { x509ChainElement.StatusFlags |= X509ChainStatusFlags.InvalidBasicConstraints; } } else if (certificate.Version >= 3) { x509ChainElement.StatusFlags |= X509ChainStatusFlags.InvalidBasicConstraints; } if (!this.IsSelfIssued(certificate)) { if (this.max_path_length > 0) { this.max_path_length--; } else if (this.bce_restriction != null) { this.bce_restriction.StatusFlags |= X509ChainStatusFlags.InvalidBasicConstraints; } } if (x509BasicConstraintsExtension != null && x509BasicConstraintsExtension.HasPathLengthConstraint && x509BasicConstraintsExtension.PathLengthConstraint < this.max_path_length) { this.max_path_length = x509BasicConstraintsExtension.PathLengthConstraint; this.bce_restriction = x509ChainElement; } X509KeyUsageExtension x509KeyUsageExtension = (X509KeyUsageExtension)certificate.Extensions["2.5.29.15"]; if (x509KeyUsageExtension != null) { X509KeyUsageFlags x509KeyUsageFlags = X509KeyUsageFlags.KeyCertSign; if ((x509KeyUsageExtension.KeyUsages & x509KeyUsageFlags) != x509KeyUsageFlags) { x509ChainElement.StatusFlags |= X509ChainStatusFlags.NotValidForUsage; } } this.ProcessCertificateExtensions(x509ChainElement); }
private X509ChainStatusFlags CheckRevocation(X509Certificate2 certificate, X509Certificate2 ca_cert, bool online) { X509KeyUsageExtension x509KeyUsageExtension = (X509KeyUsageExtension)ca_cert.Extensions["2.5.29.15"]; if (x509KeyUsageExtension != null) { X509KeyUsageFlags x509KeyUsageFlags = X509KeyUsageFlags.CrlSign; if ((x509KeyUsageExtension.KeyUsages & x509KeyUsageFlags) != x509KeyUsageFlags) { return(X509ChainStatusFlags.RevocationStatusUnknown); } } X509Crl x509Crl = this.FindCrl(ca_cert); if (x509Crl != null || online) { } if (x509Crl == null) { return(X509ChainStatusFlags.RevocationStatusUnknown); } if (!x509Crl.VerifySignature(ca_cert.PublicKey.Key)) { return(X509ChainStatusFlags.RevocationStatusUnknown); } X509Crl.X509CrlEntry crlEntry = x509Crl.GetCrlEntry(certificate.MonoCertificate); if (crlEntry != null) { if (!this.ProcessCrlEntryExtensions(crlEntry)) { return(X509ChainStatusFlags.Revoked); } if (crlEntry.RevocationDate <= this.ChainPolicy.VerificationTime) { return(X509ChainStatusFlags.Revoked); } } if (x509Crl.NextUpdate < this.ChainPolicy.VerificationTime) { return(X509ChainStatusFlags.RevocationStatusUnknown | X509ChainStatusFlags.OfflineRevocation); } if (!this.ProcessCrlExtensions(x509Crl)) { return(X509ChainStatusFlags.RevocationStatusUnknown); } return(X509ChainStatusFlags.NoError); }
internal X509ExtensionCollection (MX.X509Certificate cert) { _list = new ArrayList (cert.Extensions.Count); if (cert.Extensions.Count == 0) return; #if !MOONLIGHT object[] parameters = new object [2]; #endif foreach (MX.X509Extension ext in cert.Extensions) { bool critical = ext.Critical; string oid = ext.Oid; byte[] raw_data = null; // extension data is embedded in an octet stream (4) ASN1 value = ext.Value; if ((value.Tag == 0x04) && (value.Count > 0)) raw_data = value [0].GetBytes (); X509Extension newt = null; #if MOONLIGHT || FULL_AOT_RUNTIME // non-extensible switch (oid) { case "2.5.29.14": newt = new X509SubjectKeyIdentifierExtension (new AsnEncodedData (oid, raw_data), critical); break; case "2.5.29.15": newt = new X509KeyUsageExtension (new AsnEncodedData (oid, raw_data), critical); break; case "2.5.29.19": newt = new X509BasicConstraintsExtension (new AsnEncodedData (oid, raw_data), critical); break; case "2.5.29.37": newt = new X509EnhancedKeyUsageExtension (new AsnEncodedData (oid, raw_data), critical); break; } #else parameters [0] = new AsnEncodedData (oid, raw_data ?? Empty); parameters [1] = critical; newt = (X509Extension) CryptoConfig.CreateFromName (oid, parameters); #endif if (newt == null) { // not registred in CryptoConfig, using default newt = new X509Extension (oid, raw_data ?? Empty, critical); } _list.Add (newt); } }
public void WrongExtension_X509Extension () { X509Extension ex = new X509Extension ("1.2.3", new byte [0], true); X509KeyUsageExtension ku = new X509KeyUsageExtension (X509KeyUsageFlags.CrlSign, true); ku.CopyFrom (ex); Assert.IsTrue (ku.Critical, "Critical"); Assert.AreEqual (String.Empty, BitConverter.ToString (ku.RawData), "RawData"); Assert.AreEqual ("1.2.3", ku.Oid.Value, "Oid.Value"); Assert.IsNull (ku.Oid.FriendlyName, "Oid.FriendlyName"); }
public void ConstructorAsnEncodedData_BadAsnTag () { AsnEncodedData aed = new AsnEncodedData ("1.2.3", new byte[] { 0x05, 0x00 }); X509KeyUsageExtension ku = new X509KeyUsageExtension (aed, true); Assert.AreEqual ("0500", ku.Format (true), "Format(true)"); Assert.AreEqual ("0500", ku.Format (false), "Format(false)"); X509KeyUsageFlags kuf = ku.KeyUsages; }
internal static X509Certificate2 SelectSignerCertificate () { X509Store store = new X509Store(); store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly | OpenFlags.IncludeArchived); X509Certificate2Collection certificates = new X509Certificate2Collection(); foreach (X509Certificate2 certificate in store.Certificates) { if (certificate.HasPrivateKey && certificate.NotBefore <= DateTime.Now && certificate.NotAfter >= DateTime.Now) { bool validUsages = true; foreach (X509Extension extension in certificate.Extensions) { if (String.Compare(extension.Oid.Value, CAPI.szOID_KEY_USAGE, StringComparison.OrdinalIgnoreCase) == 0) { X509KeyUsageExtension keyUsage = new X509KeyUsageExtension(); keyUsage.CopyFrom(extension); if ((keyUsage.KeyUsages & X509KeyUsageFlags.DigitalSignature) == 0 && (keyUsage.KeyUsages & X509KeyUsageFlags.NonRepudiation) == 0) { validUsages = false; } break; } } if (validUsages) { certificates.Add(certificate); } } } if (certificates.Count < 1) throw new CryptographicException(CAPI.CRYPT_E_SIGNER_NOT_FOUND); certificates = X509Certificate2UI.SelectFromCollection(certificates, null, null, X509SelectionFlag.SingleSelection); if (certificates.Count < 1) throw new CryptographicException(CAPI.ERROR_CANCELLED); Debug.Assert(certificates.Count == 1); return certificates[0]; }
private static unsafe int VerifyCertificate (X509Certificate2 certificate, X509Certificate2Collection extraStore) { int dwErrorStatus; int hr = X509Utils.VerifyCertificate(X509Utils.GetCertContext(certificate), null, null, X509RevocationMode.Online, X509RevocationFlag.ExcludeRoot, DateTime.Now, new TimeSpan(0, 0, 0), extraStore, new IntPtr(CAPI.CERT_CHAIN_POLICY_BASE), new IntPtr(&dwErrorStatus)); if (hr != CAPI.S_OK) return dwErrorStatus; // Check key usages to make sure it is good for signing. foreach (X509Extension extension in certificate.Extensions) { if (String.Compare(extension.Oid.Value, CAPI.szOID_KEY_USAGE, StringComparison.OrdinalIgnoreCase) == 0) { X509KeyUsageExtension keyUsage = new X509KeyUsageExtension(); keyUsage.CopyFrom(extension); if ((keyUsage.KeyUsages & X509KeyUsageFlags.DigitalSignature) == 0 && (keyUsage.KeyUsages & X509KeyUsageFlags.NonRepudiation) == 0) { hr = CAPI.CERT_E_WRONG_USAGE; break; } } } return hr; }
public void CopyFrom_Null () { X509KeyUsageExtension eku = new X509KeyUsageExtension (); eku.CopyFrom (null); }
public X509KeyUsageExtensionWrapper(X509KeyUsageExtension extension) : base(extension) { x509 = extension; }
public void WrongExtension_X509KeyUsageExtension () { X509KeyUsageExtension ku = new X509KeyUsageExtension (); X509SubjectKeyIdentifierExtension ski = new X509SubjectKeyIdentifierExtension (); ski.CopyFrom (ku); }
internal static CmsRecipientCollection SelectRecipients(SubjectIdentifierType recipientIdentifierType) { X509Store store = new X509Store("AddressBook"); store.Open(OpenFlags.OpenExistingOnly); X509Certificate2Collection certificates = new X509Certificate2Collection(store.Certificates); X509Certificate2Enumerator enumerator = store.Certificates.GetEnumerator(); while (enumerator.MoveNext()) { X509Certificate2 current = enumerator.Current; if ((current.NotBefore <= DateTime.Now) && (current.NotAfter >= DateTime.Now)) { bool flag = true; X509ExtensionEnumerator enumerator2 = current.Extensions.GetEnumerator(); while (enumerator2.MoveNext()) { X509Extension asnEncodedData = enumerator2.Current; if (string.Compare(asnEncodedData.Oid.Value, "2.5.29.15", StringComparison.OrdinalIgnoreCase) == 0) { X509KeyUsageExtension extension2 = new X509KeyUsageExtension(); extension2.CopyFrom(asnEncodedData); if (((extension2.KeyUsages & X509KeyUsageFlags.KeyEncipherment) == X509KeyUsageFlags.None) && ((extension2.KeyUsages & X509KeyUsageFlags.KeyAgreement) == X509KeyUsageFlags.None)) { flag = false; } break; } } if (flag) { certificates.Add(current); } } } if (certificates.Count < 1) { throw new CryptographicException(-2146889717); } X509Certificate2Collection certificates2 = X509Certificate2UI.SelectFromCollection(certificates, null, null, X509SelectionFlag.MultiSelection); if (certificates2.Count < 1) { throw new CryptographicException(0x4c7); } return new CmsRecipientCollection(recipientIdentifierType, certificates2); }
private X509KeyUsageExtension ValidateKeyUsage (X509KeyUsageFlags kuf, string rawdata) { X509KeyUsageExtension ku = new X509KeyUsageExtension (kuf, false); Assert.IsFalse (ku.Critical, kuf.ToString () + ".Critical"); Assert.AreEqual (rawdata, BitConverter.ToString (ku.RawData), kuf.ToString () + ".RawData"); Assert.AreEqual (oid, ku.Oid.Value, kuf.ToString () + ".Oid.Value"); // FIXME: Don't expect that FriendlyName is English. This test fails under non-English Windows. //Assert.AreEqual (fname, ku.Oid.FriendlyName, kuf.ToString () + ".Oid.FriendlyName"); Assert.AreEqual (kuf, ku.KeyUsages, kuf.ToString () + ".KeyUsages"); return ku; }
// [ExpectedException (typeof (...))] public void ConstructorKeyUsage_Invalid () { X509KeyUsageFlags kuf = (X509KeyUsageFlags)Int32.MinValue; X509KeyUsageExtension ku = new X509KeyUsageExtension (kuf, false); Assert.AreEqual (0, (int)ku.KeyUsages, "KeyUsages"); Assert.AreEqual ("03-01-00", BitConverter.ToString (ku.RawData), "RawData"); // FIXME: Don't expect that FriendlyName is English. This test fails under non-English Windows. //Assert.AreEqual ("Information Not Available", ku.Format (true), "Format(true)"); //Assert.AreEqual ("Information Not Available", ku.Format (false), "Format(false)"); }
public void WrongExtension_X509Extension_KeyUsages () { X509Extension ex = new X509Extension ("1.2.3", new byte[0], true); X509KeyUsageExtension ku = new X509KeyUsageExtension (); ku.CopyFrom (ex); Assert.AreEqual (0, ku.KeyUsages, "KeyUsages"); }
private static unsafe int VerifyCertificate(X509Certificate2 certificate, X509Certificate2Collection extraStore) { int num1; int num2 = X509Utils.VerifyCertificate(X509Utils.GetCertContext(certificate), (OidCollection)null, (OidCollection)null, X509RevocationMode.Online, X509RevocationFlag.ExcludeRoot, DateTime.Now, new TimeSpan(0, 0, 0), extraStore, new IntPtr(1L), new IntPtr((void*)&num1)); if (num2 != 0) return num1; foreach (X509Extension x509Extension in certificate.Extensions) { if (string.Compare(x509Extension.Oid.Value, "2.5.29.15", StringComparison.OrdinalIgnoreCase) == 0) { X509KeyUsageExtension keyUsageExtension = new X509KeyUsageExtension(); keyUsageExtension.CopyFrom((AsnEncodedData)x509Extension); if ((keyUsageExtension.KeyUsages & X509KeyUsageFlags.DigitalSignature) == X509KeyUsageFlags.None && (keyUsageExtension.KeyUsages & X509KeyUsageFlags.NonRepudiation) == X509KeyUsageFlags.None) { num2 = -2146762480; break; } } } return num2; }
public void WrongAsnEncodedData () { AsnEncodedData aed = new AsnEncodedData (new byte[0]); X509KeyUsageExtension ku = new X509KeyUsageExtension (X509KeyUsageFlags.CrlSign, true); ku.CopyFrom (aed); // note: not the same behaviour than using the constructor! }
private static bool CheckCertificateUsage(System.Security.Cryptography.X509Certificates.X509Certificate2 cert) { bool result; try { if (cert.Version < 3) { result = true; } else { System.Security.Cryptography.X509Certificates.X509KeyUsageExtension x509KeyUsageExtension = (System.Security.Cryptography.X509Certificates.X509KeyUsageExtension)cert.Extensions["2.5.29.15"]; System.Security.Cryptography.X509Certificates.X509EnhancedKeyUsageExtension x509EnhancedKeyUsageExtension = (System.Security.Cryptography.X509Certificates.X509EnhancedKeyUsageExtension)cert.Extensions["2.5.29.37"]; if (x509KeyUsageExtension != null && x509EnhancedKeyUsageExtension != null) { if ((x509KeyUsageExtension.KeyUsages & ServicePointManager.ChainValidationHelper.s_flags) == System.Security.Cryptography.X509Certificates.X509KeyUsageFlags.None) { result = false; } else { result = (x509EnhancedKeyUsageExtension.EnhancedKeyUsages["1.3.6.1.5.5.7.3.1"] != null || x509EnhancedKeyUsageExtension.EnhancedKeyUsages["2.16.840.1.113730.4.1"] != null); } } else if (x509KeyUsageExtension != null) { result = ((x509KeyUsageExtension.KeyUsages & ServicePointManager.ChainValidationHelper.s_flags) != System.Security.Cryptography.X509Certificates.X509KeyUsageFlags.None); } else if (x509EnhancedKeyUsageExtension != null) { result = (x509EnhancedKeyUsageExtension.EnhancedKeyUsages["1.3.6.1.5.5.7.3.1"] != null || x509EnhancedKeyUsageExtension.EnhancedKeyUsages["2.16.840.1.113730.4.1"] != null); } else { System.Security.Cryptography.X509Certificates.X509Extension x509Extension = cert.Extensions["2.16.840.1.113730.1.1"]; if (x509Extension != null) { string text = x509Extension.NetscapeCertType(false); result = (text.IndexOf("SSL Server Authentication") != -1); } else { result = true; } } } } catch (Exception arg) { Console.Error.WriteLine("ERROR processing certificate: {0}", arg); Console.Error.WriteLine("Please, report this problem to the Mono team"); result = false; } return(result); }
public void CopyFrom_Self () { X509KeyUsageExtension ku = new X509KeyUsageExtension (X509KeyUsageFlags.CrlSign, true); Assert.IsTrue (ku.Critical, "Critical"); byte[] raw = ku.RawData; Assert.AreEqual ("03-02-01-02", BitConverter.ToString (raw), "RawData"); AsnEncodedData aed = new AsnEncodedData (raw); X509KeyUsageExtension copy = new X509KeyUsageExtension (aed, false); Assert.IsFalse (copy.Critical, "Critical"); Assert.AreEqual (4, copy.RawData.Length, "RawData"); // original Oid ignored Assert.AreEqual (oid, copy.Oid.Value, "Oid.Value"); Assert.AreEqual (fname, copy.Oid.FriendlyName, "Oid.FriendlyName"); Assert.AreEqual (X509KeyUsageFlags.CrlSign, copy.KeyUsages, "KeyUsages"); }
internal string KeyUsageExtension (bool multiLine) { try { X509KeyUsageExtension ku = new X509KeyUsageExtension (this, false); return ku.ToString (multiLine); } catch { return String.Empty; } }
[Category ("NotDotNet")] // MS bug reported as http://lab.msdn.microsoft.com/ProductFeedback/viewfeedback.aspx?feedbackid=34cdc5e9-c7f9-4f55-b390-288bfef6e44e public void ConstructorEmpty_KeyUsage () { X509KeyUsageExtension ku = new X509KeyUsageExtension (); Assert.AreEqual (0, (int)ku.KeyUsages, "KeyUsages"); }
private X509ChainStatusFlags CheckRevocation(X509Certificate2 certificate, X509Certificate2 ca_cert, bool online) { // change this if/when we support OCSP X509KeyUsageExtension kue = (ca_cert.Extensions["2.5.29.15"] as X509KeyUsageExtension); if (kue != null) { // ... verify CrlSign is set X509KeyUsageFlags success = X509KeyUsageFlags.CrlSign; if ((kue.KeyUsages & success) != success) { // FIXME - we should try to find an alternative CA that has the CrlSign bit return(X509ChainStatusFlags.RevocationStatusUnknown); } } MX.X509Crl crl = FindCrl(ca_cert); if ((crl == null) && online) { // FIXME - download and install new CRL // then you get a second chance // crl = FindCrl (ca_cert, ref valid, ref out_of_date); // We need to get the subjectAltName and an URI from there (or use OCSP) // X509KeyUsageExtension subjectAltName = (ca_cert.Extensions["2.5.29.17"] as X509KeyUsageExtension); } if (crl != null) { // validate the digital signature on the CRL using the CA public key // note #1: we can't use X509Crl.VerifySignature(X509Certificate) because it duplicates // checks and we loose the "why" of the failure // note #2: we do this before other tests as an invalid signature could be a hacked CRL // (so anything within can't be trusted) if (!crl.VerifySignature(ca_cert.PublicKey.Key)) { return(X509ChainStatusFlags.RevocationStatusUnknown); } MX.X509Crl.X509CrlEntry entry = crl.GetCrlEntry(certificate.MonoCertificate); if (entry != null) { // We have an entry for this CRL that includes an unknown CRITICAL extension // See [X.509 7.3] NOTE 4 if (!ProcessCrlEntryExtensions(entry)) { return(X509ChainStatusFlags.Revoked); } // FIXME - a little more is involved if (entry.RevocationDate <= ChainPolicy.VerificationTime) { return(X509ChainStatusFlags.Revoked); } } // are we overdue for a CRL update ? if so we can't be sure of any certificate status if (crl.NextUpdate < ChainPolicy.VerificationTime) { return(X509ChainStatusFlags.RevocationStatusUnknown | X509ChainStatusFlags.OfflineRevocation); } // we have a CRL that includes an unknown CRITICAL extension // we put this check at the end so we do not "hide" any Revoked flags if (!ProcessCrlExtensions(crl)) { return(X509ChainStatusFlags.RevocationStatusUnknown); } } else { return(X509ChainStatusFlags.RevocationStatusUnknown); } return(X509ChainStatusFlags.NoError); }
internal static CmsRecipientCollection SelectRecipients (SubjectIdentifierType recipientIdentifierType) { X509Store store = new X509Store("AddressBook"); store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly); X509Certificate2Collection certificates = new X509Certificate2Collection(store.Certificates); foreach (X509Certificate2 certificate in store.Certificates) { if (certificate.NotBefore <= DateTime.Now && certificate.NotAfter >= DateTime.Now) { bool validUsages = true; foreach (X509Extension extension in certificate.Extensions) { if (String.Compare(extension.Oid.Value, CAPI.szOID_KEY_USAGE, StringComparison.OrdinalIgnoreCase) == 0) { X509KeyUsageExtension keyUsage = new X509KeyUsageExtension(); keyUsage.CopyFrom(extension); if ((keyUsage.KeyUsages & X509KeyUsageFlags.KeyEncipherment) == 0 && (keyUsage.KeyUsages & X509KeyUsageFlags.KeyAgreement) == 0) { validUsages = false; } break; } } if (validUsages) { certificates.Add(certificate); } } } if (certificates.Count < 1) throw new CryptographicException(CAPI.CRYPT_E_RECIPIENT_NOT_FOUND); X509Certificate2Collection recipients = X509Certificate2UI.SelectFromCollection(certificates, null, null, X509SelectionFlag.MultiSelection); if (recipients.Count < 1) throw new CryptographicException(CAPI.ERROR_CANCELLED); return new CmsRecipientCollection(recipientIdentifierType, recipients); }
public bool CheckSignature(X509Certificate2 certificate, bool verifySignatureOnly) { if (!this.CheckSignature(certificate.PublicKey.Key)) { return false; } if (verifySignatureOnly) { SignedXmlDebugLog.LogVerificationResult(this, certificate, true); return true; } X509ExtensionEnumerator enumerator = certificate.Extensions.GetEnumerator(); while (enumerator.MoveNext()) { X509Extension current = enumerator.Current; if (string.Compare(current.Oid.Value, "2.5.29.15", StringComparison.OrdinalIgnoreCase) == 0) { X509KeyUsageExtension keyUsages = new X509KeyUsageExtension(); keyUsages.CopyFrom(current); SignedXmlDebugLog.LogVerifyKeyUsage(this, certificate, keyUsages); if (((keyUsages.KeyUsages & X509KeyUsageFlags.DigitalSignature) != X509KeyUsageFlags.None) || ((keyUsages.KeyUsages & X509KeyUsageFlags.NonRepudiation) != X509KeyUsageFlags.None)) { break; } SignedXmlDebugLog.LogVerificationFailure(this, SecurityResources.GetResourceString("Log_VerificationFailed_X509KeyUsage")); return false; } } X509Chain chain = new X509Chain(); chain.ChainPolicy.ExtraStore.AddRange(this.BuildBagOfCerts()); bool flag2 = chain.Build(certificate); SignedXmlDebugLog.LogVerifyX509Chain(this, chain, certificate); if (!flag2) { SignedXmlDebugLog.LogVerificationFailure(this, SecurityResources.GetResourceString("Log_VerificationFailed_X509Chain")); return false; } SignedXmlDebugLog.LogVerificationResult(this, certificate, true); return true; }
/// <summary> /// Check that the KeyUsageExtension is DigitalSignature. /// </summary> /// <param name="SOD"></param> /// <param name="keyUsageStr"></param> /// <returns></returns> public static bool KeyUsageIsDigitalSignatureOnly(X509Certificate2 SOD) { bool keyUsageIsDigitalSignatureFound = false; foreach (var extension in SOD.Extensions) { if (extension is System.Security.Cryptography.X509Certificates.X509KeyUsageExtension) { System.Security.Cryptography.X509Certificates.X509KeyUsageExtension keyUsage = extension as System.Security.Cryptography.X509Certificates.X509KeyUsageExtension; if (string.Compare(keyUsage.KeyUsages.ToString().ToUpper(), "DIGITALSIGNATURE") != 0) { // KeyUsage found that is not DigitalSignature return(false); } else { // DigitalSignature found.... if (!keyUsage.Critical) { // ....but not critical return(false); } else { // ... and critical keyUsageIsDigitalSignatureFound = true; } } } } return(keyUsageIsDigitalSignatureFound); }
internal static X509Certificate2 SelectSignerCertificate() { X509Store store = new X509Store(); store.Open(OpenFlags.IncludeArchived | OpenFlags.OpenExistingOnly); X509Certificate2Collection certificates = new X509Certificate2Collection(); X509Certificate2Enumerator enumerator = store.Certificates.GetEnumerator(); while (enumerator.MoveNext()) { X509Certificate2 current = enumerator.Current; if ((current.HasPrivateKey && (current.NotBefore <= DateTime.Now)) && (current.NotAfter >= DateTime.Now)) { bool flag = true; X509ExtensionEnumerator enumerator2 = current.Extensions.GetEnumerator(); while (enumerator2.MoveNext()) { X509Extension asnEncodedData = enumerator2.Current; if (string.Compare(asnEncodedData.Oid.Value, "2.5.29.15", StringComparison.OrdinalIgnoreCase) == 0) { X509KeyUsageExtension extension2 = new X509KeyUsageExtension(); extension2.CopyFrom(asnEncodedData); if (((extension2.KeyUsages & X509KeyUsageFlags.DigitalSignature) == X509KeyUsageFlags.None) && ((extension2.KeyUsages & X509KeyUsageFlags.NonRepudiation) == X509KeyUsageFlags.None)) { flag = false; } break; } } if (flag) { certificates.Add(current); } } } if (certificates.Count < 1) { throw new CryptographicException(-2146889714); } certificates = X509Certificate2UI.SelectFromCollection(certificates, null, null, X509SelectionFlag.SingleSelection); if (certificates.Count < 1) { throw new CryptographicException(0x4c7); } return certificates[0]; }
public X509Certificate2Collection Find(X509FindType findType, object findValue, bool validOnly) { if (findValue == null) { throw new ArgumentNullException("findValue"); } string text = string.Empty; string text2 = string.Empty; X509KeyUsageFlags x509KeyUsageFlags = X509KeyUsageFlags.None; DateTime t = DateTime.MinValue; switch (findType) { case X509FindType.FindByThumbprint: case X509FindType.FindBySubjectName: case X509FindType.FindBySubjectDistinguishedName: case X509FindType.FindByIssuerName: case X509FindType.FindByIssuerDistinguishedName: case X509FindType.FindBySerialNumber: case X509FindType.FindByTemplateName: case X509FindType.FindBySubjectKeyIdentifier: try { text = (string)findValue; } catch (Exception inner) { string text3 = Locale.GetText("Invalid find value type '{0}', expected '{1}'.", new object[] { findValue.GetType(), "string" }); throw new CryptographicException(text3, inner); } break; case X509FindType.FindByTimeValid: case X509FindType.FindByTimeNotYetValid: case X509FindType.FindByTimeExpired: try { t = (DateTime)findValue; } catch (Exception inner2) { string text4 = Locale.GetText("Invalid find value type '{0}', expected '{1}'.", new object[] { findValue.GetType(), "X509DateTime" }); throw new CryptographicException(text4, inner2); } break; case X509FindType.FindByApplicationPolicy: case X509FindType.FindByCertificatePolicy: case X509FindType.FindByExtension: try { text2 = (string)findValue; } catch (Exception inner3) { string text5 = Locale.GetText("Invalid find value type '{0}', expected '{1}'.", new object[] { findValue.GetType(), "X509KeyUsageFlags" }); throw new CryptographicException(text5, inner3); } try { CryptoConfig.EncodeOID(text2); } catch (CryptographicUnexpectedOperationException) { string text6 = Locale.GetText("Invalid OID value '{0}'.", new object[] { text2 }); throw new ArgumentException("findValue", text6); } break; case X509FindType.FindByKeyUsage: try { x509KeyUsageFlags = (X509KeyUsageFlags)((int)findValue); } catch (Exception inner4) { string text7 = Locale.GetText("Invalid find value type '{0}', expected '{1}'.", new object[] { findValue.GetType(), "X509KeyUsageFlags" }); throw new CryptographicException(text7, inner4); } break; default: { string text8 = Locale.GetText("Invalid find type '{0}'.", new object[] { findType }); throw new CryptographicException(text8); } } CultureInfo invariantCulture = CultureInfo.InvariantCulture; X509Certificate2Collection x509Certificate2Collection = new X509Certificate2Collection(); foreach (object obj in base.InnerList) { X509Certificate2 x509Certificate = (X509Certificate2)obj; bool flag = false; switch (findType) { case X509FindType.FindByThumbprint: flag = (string.Compare(text, x509Certificate.Thumbprint, true, invariantCulture) == 0 || string.Compare(text, x509Certificate.GetCertHashString(), true, invariantCulture) == 0); break; case X509FindType.FindBySubjectName: { string nameInfo = x509Certificate.GetNameInfo(X509NameType.SimpleName, false); flag = (nameInfo.IndexOf(text, StringComparison.InvariantCultureIgnoreCase) >= 0); break; } case X509FindType.FindBySubjectDistinguishedName: flag = (string.Compare(text, x509Certificate.Subject, true, invariantCulture) == 0); break; case X509FindType.FindByIssuerName: { string nameInfo2 = x509Certificate.GetNameInfo(X509NameType.SimpleName, true); flag = (nameInfo2.IndexOf(text, StringComparison.InvariantCultureIgnoreCase) >= 0); break; } case X509FindType.FindByIssuerDistinguishedName: flag = (string.Compare(text, x509Certificate.Issuer, true, invariantCulture) == 0); break; case X509FindType.FindBySerialNumber: flag = (string.Compare(text, x509Certificate.SerialNumber, true, invariantCulture) == 0); break; case X509FindType.FindByTimeValid: flag = (t >= x509Certificate.NotBefore && t <= x509Certificate.NotAfter); break; case X509FindType.FindByTimeNotYetValid: flag = (t < x509Certificate.NotBefore); break; case X509FindType.FindByTimeExpired: flag = (t > x509Certificate.NotAfter); break; case X509FindType.FindByApplicationPolicy: flag = (x509Certificate.Extensions.Count == 0); break; case X509FindType.FindByExtension: flag = (x509Certificate.Extensions[text2] != null); break; case X509FindType.FindByKeyUsage: { X509KeyUsageExtension x509KeyUsageExtension = x509Certificate.Extensions["2.5.29.15"] as X509KeyUsageExtension; flag = (x509KeyUsageExtension == null || (x509KeyUsageExtension.KeyUsages & x509KeyUsageFlags) == x509KeyUsageFlags); break; } case X509FindType.FindBySubjectKeyIdentifier: { X509SubjectKeyIdentifierExtension x509SubjectKeyIdentifierExtension = x509Certificate.Extensions["2.5.29.14"] as X509SubjectKeyIdentifierExtension; if (x509SubjectKeyIdentifierExtension != null) { flag = (string.Compare(text, x509SubjectKeyIdentifierExtension.SubjectKeyIdentifier, true, invariantCulture) == 0); } break; } } if (flag) { if (validOnly) { try { if (x509Certificate.Verify()) { x509Certificate2Collection.Add(x509Certificate); } } catch { } } else { x509Certificate2Collection.Add(x509Certificate); } } } return(x509Certificate2Collection); }
public void WrongExtension_X509KeyUsageExtension () { X509KeyUsageExtension ku = new X509KeyUsageExtension (); X509BasicConstraintsExtension bc = new X509BasicConstraintsExtension (); bc.CopyFrom (ku); }
public X509Certificate2Collection Find(X509FindType findType, object findValue, bool validOnly) { if (findValue == null) { throw new ArgumentNullException("findValue"); } string str = String.Empty; string oid = String.Empty; X509KeyUsageFlags ku = X509KeyUsageFlags.None; DateTime dt = DateTime.MinValue; switch (findType) { case X509FindType.FindByThumbprint: case X509FindType.FindBySubjectName: case X509FindType.FindBySubjectDistinguishedName: case X509FindType.FindByIssuerName: case X509FindType.FindByIssuerDistinguishedName: case X509FindType.FindBySerialNumber: case X509FindType.FindByTemplateName: case X509FindType.FindBySubjectKeyIdentifier: try { str = (string)findValue; } catch (Exception e) { string msg = Locale.GetText("Invalid find value type '{0}', expected '{1}'.", findValue.GetType(), "string"); throw new CryptographicException(msg, e); } break; case X509FindType.FindByApplicationPolicy: case X509FindType.FindByCertificatePolicy: case X509FindType.FindByExtension: try { oid = (string)findValue; } catch (Exception e) { string msg = Locale.GetText("Invalid find value type '{0}', expected '{1}'.", findValue.GetType(), "X509KeyUsageFlags"); throw new CryptographicException(msg, e); } // OID validation try { CryptoConfig.EncodeOID(oid); } catch (CryptographicUnexpectedOperationException) { string msg = Locale.GetText("Invalid OID value '{0}'.", oid); throw new ArgumentException("findValue", msg); } break; case X509FindType.FindByKeyUsage: try { ku = (X509KeyUsageFlags)findValue; } catch (Exception e) { string msg = Locale.GetText("Invalid find value type '{0}', expected '{1}'.", findValue.GetType(), "X509KeyUsageFlags"); throw new CryptographicException(msg, e); } break; case X509FindType.FindByTimeValid: case X509FindType.FindByTimeNotYetValid: case X509FindType.FindByTimeExpired: try { dt = (DateTime)findValue; } catch (Exception e) { string msg = Locale.GetText("Invalid find value type '{0}', expected '{1}'.", findValue.GetType(), "X509DateTime"); throw new CryptographicException(msg, e); } break; default: { string msg = Locale.GetText("Invalid find type '{0}'.", findType); throw new CryptographicException(msg); } } CultureInfo cinv = CultureInfo.InvariantCulture; X509Certificate2Collection results = new X509Certificate2Collection(); foreach (X509Certificate2 x in InnerList) { bool value_match = false; switch (findType) { case X509FindType.FindByThumbprint: // works with Thumbprint, GetCertHashString in both normal (upper) and lower case value_match = ((String.Compare(str, x.Thumbprint, true, cinv) == 0) || (String.Compare(str, x.GetCertHashString(), true, cinv) == 0)); break; case X509FindType.FindBySubjectName: string [] names = x.SubjectName.Format(true).Split(newline_split, StringSplitOptions.RemoveEmptyEntries); foreach (string name in names) { int pos = name.IndexOf('='); value_match = (name.IndexOf(str, pos, StringComparison.InvariantCultureIgnoreCase) >= 0); if (value_match) { break; } } break; case X509FindType.FindBySubjectDistinguishedName: value_match = (String.Compare(str, x.Subject, true, cinv) == 0); break; case X509FindType.FindByIssuerName: string iname = x.GetNameInfo(X509NameType.SimpleName, true); value_match = (iname.IndexOf(str, StringComparison.InvariantCultureIgnoreCase) >= 0); break; case X509FindType.FindByIssuerDistinguishedName: value_match = (String.Compare(str, x.Issuer, true, cinv) == 0); break; case X509FindType.FindBySerialNumber: value_match = (String.Compare(str, x.SerialNumber, true, cinv) == 0); break; case X509FindType.FindByTemplateName: // TODO - find a valid test case break; case X509FindType.FindBySubjectKeyIdentifier: value_match = (String.Compare(str, GetKeyIdentifier(x), true, cinv) == 0); break; case X509FindType.FindByApplicationPolicy: // note: include when no extensions are present (even if v3) value_match = (x.Extensions.Count == 0); // TODO - find test case with extension break; case X509FindType.FindByCertificatePolicy: // TODO - find test case with extension break; case X509FindType.FindByExtension: value_match = (x.Extensions [oid] != null); break; case X509FindType.FindByKeyUsage: X509KeyUsageExtension kue = (x.Extensions ["2.5.29.15"] as X509KeyUsageExtension); if (kue == null) { // key doesn't have any hard coded limitations // note: MS doesn't check for ExtendedKeyUsage value_match = true; } else { value_match = ((kue.KeyUsages & ku) == ku); } break; case X509FindType.FindByTimeValid: value_match = ((dt >= x.NotBefore) && (dt <= x.NotAfter)); break; case X509FindType.FindByTimeNotYetValid: value_match = (dt < x.NotBefore); break; case X509FindType.FindByTimeExpired: value_match = (dt > x.NotAfter); break; } if (!value_match) { continue; } if (validOnly) { try { if (x.Verify()) { results.Add(x); } } catch { } } else { results.Add(x); } } return(results); }
public void ConstructorAsnEncodedData_Null () { X509KeyUsageExtension ku = new X509KeyUsageExtension (null, true); }
// CTL == Certificate Trust List / NOT SUPPORTED // TODO - check for X509ChainStatusFlags.CtlNotTimeValid // TODO - check for X509ChainStatusFlags.CtlNotSignatureValid // TODO - check for X509ChainStatusFlags.CtlNotValidForUsage private void PrepareForNextCertificate(int n) { X509ChainElement element = elements [n]; X509Certificate2 certificate = element.Certificate; // TODO 6.1.4.a-b // 6.1.4.c working_issuer_name = certificate.SubjectName; // 6.1.4.d-e - our key includes both the public key and it's parameters working_public_key = certificate.PublicKey.Key; // 6.1.4.f // working_public_key_algorithm = certificate.PublicKey.Oid.Value; // TODO 6.1.4.g-j // 6.1.4.k - Verify that the certificate is a CA certificate X509BasicConstraintsExtension bce = (certificate.Extensions["2.5.29.19"] as X509BasicConstraintsExtension); if (bce != null) { if (!bce.CertificateAuthority) { element.StatusFlags |= X509ChainStatusFlags.InvalidBasicConstraints; } } else if (certificate.Version >= 3) { // recent (v3+) CA certificates must include BCE element.StatusFlags |= X509ChainStatusFlags.InvalidBasicConstraints; } // 6.1.4.l - if the certificate isn't self-issued... if (!IsSelfIssued(certificate)) { // ... verify that max_path_length > 0 if (max_path_length > 0) { max_path_length--; } else { // to match MS the reported status must be against the certificate // with the BCE and not where the path is too long. It also means // that this condition has to be reported only once if (bce_restriction != null) { bce_restriction.StatusFlags |= X509ChainStatusFlags.InvalidBasicConstraints; } } } // 6.1.4.m - if pathLengthConstraint is present... if ((bce != null) && (bce.HasPathLengthConstraint)) { // ... and is less that max_path_length, set max_path_length to it's value if (bce.PathLengthConstraint < max_path_length) { max_path_length = bce.PathLengthConstraint; bce_restriction = element; } } // 6.1.4.n - if key usage extension is present... X509KeyUsageExtension kue = (certificate.Extensions["2.5.29.15"] as X509KeyUsageExtension); if (kue != null) { // ... verify keyCertSign is set X509KeyUsageFlags success = X509KeyUsageFlags.KeyCertSign; if ((kue.KeyUsages & success) != success) { element.StatusFlags |= X509ChainStatusFlags.NotValidForUsage; } } // 6.1.4.o - recognize and process other critical extension present in the certificate ProcessCertificateExtensions(element); }
// [ExpectedException (typeof (...))] public void ConstructorKeyUsage_Invalid () { X509KeyUsageFlags kuf = (X509KeyUsageFlags)Int32.MinValue; X509KeyUsageExtension ku = new X509KeyUsageExtension (kuf, false); Assert.AreEqual (0, (int)ku.KeyUsages, "KeyUsages"); Assert.AreEqual ("03-01-00", BitConverter.ToString (ku.RawData), "RawData"); Assert.AreEqual ("Information Not Available", ku.Format (true), "Format(true)"); Assert.AreEqual ("Information Not Available", ku.Format (false), "Format(false)"); }
private static unsafe int VerifyCertificate(X509Certificate2 certificate, X509Certificate2Collection extraStore) { int num; int num2 = System.Security.Cryptography.X509Certificates.X509Utils.VerifyCertificate(System.Security.Cryptography.X509Certificates.X509Utils.GetCertContext(certificate), null, null, X509RevocationMode.Online, X509RevocationFlag.ExcludeRoot, DateTime.Now, new TimeSpan(0, 0, 0), extraStore, new IntPtr(1L), new IntPtr((void*) &num)); if (num2 != 0) { return num; } X509ExtensionEnumerator enumerator = certificate.Extensions.GetEnumerator(); while (enumerator.MoveNext()) { X509Extension current = enumerator.Current; if (string.Compare(current.Oid.Value, "2.5.29.15", StringComparison.OrdinalIgnoreCase) == 0) { X509KeyUsageExtension extension2 = new X509KeyUsageExtension(); extension2.CopyFrom(current); if (((extension2.KeyUsages & X509KeyUsageFlags.DigitalSignature) == X509KeyUsageFlags.None) && ((extension2.KeyUsages & X509KeyUsageFlags.NonRepudiation) == X509KeyUsageFlags.None)) { return -2146762480; } } } return num2; }
private X509KeyUsageExtension ValidateKeyUsage (X509KeyUsageFlags kuf, string rawdata) { X509KeyUsageExtension ku = new X509KeyUsageExtension (kuf, false); Assert.IsFalse (ku.Critical, kuf.ToString () + ".Critical"); Assert.AreEqual (rawdata, BitConverter.ToString (ku.RawData), kuf.ToString () + ".RawData"); Assert.AreEqual (oid, ku.Oid.Value, kuf.ToString () + ".Oid.Value"); Assert.AreEqual (fname, ku.Oid.FriendlyName, kuf.ToString () + ".Oid.FriendlyName"); Assert.AreEqual (kuf, ku.KeyUsages, kuf.ToString () + ".KeyUsages"); return ku; }
public void WrongExtension_X509EnhancedKeyUsageExtension () { X509EnhancedKeyUsageExtension eku = new X509EnhancedKeyUsageExtension (); X509KeyUsageExtension ku = new X509KeyUsageExtension (); ku.CopyFrom (eku); }
/// <summary> /// Applies the basic constrains and key usages to the underlying certificate builder /// before the certificate is signed. /// </summary> void PrepareSigning() { // Set the signing hashing function _builder.Hash = "SHA256"; // Clear all extensions created during the previous preparation _builder.Extensions.Clear(); #region Subject if (SubjectAlternativeNames != null && SubjectAlternativeNames.Count > 0) { var dnsNameList = new List <string>(); var ipList = new List <string>(); foreach (var item in SubjectAlternativeNames) { IPAddress ipAddress; if (IPAddress.TryParse(item, out ipAddress)) { ipList.Add(item); } else { dnsNameList.Add(item); } } var extension = new SubjectAltNameExtension(null, dnsNameList.ToArray(), ipList.ToArray(), null); _builder.Extensions.Add(extension); } #endregion #region Serial number { var serialNumber = _serialNumber == null ? null : (byte[])_serialNumber.Clone(); if (serialNumber == null) { serialNumber = Guid.NewGuid().ToByteArray(); } /* // The serial number is correctly set and must NOT be reversed * // Convert the serial number to big endian format * Array.Reverse(serialNumber); */ _builder.SerialNumber = serialNumber; } #endregion #region Basic key usages var keyUsages = KeyUsages; if (IsCertificateAuthority) { // Indicate that the public key of the certificate can be used to validate the signatures of // other certificates keyUsages |= BasicKeyUsages.KeyCertSign; var extension = new BasicConstraintsExtension() { CertificateAuthority = true, PathLenConstraint = CertificateAuthorityPathLength, // This extension must be critical Critical = true, }; _builder.Extensions.Add(extension); } else { keyUsages &= ~BasicKeyUsages.KeyCertSign; } if (keyUsages != BasicKeyUsages.None) { #if MONO_BUG // There was a bug in the Mono implementation of the KeyUsageExtension // which is still NOT fixed var buffer = new System.Security.Cryptography.X509Certificates.X509KeyUsageExtension( (System.Security.Cryptography.X509Certificates.X509KeyUsageFlags)keyUsages, false ).RawData; var asn = new ASN1(0x30, buffer); asn.Add(ASN1Convert.FromOid("2.5.29.15")); asn.Add(new ASN1(4, buffer)); _builder.Extensions.Add(new X509Extension(asn) { Critical = KeyUsagesCritical }); #else // This code should be used once the bug is fixed var extension = new KeyUsageExtension() { KeyUsage = (KeyUsages)keyUsages, Critical = KeyUsagesCritical, }; _builder.Extensions.Add(extension); #endif } #endregion #region Extended key usage if (ExtendedKeyUsages != null && ExtendedKeyUsages.Count > 0) { var extension = new ExtendedKeyUsageExtension(); extension.Critical = ExtendedKeyUsagesCritical; foreach (var item in ExtendedKeyUsages) { // Avoid dupliated key usages if (false == extension.KeyPurpose.Contains(item)) { extension.KeyPurpose.Add(item); } } _builder.Extensions.Add(extension); } #endregion #region Custom extensions if (_extensions != null) { _builder.Extensions.AddRange(_extensions); } #endregion }