/// <summary> /// Signs the certificate with the certificate of an issuer. /// </summary> /// <param name="issuerCertificate">The certificate of the issuer.</param> /// <param name="privateKey">The private key of the issuer.</param> /// <exception cref="ArgumentNullException"><paramref name="issuerCertificate"/> is <c>null</c>.</exception> /// <exception cref="ArgumentNullException"><paramref name="privateKey"/> is <c>null</c>.</exception> /// <exception cref="ArgumentException"><paramref name="issuerCertificate"/> is not a CA.</exception> public void Sign(X509Certificate2 issuerCertificate, AsymmetricAlgorithm privateKey) { if (issuerCertificate == null) { throw new ArgumentNullException("issuerCertificate"); } if (privateKey == null) { throw new ArgumentNullException("privateKey"); } var basicConstraintsExtension = issuerCertificate.Extensions.OfType <X509BasicConstraintsExtension>().FirstOrDefault(); if (basicConstraintsExtension == null || false == basicConstraintsExtension.CertificateAuthority) { throw new ArgumentException("The certificate must be a CA.", "issuerCertificate"); } var monoIssuerCertificate = new X509Certificate(issuerCertificate.GetRawCertData()); PrepareSigning(); _builder.IssuerName = monoIssuerCertificate.SubjectName; // Get the subject key identifier of the issuer's certificate. This identifier can be used when a X.509 certificate // chain is build to validate an end-user certificate. var subjectKeyIdentifier = GetSubjectKeyIdentififer(monoIssuerCertificate); if (subjectKeyIdentifier != null) { // Add an "authority key identifier" extension to the new certificate. The extension contains // the "subject key identifier" of the issuer's certificate and is used to identify it when // a X.509 certificate verification chain is build _builder.Extensions.Add(CreateAuthorityKeyIdentifier(subjectKeyIdentifier)); } if (IsCertificateAuthority) { // Create a subject key by which the certificate can be identified when a X.509 certificate chain is build // This is required since the certificate will be used to validate other certificates var extension = CreateSubjectKeyIdentifier(Guid.NewGuid().ToByteArray()); _builder.Extensions.Add(extension); } _signedCertificate = _builder.Sign(privateKey); }
public static X509Certificate2 GenerateCert(string certificateName, RSA key) { byte[] sn = GenerateSerialNumber(); string subject = string.Format("CN={0}", certificateName); DateTime notBefore = DateTime.Now; DateTime notAfter = DateTime.Now.AddYears(20); string hashName = "SHA512"; X509CertificateBuilder cb = new X509CertificateBuilder(3); cb.SerialNumber = sn; cb.IssuerName = subject; cb.NotBefore = notBefore; cb.NotAfter = notAfter; cb.SubjectName = subject; cb.SubjectPublicKey = key; cb.Hash = hashName; byte[] rawcert = cb.Sign(key); PKCS12 p12 = new PKCS12(); Hashtable attributes = GetAttributes(); p12.AddCertificate(new Mono.Security.X509.X509Certificate(rawcert), attributes); p12.AddPkcs8ShroudedKeyBag(key, attributes); rawcert = p12.GetBytes(); return new X509Certificate2(rawcert, "", X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet); }
public void SubjectAltNameGenerator () { RSACryptoServiceProvider rsa = new RSACryptoServiceProvider (); X509CertificateBuilder x509 = new X509CertificateBuilder (); x509.IssuerName = "C=ZA, ST=Western Cape, L=Cape Town, O=Thawte Consulting cc, OU=Certification Services Division, CN=Thawte Server"; x509.NotAfter = DateTime.MaxValue; x509.NotBefore = DateTime.MinValue; x509.SubjectName = "C=US, ST=Maryland, L=Pasadena, O=Brent Baccala, OU=FreeSoft, CN=www.freesoft.org"; x509.SerialNumber = new byte[] {12, 34, 56, 78, 90}; x509.Version = 3; x509.SubjectPublicKey = rsa; string[] dns = new string[2]; dns[0] = "one"; dns[1] = "two"; string[] uris = new string[3]; uris[0] = "one:two://three"; uris[1] = "Here:I:AM://12345"; uris[2] = "last:one"; SubjectAltNameExtension sane = new SubjectAltNameExtension (null, dns, null, uris); x509.Extensions.Add (sane); byte[] data = x509.Sign (rsa); X509Certificate x509_loaded = new X509Certificate (data); SubjectAltNameExtension sane_test = new SubjectAltNameExtension (x509_loaded.Extensions[0]); Assert.AreEqual (sane_test.RFC822.Length, 0, "RFC822 count"); Assert.AreEqual (sane_test.DNSNames.Length, 2, "DNSName count"); Assert.AreEqual (sane_test.IPAddresses.Length, 0, "IPAddresses count"); Assert.AreEqual (sane_test.UniformResourceIdentifiers.Length, 3, "URI Count"); Assert.AreEqual (sane_test.DNSNames[1], "two", "DNSName test"); Assert.AreEqual (sane_test.UniformResourceIdentifiers[2], "last:one", "URI Test"); }
//adapted from https://github.com/mono/mono/blob/master/mcs/tools/security/makecert.cs public static PKCS12 GeneratePfx(string certificateName, string password) { byte[] sn = GenerateSerialNumber(); string subject = string.Format("CN={0}", certificateName); DateTime notBefore = DateTime.Now; DateTime notAfter = DateTime.Now.AddYears(20); var subjectKey = new RSACryptoServiceProvider(2048); var hashName = "SHA512"; var cb = new X509CertificateBuilder(3); cb.SerialNumber = sn; cb.IssuerName = subject; cb.NotBefore = notBefore; cb.NotAfter = notAfter; cb.SubjectName = subject; cb.SubjectPublicKey = subjectKey; cb.Hash = hashName; var rawcert = cb.Sign(subjectKey); var p12 = new PKCS12(); p12.Password = password; var attributes = GetAttributes(); p12.AddCertificate(new Mono.Security.X509.X509Certificate(rawcert), attributes); p12.AddPkcs8ShroudedKeyBag(subjectKey, attributes); return p12; }
//adapted from https://github.com/mono/mono/blob/master/mcs/tools/security/makecert.cs static byte[] GeneratePfx(string certificateName, string password) { var sn = GenerateSerialNumber(); var subject = string.Format("CN={0}", certificateName); var notBefore = DateTime.Now; var notAfter = DateTime.Now.AddYears(20); var subjectKey = new RSACryptoServiceProvider(2048); var hashName = "SHA256"; var cb = new MonoX509.X509CertificateBuilder(3); cb.SerialNumber = sn; cb.IssuerName = subject; cb.NotBefore = notBefore; cb.NotAfter = notAfter; cb.SubjectName = subject; cb.SubjectPublicKey = subjectKey; cb.Hash = hashName; var rawcert = cb.Sign(subjectKey); var p12 = new MonoX509.PKCS12(); p12.Password = password; Hashtable attributes = GetAttributes(); p12.AddCertificate(new MonoX509.X509Certificate(rawcert), attributes); p12.AddPkcs8ShroudedKeyBag(subjectKey, attributes); return(p12.GetBytes()); }
internal static void CreateSelfSignCertificatePfx( string fileName, string hostname, ILogger logger) { if (string.IsNullOrWhiteSpace(fileName)) { throw new ArgumentNullException("fileName"); } byte[] sn = Guid.NewGuid().ToByteArray(); string subject = string.Format("CN={0}", hostname); string issuer = subject; DateTime notBefore = DateTime.Now.AddDays(-2); DateTime notAfter = DateTime.Now.AddYears(10); RSA issuerKey = RSA.Create(); issuerKey.FromXmlString(MonoTestRootAgency); RSA subjectKey = RSA.Create(); // serial number MUST be positive if ((sn[0] & 0x80) == 0x80) sn[0] -= 0x80; issuer = subject; issuerKey = subjectKey; X509CertificateBuilder cb = new X509CertificateBuilder(3); cb.SerialNumber = sn; cb.IssuerName = issuer; cb.NotBefore = notBefore; cb.NotAfter = notAfter; cb.SubjectName = subject; cb.SubjectPublicKey = subjectKey; // signature cb.Hash = "SHA256"; byte[] rawcert = cb.Sign(issuerKey); PKCS12 p12 = new PKCS12(); 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); p12.SaveToFile(fileName); }
public static byte[] CreateClientCert(string subjectName, byte[] rootKey, byte[] rootCert) { if (!subjectName.StartsWith("CN=")) subjectName = "CN=" + subjectName; // Copy the root key since the PrivateKey constructor will blow away the data byte[] rootKeyCopy = new byte[rootKey.Length]; Buffer.BlockCopy(rootKey, 0, rootKeyCopy, 0, rootKey.Length); // Load the server's private key and certificate PrivateKey pvk = new PrivateKey(rootKeyCopy, null); RSA issuerKey = pvk.RSA; X509Certificate issuerCert = new X509Certificate(rootCert); // Serial number MUST be positive byte[] sn = Guid.NewGuid().ToByteArray(); if ((sn[0] & 0x80) == 0x80) sn[0] -= 0x80; ExtendedKeyUsageExtension eku = new ExtendedKeyUsageExtension(); eku.KeyPurpose.Add("1.3.6.1.5.5.7.3.2"); // Indicates the cert is intended for client auth // Generate a client certificate signed by the server root CA X509CertificateBuilder cb = new X509CertificateBuilder(3); cb.SerialNumber = sn; cb.IssuerName = issuerCert.IssuerName; cb.NotBefore = DateTime.Now; cb.NotAfter = new DateTime(643445675990000000); // 12/31/2039 23:59:59Z cb.SubjectName = subjectName; cb.SubjectPublicKey = issuerKey; cb.Hash = "SHA1"; cb.Extensions.Add(eku); byte[] clientCert = cb.Sign(issuerKey); // Generate a PKCS#12 file for the client containing the private key and certificate PKCS12 p12 = new PKCS12(); p12.Password = null; ArrayList list = new ArrayList(4); // We use a fixed array to avoid endianess issues // (in case some tools requires the ID to be 1). list.Add(new byte[] { 1, 0, 0, 0 }); Hashtable attributes = new Hashtable(1); attributes.Add(PKCS9.localKeyId, list); p12.AddCertificate(new X509Certificate(clientCert), attributes); p12.AddCertificate(issuerCert); p12.AddPkcs8ShroudedKeyBag(issuerKey, attributes); return p12.GetBytes(); }
public static void CreateRootCert(string issuer, out byte[] rootCert) { if (!issuer.StartsWith("CN=")) issuer = "CN=" + issuer; // Generate a new issuer key RSA issuerKey = (RSA)RSA.Create(); // Generate a private key PrivateKey key = new PrivateKey(); key.RSA = issuerKey; // Serial number MUST be positive byte[] sn = Guid.NewGuid().ToByteArray(); if ((sn[0] & 0x80) == 0x80) sn[0] -= 0x80; ExtendedKeyUsageExtension eku = new ExtendedKeyUsageExtension(); eku.KeyPurpose.Add("1.3.6.1.5.5.7.3.1"); // Indicates the cert is intended for server auth eku.KeyPurpose.Add("1.3.6.1.5.5.7.3.2"); // Indicates the cert is intended for client auth // Generate a self-signed certificate X509CertificateBuilder cb = new X509CertificateBuilder(3); cb.SerialNumber = sn; cb.IssuerName = issuer; cb.NotBefore = DateTime.Now; cb.NotAfter = new DateTime(643445675990000000); // 12/31/2039 23:59:59Z cb.SubjectName = issuer; cb.SubjectPublicKey = issuerKey; cb.Hash = "SHA1"; cb.Extensions.Add(eku); byte[] serverCert = cb.Sign(issuerKey); // Generate a PKCS#12 file containing the certificate and private key PKCS12 p12 = new PKCS12(); p12.Password = null; ArrayList list = new ArrayList(4); // We use a fixed array to avoid endianess issues // (in case some tools requires the ID to be 1). list.Add(new byte[] { 1, 0, 0, 0 }); Hashtable attributes = new Hashtable(1); attributes.Add(PKCS9.localKeyId, list); p12.AddCertificate(new X509Certificate(serverCert), attributes); p12.AddPkcs8ShroudedKeyBag(issuerKey, attributes); rootCert = p12.GetBytes(); }
public static void CreateServerRootCA(string issuer, out byte[] rootKey, out byte[] rootCert) { if (!issuer.StartsWith("CN=")) issuer = "CN=" + issuer; // Create a temporary file string tempFile = Path.GetTempFileName(); // Generate a new signing key RSA issuerKey = (RSA)RSA.Create(); // Generate a private key PrivateKey key = new PrivateKey(); key.RSA = issuerKey; // Save the private key and load it back into memory key.Save(tempFile); rootKey = File.ReadAllBytes(tempFile); File.Delete(tempFile); // Serial number MUST be positive byte[] sn = Guid.NewGuid().ToByteArray(); if ((sn[0] & 0x80) == 0x80) sn[0] -= 0x80; // Generate a self-signed certificate X509CertificateBuilder cb = new X509CertificateBuilder(3); cb.SerialNumber = sn; cb.IssuerName = issuer; cb.NotBefore = DateTime.Now; cb.NotAfter = new DateTime(643445675990000000); // 12/31/2039 23:59:59Z cb.SubjectName = issuer; cb.SubjectPublicKey = issuerKey; cb.Hash = "SHA1"; rootCert = cb.Sign(issuerKey); }
/// <summary>This method is called by a CA to sign the provided Certificate /// with our RSA key.</summary> public Certificate Sign(Certificate Signer, RSA PrivateKey) { X509CertificateBuilder x509_builder = new X509CertificateBuilder(3); x509_builder.IssuerName = Signer.Subject.DN; x509_builder.SubjectName = Subject.DN; SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider(); // I guess this is reversed for network order or something... byte[] tmp = sha1.ComputeHash(Signer.UnsignedData); for(int i = 0; i < tmp.Length / 2; i++) { int j = tmp.Length - i - 1; byte tmpb = tmp[i]; tmp[i] = tmp[j]; tmp[j] = tmpb; } x509_builder.SerialNumber = tmp; x509_builder.NotBefore = System.DateTime.MinValue; x509_builder.NotAfter = System.DateTime.MaxValue; x509_builder.SubjectPublicKey = _public_key; SubjectAltNameExtension sane = new SubjectAltNameExtension(null, null, null, new string[] {NodeAddress}); x509_builder.Extensions.Add(sane); byte[] cert_data = x509_builder.Sign(PrivateKey); return new Certificate(cert_data); }
private static byte[] CreateRawCert(string certName, string password) { if (String.IsNullOrEmpty(certName)) { Log.To.Listener.E(Tag, "An empty certName was received in CreateRawCert, throwing..."); throw new ArgumentException("Must contain a non-empty name", "certName"); } if (String.IsNullOrEmpty(password)) { Log.To.Listener.E(Tag, "An empty password was received in CreateRawCert, throwing..."); throw new ArgumentException("Must contain a non-empty password", "password"); } byte[] sn = GenerateSerialNumber(); string subject = string.Format("CN={0}", certName); DateTime notBefore = DateTime.Now; DateTime notAfter = DateTime.Now.AddYears(20); string hashName = "SHA512"; var key = new RSACryptoServiceProvider(2048); X509CertificateBuilder cb = new X509CertificateBuilder(3); cb.SerialNumber = sn; cb.IssuerName = subject; cb.NotBefore = notBefore; cb.NotAfter = notAfter; cb.SubjectName = subject; cb.SubjectPublicKey = key; cb.Hash = hashName; Log.To.Listener.I(Tag, "Generating X509 certificate, this is expensive..."); var sw = System.Diagnostics.Stopwatch.StartNew(); byte[] rawcert = cb.Sign(key); sw.Stop(); Log.To.Listener.I(Tag, "Finished generating X509 certificate; took {0} sec", sw.ElapsedMilliseconds / 1000.0); PKCS12 p12 = new PKCS12(); if (!String.IsNullOrEmpty(password)) { p12.Password = password; } Hashtable attributes = GetAttributes(); p12.AddCertificate(new Mono.Security.X509.X509Certificate(rawcert), attributes); p12.AddPkcs8ShroudedKeyBag(key, attributes); return p12.GetBytes(); }
public static X509Certificate2 GetOrCreateClientCert() { string dirname = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); string path = Path.Combine(dirname, ".couchbase"); Directory.CreateDirectory(path); path = Path.Combine(path, "client.pfx"); if (File.Exists(path)) { return new X509Certificate2(path); } byte[] sn = GenerateSerialNumber(); string subject = string.Format("CN=CouchbaseClient"); DateTime notBefore = DateTime.Now; DateTime notAfter = DateTime.Now.AddYears(20); RSA subjectKey = new RSACryptoServiceProvider(2048); PrivateKey privKey = new PrivateKey(); privKey.RSA = subjectKey; string hashName = "SHA512"; X509CertificateBuilder cb = new X509CertificateBuilder(3); cb.SerialNumber = sn; cb.IssuerName = subject; cb.NotBefore = notBefore; cb.NotAfter = notAfter; cb.SubjectName = subject; cb.SubjectPublicKey = subjectKey; cb.Hash = hashName; byte[] rawcert = cb.Sign(subjectKey); PKCS12 p12 = new PKCS12(); Hashtable attributes = GetAttributes(); p12.AddCertificate(new Mono.Security.X509.X509Certificate(rawcert),attributes); p12.AddPkcs8ShroudedKeyBag(subjectKey,attributes); rawcert = p12.GetBytes(); WriteCertificate(path, rawcert); return new X509Certificate2(rawcert); }
static int Main (string[] args) { if (args.Length < 1) { Header (); Console.WriteLine ("ERROR: Missing output filename {0}", Environment.NewLine); Help (); return -1; } string fileName = args [args.Length - 1]; // default values byte[] sn = Guid.NewGuid ().ToByteArray (); string subject = defaultSubject; string issuer = defaultIssuer; DateTime notBefore = DateTime.Now; DateTime notAfter = new DateTime (643445675990000000); // 12/31/2039 23:59:59Z RSA issuerKey = (RSA)RSA.Create (); issuerKey.FromXmlString (MonoTestRootAgency); RSA subjectKey = (RSA)RSA.Create (); bool selfSigned = false; string hashName = "SHA1"; CspParameters subjectParams = new CspParameters (); CspParameters issuerParams = new CspParameters (); BasicConstraintsExtension bce = null; ExtendedKeyUsageExtension eku = null; SubjectAltNameExtension alt = null; string p12file = null; string p12pwd = null; X509Certificate issuerCertificate = null; Header(); try { int i=0; while (i < args.Length) { switch (args [i++]) { // Basic options case "-#": // Serial Number sn = BitConverter.GetBytes (Convert.ToInt32 (args [i++])); break; case "-n": // Subject Distinguish Name subject = args [i++]; break; case "-$": // (authenticode) commercial or individual // CRITICAL KeyUsageRestriction extension // hash algorithm string usageRestriction = args [i++].ToLower (); switch (usageRestriction) { case "commercial": case "individual": Console.WriteLine ("WARNING: Unsupported deprecated certification extension KeyUsageRestriction not included"); // Console.WriteLine ("WARNING: ExtendedKeyUsage for codesigning has been included."); break; default: Console.WriteLine ("Unsupported restriction " + usageRestriction); return -1; } break; // Extended Options case "-a": // hash algorithm switch (args [i++].ToLower ()) { case "sha1": hashName = "SHA1"; break; case "md5": Console.WriteLine ("WARNING: MD5 is no more safe for this usage."); hashName = "MD5"; break; default: Console.WriteLine ("Unsupported hash algorithm"); break; } break; case "-b": // Validity / notBefore notBefore = DateTime.Parse (args [i++] + " 23:59:59", CultureInfo.InvariantCulture); break; case "-cy": // basic constraints - autority or end-entity switch (args [i++].ToLower ()) { case "authority": if (bce == null) bce = new BasicConstraintsExtension (); bce.CertificateAuthority = true; break; case "end": // do not include extension bce = null; break; case "both": Console.WriteLine ("ERROR: No more supported in X.509"); return -1; default: Console.WriteLine ("Unsupported certificate type"); return -1; } break; case "-d": // CN private extension ? Console.WriteLine ("Unsupported option"); break; case "-e": // Validity / notAfter notAfter = DateTime.Parse (args [i++] + " 23:59:59", CultureInfo.InvariantCulture); break; case "-eku": // extendedKeyUsage extension char[] sep = { ',' }; string[] purposes = args [i++].Split (sep); if (eku == null) eku = new ExtendedKeyUsageExtension (); foreach (string purpose in purposes) { eku.KeyPurpose.Add (purpose); } break; case "-h": // pathLength (basicConstraints) // MS use an old basicConstrains (2.5.29.10) which // allows both CA and End-Entity. This is no // more supported with 2.5.29.19. if (bce == null) { bce = new BasicConstraintsExtension (); bce.CertificateAuthority = true; } bce.PathLenConstraint = Convert.ToInt32 (args [i++]); break; case "-alt": if (alt == null) { string [] dnsNames = File.ReadAllLines (args [i++]); alt = new SubjectAltNameExtension (null, dnsNames, null, null); } break; case "-ic": issuerCertificate = LoadCertificate (args [i++]); issuer = issuerCertificate.SubjectName; break; case "-in": issuer = args [i++]; break; case "-iv": // TODO password PrivateKey pvk = PrivateKey.CreateFromFile (args [i++]); issuerKey = pvk.RSA; break; case "-l": // link (URL) // spcSpAgencyInfo private extension Console.WriteLine ("Unsupported option"); break; case "-m": // validity period (in months) notAfter = notBefore.AddMonths (Convert.ToInt32 (args [i++])); break; case "-nscp": // Netscape's private extensions - NetscapeCertType // BasicContraints - End Entity Console.WriteLine ("Unsupported option"); break; case "-r": selfSigned = true; break; case "-sc": // subject certificate ? renew ? Console.WriteLine ("Unsupported option"); break; // Issuer CspParameters options case "-ik": issuerParams.KeyContainerName = args [i++]; break; case "-iky": // select a key in the provider string ikn = args [i++].ToLower (); switch (ikn) { case "signature": issuerParams.KeyNumber = 0; break; case "exchange": issuerParams.KeyNumber = 1; break; default: issuerParams.KeyNumber = Convert.ToInt32 (ikn); break; } break; case "-ip": issuerParams.ProviderName = args [i++]; break; case "-ir": switch (args [i++].ToLower ()) { case "localmachine": issuerParams.Flags = CspProviderFlags.UseMachineKeyStore; break; case "currentuser": issuerParams.Flags = CspProviderFlags.UseDefaultKeyContainer; break; default: Console.WriteLine ("Unknown key store for issuer"); return -1; } break; case "-is": Console.WriteLine ("Unsupported option"); return -1; case "-iy": issuerParams.ProviderType = Convert.ToInt32 (args [i++]); break; // Subject CspParameters Options case "-sk": subjectParams.KeyContainerName = args [i++]; break; case "-sky": // select a key in the provider string skn = args [i++].ToLower (); switch (skn) { case "signature": subjectParams.KeyNumber = 0; break; case "exchange": subjectParams.KeyNumber = 1; break; default: subjectParams.KeyNumber = Convert.ToInt32 (skn); break; } break; case "-sp": subjectParams.ProviderName = args [i++]; break; case "-sr": switch (args [i++].ToLower ()) { case "localmachine": subjectParams.Flags = CspProviderFlags.UseMachineKeyStore; break; case "currentuser": subjectParams.Flags = CspProviderFlags.UseDefaultKeyContainer; break; default: Console.WriteLine ("Unknown key store for subject"); return -1; } break; case "-ss": Console.WriteLine ("Unsupported option"); return -1; case "-sv": string pvkFile = args [i++]; if (File.Exists (pvkFile)) { PrivateKey key = PrivateKey.CreateFromFile (pvkFile); subjectKey = key.RSA; } else { PrivateKey key = new PrivateKey (); key.RSA = subjectKey; key.Save (pvkFile); } break; case "-sy": subjectParams.ProviderType = Convert.ToInt32 (args [i++]); break; // Mono Specific Options case "-p12": p12file = args [i++]; p12pwd = args [i++]; break; // Other options case "-?": Help (); return 0; case "-!": ExtendedHelp (); return 0; default: if (i != args.Length) { Console.WriteLine ("ERROR: Unknown parameter"); Help (); return -1; } break; } } // serial number MUST be positive if ((sn [0] & 0x80) == 0x80) sn [0] -= 0x80; if (selfSigned) { if (subject != defaultSubject) { issuer = subject; issuerKey = subjectKey; } else { subject = issuer; subjectKey = issuerKey; } } 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; // extensions if (bce != null) cb.Extensions.Add (bce); if (eku != null) cb.Extensions.Add (eku); if (alt != null) cb.Extensions.Add (alt); // signature cb.Hash = hashName; byte[] rawcert = cb.Sign (issuerKey); if (p12file == null) { WriteCertificate (fileName, rawcert); } else { PKCS12 p12 = new PKCS12 (); p12.Password = p12pwd; 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); if (issuerCertificate != null) p12.AddCertificate (issuerCertificate); p12.AddPkcs8ShroudedKeyBag (subjectKey, attributes); p12.SaveToFile (p12file); } Console.WriteLine ("Success"); return 0; } catch (Exception e) { Console.WriteLine ("ERROR: " + e.ToString ()); Help (); } return 1; }
/// <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 byte[] Generate(string subject, string issuer, 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(); 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; byte[] rawcert = cb.Sign(issuerKey); PKCS12 p12 = new PKCS12(); 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(); }
private MSX509.X509Certificate2 CreateCertificate(string name, List<X509Extension> extensions, MSX509.X509Certificate2 issuerCertificate, string issuer, MSX509.StoreName storeName, int validity) { MSX509.X509Certificate2 certificate = LoadCertificate(name, storeName, location_); if(certificate != null) return certificate; state_.Logger.Information("Create X509.v3 certificate for '{0}'", name); PrivateKey key = new PrivateKey(); key.RSA = RSA.Create(); X509CertificateBuilder builder = new X509CertificateBuilder(3); builder.SerialNumber = GenerateSerial(); builder.IssuerName = "CN=" + issuer; builder.SubjectName = "CN=" + name; builder.SubjectPublicKey = key.RSA; builder.NotBefore = DateTime.Now; builder.NotAfter = builder.NotBefore.AddDays(validity); builder.Hash = "SHA1"; foreach(X509Extension extension in extensions) builder.Extensions.Add(extension); var signator = issuerCertificate == null ? key.RSA : issuerCertificate.PrivateKey; byte[] raw = builder.Sign(signator); StoreCertificate(name, raw, key.RSA, storeName, location_); certificate = new MSX509.X509Certificate2(raw); certificate.PrivateKey = key.RSA; return certificate; }
static void Main(string[] args) { var assembly = Assembly.GetExecutingAssembly(); var title = (AssemblyTitleAttribute)Attribute.GetCustomAttribute(assembly, typeof(AssemblyTitleAttribute)); Console.WriteLine("{0} version {1}", title.Title, assembly.GetName().Version); var copyright = (AssemblyCopyrightAttribute)Attribute.GetCustomAttribute(assembly, typeof(AssemblyCopyrightAttribute)); Console.WriteLine(copyright.Copyright); Console.WriteLine("More information can be found at https://Jexus.codeplex.com"); Console.WriteLine(); var baseAddress = args.Length > 0 ? args[0] : "https://*****:*****@"Remote services must be run as root on Linux."); return; } if (!File.Exists("jws")) { Console.WriteLine(@"Remote services must be running in Jexus installation folder."); return; } var loc = baseAddress.LastIndexOf(':'); var port = "443"; if (loc != -1) { port = baseAddress.Substring(loc + 1); } string dirname = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); string path = Path.Combine(dirname, ".mono", "httplistener"); if (false == Directory.Exists(path)) { Directory.CreateDirectory(path); } string target_cert = Path.Combine(path, string.Format("{0}.cer", port)); if (File.Exists(target_cert)) { Console.WriteLine("Use {0}", target_cert); } else { Console.WriteLine("Generating a self-signed certificate for Jexus Manager"); // Generate certificate string defaultIssuer = "CN=jexus.lextudio.com"; string defaultSubject = "CN=jexus.lextudio.com"; byte[] sn = Guid.NewGuid().ToByteArray(); string subject = defaultSubject; string issuer = defaultIssuer; DateTime notBefore = DateTime.Now; DateTime notAfter = new DateTime(643445675990000000); // 12/31/2039 23:59:59Z RSA issuerKey = new RSACryptoServiceProvider(2048); RSA subjectKey = null; bool selfSigned = true; string hashName = "SHA1"; CspParameters subjectParams = new CspParameters(); CspParameters issuerParams = new CspParameters(); BasicConstraintsExtension bce = new BasicConstraintsExtension { PathLenConstraint = BasicConstraintsExtension.NoPathLengthConstraint, CertificateAuthority = true }; ExtendedKeyUsageExtension eku = new ExtendedKeyUsageExtension(); eku.KeyPurpose.Add("1.3.6.1.5.5.7.3.1"); SubjectAltNameExtension alt = null; string p12file = Path.Combine(path, "temp.pfx"); string p12pwd = "test"; // serial number MUST be positive if ((sn[0] & 0x80) == 0x80) sn[0] -= 0x80; if (selfSigned) { if (subject != defaultSubject) { issuer = subject; issuerKey = subjectKey; } else { subject = issuer; subjectKey = issuerKey; } } 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; // extensions if (bce != null) cb.Extensions.Add(bce); if (eku != null) cb.Extensions.Add(eku); if (alt != null) cb.Extensions.Add(alt); IDigest digest = new Sha1Digest(); byte[] resBuf = new byte[digest.GetDigestSize()]; var spki = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(DotNetUtilities.GetRsaPublicKey(issuerKey)); byte[] bytes = spki.PublicKeyData.GetBytes(); digest.BlockUpdate(bytes, 0, bytes.Length); digest.DoFinal(resBuf, 0); cb.Extensions.Add(new SubjectKeyIdentifierExtension { Identifier = resBuf }); cb.Extensions.Add(new AuthorityKeyIdentifierExtension { Identifier = resBuf }); // signature cb.Hash = hashName; byte[] rawcert = cb.Sign(issuerKey); PKCS12 p12 = new PKCS12(); p12.Password = p12pwd; 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 Mono.Security.X509.X509Certificate(rawcert), attributes); p12.AddPkcs8ShroudedKeyBag(subjectKey, attributes); p12.SaveToFile(p12file); var x509 = new System.Security.Cryptography.X509Certificates.X509Certificate2(p12file, p12pwd, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags.Exportable); // Install certificate string target_pvk = Path.Combine(path, string.Format("{0}.pvk", port)); using (Stream cer = File.OpenWrite(target_cert)) { byte[] raw = x509.RawData; cer.Write(raw, 0, raw.Length); } PrivateKey pvk = new PrivateKey(); pvk.RSA = subjectKey; pvk.Save(target_pvk); } } JexusServer.Credentials = args.Length > 2 ? args[1] + "|" + args[2] : "jexus|lextudio.com"; JexusServer.Timeout = args.Length > 3 ? double.Parse(args[3]) : 30D; using (WebApp.Start<Startup>(url: baseAddress)) { Console.WriteLine("Remote services have started at {0}.", baseAddress); Console.WriteLine("Credentials is {0}", JexusServer.Credentials); Console.WriteLine("Press Enter to quit."); Console.ReadLine(); } }