bool KeyUsage(MSX.PKCS12 pfx) { foreach (MSX.X509Certificate cert in pfx.Certificates) { MSX.X509Extension xtn = cert.Extensions ["2.5.29.15"]; if (xtn == null) { continue; } var ku = new KeyUsageExtension(xtn); if (!ku.Support(KeyUsages.digitalSignature) && !ku.Support(KeyUsages.keyEncipherment)) { continue; } key = GetKeyMatchingCertificate(pfx, cert); if (key == null) { continue; } x509 = new X509Certificate(cert.RawData); break; } // complete ? return((x509 != null) && (key != null)); }
public void Constructor_ASN1() { KeyUsageExtension ext = new KeyUsageExtension(); KeyUsageExtension kue = new KeyUsageExtension(ext.ASN1); Empty(kue); }
public void Critical() { KeyUsageExtension kue = new KeyUsageExtension(); kue.Critical = true; foreach (KeyUsages ku in Enum.GetValues(typeof(KeyUsages))) { kue.KeyUsage = ku; byte[] rawext = kue.GetBytes(); int length = 16; if ((int)ku > Byte.MaxValue) { length++; Assert.AreEqual((byte)ku, rawext[rawext.Length - 2], ku.ToString() + ".Value2"); Assert.AreEqual((byte)((int)ku >> 8), rawext[rawext.Length - 1], ku.ToString() + ".Value1"); } else { Assert.AreEqual((byte)ku, rawext[rawext.Length - 1], ku.ToString() + ".Value"); } Assert.AreEqual(length, rawext.Length, ku.ToString() + ".Length"); Assert.AreEqual(1, rawext[7], ku.ToString() + ".Critical.Tag"); Assert.AreEqual(1, rawext[8], ku.ToString() + ".Critical.Length"); Assert.AreEqual(255, rawext[9], ku.ToString() + ".Critical.Value"); } }
private bool checkCertificateUsage(Mono.Security.X509.X509Certificate cert) { ClientContext clientContext = (ClientContext)base.Context; if (cert.Version < 3) { return(true); } KeyUsages usage = KeyUsages.none; switch (clientContext.Negotiating.Cipher.ExchangeAlgorithmType) { case ExchangeAlgorithmType.DiffieHellman: usage = KeyUsages.keyAgreement; break; case ExchangeAlgorithmType.Fortezza: return(false); case ExchangeAlgorithmType.RsaKeyX: usage = KeyUsages.keyEncipherment; break; case ExchangeAlgorithmType.RsaSign: usage = KeyUsages.digitalSignature; break; } KeyUsageExtension keyUsageExtension = null; ExtendedKeyUsageExtension extendedKeyUsageExtension = null; Mono.Security.X509.X509Extension x509Extension = cert.Extensions["2.5.29.15"]; if (x509Extension != null) { keyUsageExtension = new KeyUsageExtension(x509Extension); } x509Extension = cert.Extensions["2.5.29.37"]; if (x509Extension != null) { extendedKeyUsageExtension = new ExtendedKeyUsageExtension(x509Extension); } if (keyUsageExtension != null && extendedKeyUsageExtension != null) { return(keyUsageExtension.Support(usage) && (extendedKeyUsageExtension.KeyPurpose.Contains("1.3.6.1.5.5.7.3.1") || extendedKeyUsageExtension.KeyPurpose.Contains("2.16.840.1.113730.4.1"))); } if (keyUsageExtension != null) { return(keyUsageExtension.Support(usage)); } if (extendedKeyUsageExtension != null) { return(extendedKeyUsageExtension.KeyPurpose.Contains("1.3.6.1.5.5.7.3.1") || extendedKeyUsageExtension.KeyPurpose.Contains("2.16.840.1.113730.4.1")); } x509Extension = cert.Extensions["2.16.840.1.113730.1.1"]; if (x509Extension != null) { NetscapeCertTypeExtension netscapeCertTypeExtension = new NetscapeCertTypeExtension(x509Extension); return(netscapeCertTypeExtension.Support(NetscapeCertTypeExtension.CertTypes.SslServer)); } return(true); }
private bool checkCertificateUsage(Mono.Security.X509.X509Certificate cert) { ClientContext context = (ClientContext)this.Context; if (cert.Version < 3) { return(true); } KeyUsages usage = KeyUsages.none; switch (context.Negotiating.Cipher.ExchangeAlgorithmType) { case ExchangeAlgorithmType.DiffieHellman: usage = KeyUsages.keyAgreement; break; case ExchangeAlgorithmType.Fortezza: return(false); case ExchangeAlgorithmType.RsaKeyX: usage = KeyUsages.keyEncipherment; break; case ExchangeAlgorithmType.RsaSign: usage = KeyUsages.digitalSignature; break; } KeyUsageExtension keyUsageExtension1 = (KeyUsageExtension)null; ExtendedKeyUsageExtension keyUsageExtension2 = (ExtendedKeyUsageExtension)null; Mono.Security.X509.X509Extension extension1 = cert.Extensions["2.5.29.15"]; if (extension1 != null) { keyUsageExtension1 = new KeyUsageExtension(extension1); } Mono.Security.X509.X509Extension extension2 = cert.Extensions["2.5.29.37"]; if (extension2 != null) { keyUsageExtension2 = new ExtendedKeyUsageExtension(extension2); } if (keyUsageExtension1 != null && keyUsageExtension2 != null) { if (!keyUsageExtension1.Support(usage)) { return(false); } return(keyUsageExtension2.KeyPurpose.Contains((object)"1.3.6.1.5.5.7.3.1") || keyUsageExtension2.KeyPurpose.Contains((object)"2.16.840.1.113730.4.1")); } if (keyUsageExtension1 != null) { return(keyUsageExtension1.Support(usage)); } if (keyUsageExtension2 != null) { return(keyUsageExtension2.KeyPurpose.Contains((object)"1.3.6.1.5.5.7.3.1") || keyUsageExtension2.KeyPurpose.Contains((object)"2.16.840.1.113730.4.1")); } Mono.Security.X509.X509Extension extension3 = cert.Extensions["2.16.840.1.113730.1.1"]; return(extension3 == null || new NetscapeCertTypeExtension(extension3).Support(NetscapeCertTypeExtension.CertTypes.SslServer)); }
public bool VerifySignature(X509Certificate x509) { if (x509 == null) { throw new ArgumentNullException("x509"); } if (x509.Version >= 3) { X509Extension x509Extension = x509.Extensions["2.5.29.15"]; if (x509Extension != null) { KeyUsageExtension keyUsageExtension = new KeyUsageExtension(x509Extension); if (!keyUsageExtension.Support(KeyUsages.cRLSign)) { return(false); } } x509Extension = x509.Extensions["2.5.29.19"]; if (x509Extension != null) { BasicConstraintsExtension basicConstraintsExtension = new BasicConstraintsExtension(x509Extension); if (!basicConstraintsExtension.CertificateAuthority) { return(false); } } } if (this.issuer != x509.SubjectName) { return(false); } string text = this.signatureOID; if (text != null) { if (X509Crl.< > f__switch$map11 == null) { X509Crl.< > f__switch$map11 = new Dictionary <string, int>(1) { { "1.2.840.10040.4.3", 0 } }; } int num; if (X509Crl.< > f__switch$map11.TryGetValue(text, out num)) { if (num == 0) { return(this.VerifySignature(x509.DSA)); } } } return(this.VerifySignature(x509.RSA)); }
private void Empty(KeyUsageExtension kue) { Assert.IsFalse(kue.Critical, "Critical"); Assert.AreEqual("2.5.29.15", kue.Oid, "Oid"); Assert.IsNotNull(kue.Name, "Name"); Assert.IsFalse(kue.Name == kue.Oid, "Name!=Oid"); Assert.AreEqual(KeyUsages.none, kue.KeyUsage, "KeyUsage"); Assert.IsTrue(kue.Support(KeyUsages.none), "Support(none)"); Assert.IsFalse(kue.Support(KeyUsages.digitalSignature), "Support(digitalSignature)"); Assert.IsFalse(kue.Support(KeyUsages.decipherOnly), "Support(decipherOnly)"); }
public bool VerifySignature(X509Certificate x509) { if (x509 == null) { throw new ArgumentNullException("x509"); } if (x509.Version >= 3) { X509Extension extension = x509.Extensions["2.5.29.15"]; if (extension != null) { KeyUsageExtension extension2 = new KeyUsageExtension(extension); if (!extension2.Support(KeyUsages.cRLSign)) { return(false); } } extension = x509.Extensions["2.5.29.19"]; if (extension != null) { BasicConstraintsExtension extension3 = new BasicConstraintsExtension(extension); if (!extension3.CertificateAuthority) { return(false); } } } if (this.issuer != x509.SubjectName) { return(false); } string signatureOID = this.signatureOID; if (signatureOID != null) { if (__f__switch_map12 == null) { Dictionary <string, int> dictionary = new Dictionary <string, int>(1) { { "1.2.840.10040.4.3", 0 } }; __f__switch_map12 = dictionary; } if (__f__switch_map12.TryGetValue(signatureOID, out int num) && (num == 0)) { return(this.VerifySignature(x509.DSA)); } } return(this.VerifySignature(x509.RSA)); }
public bool VerifySignature(X509Certificate x509) { if (x509 == null) { throw new ArgumentNullException("x509"); } // 1. x509 certificate must be a CA certificate (unknown for v1 or v2 certs) if (x509.Version >= 3) { BasicConstraintsExtension basicConstraints = null; // 1.2. Check for ca = true in BasicConstraint X509Extension ext = x509.Extensions ["2.5.29.19"]; if (ext != null) { basicConstraints = new BasicConstraintsExtension(ext); if (!basicConstraints.CertificateAuthority) { return(false); } } // 1.1. Check for "cRLSign" bit in KeyUsage extension ext = x509.Extensions ["2.5.29.15"]; if (ext != null) { KeyUsageExtension keyUsage = new KeyUsageExtension(ext); if (!keyUsage.Support(KeyUsages.cRLSign)) { // 2nd chance if basicConstraints is CertificateAuthority // and KeyUsage support digitalSignature if ((basicConstraints == null) || !keyUsage.Support(KeyUsages.digitalSignature)) { return(false); } } } } // 2. CRL issuer must match CA subject name if (issuer != x509.SubjectName) { return(false); } // 3. Check the CRL signature with the CA certificate public key switch (signatureOID) { case "1.2.840.10040.4.3": return(VerifySignature(x509.DSA)); default: return(VerifySignature(x509.RSA)); } }
private bool CheckClientCertificateExtensions(X509Certificate cert) { KeyUsages ku = KeyUsages.digitalSignature | KeyUsages.keyEncipherment | KeyUsages.keyAgreement; KeyUsageExtension kux = null; ExtendedKeyUsageExtension eku = null; X509Extension xtn = cert.Extensions["2.5.29.15"]; if (xtn != null) { kux = new KeyUsageExtension(xtn); } xtn = cert.Extensions["2.5.29.37"]; if (xtn != null) { eku = new ExtendedKeyUsageExtension(xtn); } if ((kux != null) && (eku != null)) { // RFC3280 states that when both KeyUsageExtension and // ExtendedKeyUsageExtension are present then BOTH should // be valid return(kux.Support(ku) && eku.KeyPurpose.Contains("1.3.6.1.5.5.7.3.2")); } else if (kux != null) { return(kux.Support(ku)); } else if (eku != null) { // Client Authentication (1.3.6.1.5.5.7.3.2) return(eku.KeyPurpose.Contains("1.3.6.1.5.5.7.3.2")); } // last chance - try with older (deprecated) Netscape extensions xtn = cert.Extensions["2.16.840.1.113730.1.1"]; if (xtn != null) { NetscapeCertTypeExtension ct = new NetscapeCertTypeExtension(xtn); return(ct.Support(NetscapeCertTypeExtension.CertTypes.SslClient)); } // certificate isn't valid for SSL client usage return(false); }
public void KeyUsage_MaxValue() { KeyUsageExtension kue = new KeyUsageExtension(); kue.KeyUsage = (KeyUsages)Int32.MaxValue; Assert.IsTrue(kue.Support(KeyUsages.none), "Support(none)"); Assert.IsTrue(kue.Support(KeyUsages.digitalSignature), "Support(digitalSignature)"); Assert.IsTrue(kue.Support(KeyUsages.nonRepudiation), "Support(nonRepudiation)"); Assert.IsTrue(kue.Support(KeyUsages.keyEncipherment), "Support(keyEncipherment)"); Assert.IsTrue(kue.Support(KeyUsages.dataEncipherment), "Support(dataEncipherment)"); Assert.IsTrue(kue.Support(KeyUsages.keyAgreement), "Support(keyAgreement)"); Assert.IsTrue(kue.Support(KeyUsages.keyCertSign), "Support(keyCertSign)"); Assert.IsTrue(kue.Support(KeyUsages.cRLSign), "Support(cRLSign)"); Assert.IsTrue(kue.Support(KeyUsages.encipherOnly), "Support(encipherOnly)"); Assert.IsTrue(kue.Support(KeyUsages.decipherOnly), "Support(decipherOnly)"); }
private MSX509.X509Certificate2 GetRootCertificate() { List <X509Extension> extensions = new List <X509Extension>(); BasicConstraintsExtension constraints = new BasicConstraintsExtension(); constraints.CertificateAuthority = true; constraints.Critical = true; extensions.Add(constraints); KeyUsageExtension keyUsage = new KeyUsageExtension(); keyUsage.KeyUsage = KeyUsages.keyCertSign | KeyUsages.cRLSign; extensions.Add(keyUsage); return(CreateCertificate(state_.Config.X509.AuthorityName, extensions, null, state_.Config.X509.AuthorityName, MSX509.StoreName.Root, state_.Config.X509.RootValidity)); }
internal static bool VerifyKeyUsage(MX.X509Certificate certificate, KeyUsages keyUsages, string purpose) { if (certificate.Extensions == null) { return(true); } KeyUsageExtension kux = null; ExtendedKeyUsageExtension eku = null; var xtn = certificate.Extensions [OidKeyUsage]; if (xtn != null) { kux = new KeyUsageExtension(xtn); } xtn = certificate.Extensions [OidExtendedKeyUsage]; if (xtn != null) { eku = new ExtendedKeyUsageExtension(xtn); } if ((kux != null) && (eku != null)) { // RFC3280 states that when both KeyUsageExtension and // ExtendedKeyUsageExtension are present then BOTH should // be valid if (!kux.Support(keyUsages)) { return(false); } return(eku.KeyPurpose.Contains(purpose)); } else if (kux != null) { return(kux.Support(keyUsages)); } else if (eku != null) { return(eku.KeyPurpose.Contains(purpose)); } return(true); }
public bool VerifySignature(X509Certificate x509) { if (x509 == null) { throw new ArgumentNullException("x509"); } if (x509.Version >= 3) { X509Extension x509Extension = x509.Extensions["2.5.29.15"]; if (x509Extension != null) { KeyUsageExtension keyUsageExtension = new KeyUsageExtension(x509Extension); if (!keyUsageExtension.Support(KeyUsages.cRLSign)) { return(false); } } x509Extension = x509.Extensions["2.5.29.19"]; if (x509Extension != null) { BasicConstraintsExtension basicConstraintsExtension = new BasicConstraintsExtension(x509Extension); if (!basicConstraintsExtension.CertificateAuthority) { return(false); } } } if (issuer != x509.SubjectName) { return(false); } switch (signatureOID) { case "1.2.840.10040.4.3": return(VerifySignature(x509.DSA)); default: return(VerifySignature(x509.RSA)); } }
internal MSX509.X509Certificate2 GetCertificate(string name) { List <X509Extension> extensions = new List <X509Extension>(); BasicConstraintsExtension constraints = new BasicConstraintsExtension(); constraints.CertificateAuthority = false; constraints.Critical = true; extensions.Add(constraints); KeyUsageExtension keyUsage = new KeyUsageExtension(); keyUsage.KeyUsage = KeyUsages.digitalSignature | KeyUsages.nonRepudiation | KeyUsages.keyEncipherment; extensions.Add(keyUsage); ExtendedKeyUsageExtension extendedUsage = new ExtendedKeyUsageExtension(); extendedUsage.KeyPurpose.Add("1.3.6.1.5.5.7.3.1"); extendedUsage.KeyPurpose.Add("1.3.6.1.5.5.7.3.2"); extensions.Add(extendedUsage); return(CreateCertificate(name, extensions, GetRootCertificate(), state_.Config.X509.AuthorityName, MSX509.StoreName.My, state_.Config.X509.RootValidity)); }
public void Constructor_Empty() { KeyUsageExtension kue = new KeyUsageExtension(); Empty(kue); }
/// <summary> /// Creates a Key Usage extension. /// </summary> /// <param name="keyUsage">One of the <see cref="KeyUsageExtension"/> values.</param> /// <returns>A <see cref="X509Extension"/> instance.</returns> public static X509Extension CreateKeyUsageExtension(KeyUsageExtension keyUsage) { return CreateKeyUsageExtension(keyUsage, false); }
// Note: this method only works for RSA certificates // DH certificates requires some changes - does anyone use one ? private bool checkCertificateUsage(X509Certificate cert) { ClientContext context = (ClientContext)this.Context; // certificate extensions are required for this // we "must" accept older certificates without proofs if (cert.Version < 3) { return(true); } KeyUsages ku = KeyUsages.none; switch (context.Negotiating.Cipher.ExchangeAlgorithmType) { case ExchangeAlgorithmType.RsaSign: ku = KeyUsages.digitalSignature; break; case ExchangeAlgorithmType.RsaKeyX: ku = KeyUsages.keyEncipherment; break; case ExchangeAlgorithmType.DiffieHellman: ku = KeyUsages.keyAgreement; break; case ExchangeAlgorithmType.Fortezza: return(false); // unsupported certificate type } KeyUsageExtension kux = null; ExtendedKeyUsageExtension eku = null; X509Extension xtn = cert.Extensions ["2.5.29.15"]; if (xtn != null) { kux = new KeyUsageExtension(xtn); } xtn = cert.Extensions ["2.5.29.37"]; if (xtn != null) { eku = new ExtendedKeyUsageExtension(xtn); } if ((kux != null) && (eku != null)) { // RFC3280 states that when both KeyUsageExtension and // ExtendedKeyUsageExtension are present then BOTH should // be valid if (!kux.Support(ku)) { return(false); } return(eku.KeyPurpose.Contains("1.3.6.1.5.5.7.3.1") || eku.KeyPurpose.Contains("2.16.840.1.113730.4.1")); } else if (kux != null) { return(kux.Support(ku)); } else if (eku != null) { // Server Authentication (1.3.6.1.5.5.7.3.1) or // Netscape Server Gated Crypto (2.16.840.1.113730.4) return(eku.KeyPurpose.Contains("1.3.6.1.5.5.7.3.1") || eku.KeyPurpose.Contains("2.16.840.1.113730.4.1")); } // last chance - try with older (deprecated) Netscape extensions xtn = cert.Extensions ["2.16.840.1.113730.1.1"]; if (xtn != null) { NetscapeCertTypeExtension ct = new NetscapeCertTypeExtension(xtn); return(ct.Support(NetscapeCertTypeExtension.CertTypes.SslServer)); } // if the CN=host (checked later) then we assume this is meant for SSL/TLS // e.g. the new smtp.gmail.com certificate return(true); }
private bool checkCertificateUsage(X509Certificate cert) { ServerContext context = (ServerContext)this.Context; // certificate extensions are required for this // we "must" accept older certificates without proofs if (cert.Version < 3) { return(true); } KeyUsages ku = KeyUsages.none; switch (context.Negotiating.Cipher.ExchangeAlgorithmType) { case ExchangeAlgorithmType.RsaSign: case ExchangeAlgorithmType.RsaKeyX: ku = KeyUsages.digitalSignature; break; case ExchangeAlgorithmType.DiffieHellman: ku = KeyUsages.keyAgreement; break; case ExchangeAlgorithmType.Fortezza: return(false); // unsupported certificate type } KeyUsageExtension kux = null; ExtendedKeyUsageExtension eku = null; X509Extension xtn = cert.Extensions["2.5.29.15"]; if (xtn != null) { kux = new KeyUsageExtension(xtn); } xtn = cert.Extensions["2.5.29.37"]; if (xtn != null) { eku = new ExtendedKeyUsageExtension(xtn); } if ((kux != null) && (eku != null)) { // RFC3280 states that when both KeyUsageExtension and // ExtendedKeyUsageExtension are present then BOTH should // be valid return(kux.Support(ku) && eku.KeyPurpose.Contains("1.3.6.1.5.5.7.3.2")); } else if (kux != null) { return(kux.Support(ku)); } else if (eku != null) { // Client Authentication (1.3.6.1.5.5.7.3.2) return(eku.KeyPurpose.Contains("1.3.6.1.5.5.7.3.2")); } // last chance - try with older (deprecated) Netscape extensions xtn = cert.Extensions["2.16.840.1.113730.1.1"]; if (xtn != null) { NetscapeCertTypeExtension ct = new NetscapeCertTypeExtension(xtn); return(ct.Support(NetscapeCertTypeExtension.CertTypes.SslClient)); } // certificate isn't valid for SSL server usage return(false); }
/// <summary> /// Creates a Key Usage extension. /// </summary> /// <param name="keyUsage">One of the <see cref="KeyUsageExtension"/> values.</param> /// <param name="critical"><b>true</b> if the extension is marked as critical, <b>false</b> otherwise.</param> /// <returns>A <see cref="X509Extension"/> instance.</returns> public static X509Extension CreateKeyUsageExtension(KeyUsageExtension keyUsage, bool critical) { BitStringEncodable value = new BitStringEncodable((byte)keyUsage); return new X509Extension(new Oid("2.5.29.15", "Key Usage"), value.ToArray(), critical); }
/// <summary> /// Generates an X509 certificate using the Mono.Security assembly. /// Potentially could prise out the relevant classes from the Mono /// source code in order to reduce plgx size and complexity... one day /// </summary> /// <param name="subject">The subject.</param> /// <param name="issuer">The issuer.</param> /// <returns></returns> public static PKCS12 Generate(string subject, string issuer, string password, KeePassRPCExt KeePassRPCPlugin) { byte[] sn = Guid.NewGuid().ToByteArray(); DateTime notBefore = DateTime.Now; DateTime notAfter = new DateTime(643445675990000000); // 12/31/2039 23:59:59Z subject = "CN=" + subject; issuer = "CN=" + issuer; RSA subjectKey = (RSA)RSA.Create(); RSA issuerKey = (RSA)RSA.Create(); subjectKey.KeySize = 2048; issuerKey.KeySize = 2048; string hashName = "SHA1"; CspParameters subjectParams = new CspParameters(); CspParameters issuerParams = new CspParameters(); // serial number MUST be positive if ((sn[0] & 0x80) == 0x80) { sn[0] -= 0x80; } //issuer = subject; //RSA issuerKey = subjectKey; if (subject == null) { throw new Exception("Missing Subject Name"); } X509CertificateBuilder cb = new X509CertificateBuilder(3); cb.SerialNumber = sn; cb.IssuerName = issuer; cb.NotBefore = notBefore; cb.NotAfter = notAfter; cb.SubjectName = subject; cb.SubjectPublicKey = subjectKey; cb.Hash = hashName; //X509 extensions KeyUsageExtension keyUsage = new KeyUsageExtension(); keyUsage.KeyUsage = KeyUsages.keyEncipherment | KeyUsages.digitalSignature; cb.Extensions.Add(keyUsage); ExtendedKeyUsageExtension extendedKeyUsage = new ExtendedKeyUsageExtension(); extendedKeyUsage.KeyPurpose.Add("1.3.6.1.5.5.7.3.1"); cb.Extensions.Add(extendedKeyUsage); byte[] rawcert = cb.Sign(issuerKey); PKCS12 p12 = new PKCS12(); p12.Password = password; ArrayList list = new ArrayList(); // we use a fixed array to avoid endianess issues // (in case some tools requires the ID to be 1). list.Add(new byte[4] { 1, 0, 0, 0 }); Hashtable attributes = new Hashtable(1); attributes.Add(PKCS9.localKeyId, list); p12.AddCertificate(new X509Certificate(rawcert), attributes); p12.AddPkcs8ShroudedKeyBag(subjectKey, attributes); /* * if (Type.GetType("Mono.Runtime") != null) * { * string fileName = Path.Combine(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "KeePassRPC"), "cert.p12"); * if (KeePassRPCPlugin.logger != null) KeePassRPCPlugin.logger.WriteLine(fileName); * try * { * p12.SaveToFile(fileName); * } * catch (Exception) * { * if (KeePassRPCPlugin.logger != null) KeePassRPCPlugin.logger.WriteLine("Could not write to " + fileName + " security between KPRPC and clients may not be established."); * } * } * * return p12.GetBytes(); */ return(p12); }
/// <summary> /// Generates an X509 certificate using the Mono.Security assembly. /// Potentially could prise out the relevant classes from the Mono /// source code in order to reduce plgx size and complexity... one day /// </summary> /// <param name="subject">The subject.</param> /// <param name="issuer">The issuer.</param> /// <returns></returns> public static PKCS12 Generate(string subject, string issuer, string password, KeePassRPCExt KeePassRPCPlugin) { byte[] sn = Guid.NewGuid().ToByteArray(); DateTime notBefore = DateTime.Now; DateTime notAfter = new DateTime(643445675990000000); // 12/31/2039 23:59:59Z subject = "CN=" + subject; issuer = "CN=" + issuer; RSA subjectKey = (RSA)RSA.Create(); RSA issuerKey = (RSA)RSA.Create(); subjectKey.KeySize = 2048; issuerKey.KeySize = 2048; string hashName = "SHA1"; CspParameters subjectParams = new CspParameters(); CspParameters issuerParams = new CspParameters(); // serial number MUST be positive if ((sn[0] & 0x80) == 0x80) sn[0] -= 0x80; //issuer = subject; //RSA issuerKey = subjectKey; if (subject == null) throw new Exception("Missing Subject Name"); X509CertificateBuilder cb = new X509CertificateBuilder(3); cb.SerialNumber = sn; cb.IssuerName = issuer; cb.NotBefore = notBefore; cb.NotAfter = notAfter; cb.SubjectName = subject; cb.SubjectPublicKey = subjectKey; cb.Hash = hashName; //X509 extensions KeyUsageExtension keyUsage = new KeyUsageExtension(); keyUsage.KeyUsage = KeyUsages.keyEncipherment | KeyUsages.digitalSignature; cb.Extensions.Add(keyUsage); ExtendedKeyUsageExtension extendedKeyUsage = new ExtendedKeyUsageExtension(); extendedKeyUsage.KeyPurpose.Add("1.3.6.1.5.5.7.3.1"); cb.Extensions.Add(extendedKeyUsage); byte[] rawcert = cb.Sign(issuerKey); PKCS12 p12 = new PKCS12(); p12.Password = password; ArrayList list = new ArrayList(); // we use a fixed array to avoid endianess issues // (in case some tools requires the ID to be 1). list.Add(new byte[4] { 1, 0, 0, 0 }); Hashtable attributes = new Hashtable(1); attributes.Add(PKCS9.localKeyId, list); p12.AddCertificate(new X509Certificate(rawcert), attributes); p12.AddPkcs8ShroudedKeyBag(subjectKey, attributes); /* if (Type.GetType("Mono.Runtime") != null) { string fileName = Path.Combine(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "KeePassRPC"), "cert.p12"); if (KeePassRPCPlugin.logger != null) KeePassRPCPlugin.logger.WriteLine(fileName); try { p12.SaveToFile(fileName); } catch (Exception) { if (KeePassRPCPlugin.logger != null) KeePassRPCPlugin.logger.WriteLine("Could not write to " + fileName + " security between KPRPC and clients may not be established."); } } return p12.GetBytes(); */ return p12; }
/// <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 }