// When called, generates the a cert for the machine DNS name with SAN localhost, and installs both certs // returns thumbprint of the machine certs public static X509Certificate2 CreateAndInstallLocalMachineCertificates(CertificateGenerator certificateGenerator) { if (certificateGenerator == null) { throw new ArgumentNullException("certificateGenerator"); } lock (s_certificateLock) { if (s_localCertificate != null) { return(s_localCertificate); } Trace.WriteLine("[CertificateManager] Installing Root and Machine certificates to machine store."); // At this point, we know we haven't generated the certs yet, or the operation is completing on another thread // Certificate generation is time-consuming, so we want to make sure that we don't unnecessarily generate a cert var rootCertificate = certificateGenerator.AuthorityCertificate.Certificate; var fqdn = Dns.GetHostEntry("127.0.0.1").HostName; var hostname = fqdn.Split('.')[0]; // always create a certificate locally for the current machine's fully qualified domain name, // hostname, and "localhost". CertificateCreationSettings certificateCreationSettings = new CertificateCreationSettings() { FriendlyName = "WCF Bridge - Machine certificate generated by the CertificateManager", Subject = fqdn, SubjectAlternativeNames = new string[] { fqdn, hostname, "localhost" } }; var hostCert = certificateGenerator.CreateMachineCertificate(certificateCreationSettings).Certificate; // Since s_myCertificates keys by subject name, we won't install a cert for the same subject twice // only the first-created cert will win InstallCertificateToRootStore(rootCertificate); InstallCertificateToMyStore(hostCert, certificateCreationSettings.ValidityType == CertificateValidityType.Valid); s_localCertificate = hostCert; // Create the PeerTrust cert certificateCreationSettings = new CertificateCreationSettings() { FriendlyName = "WCF Bridge - UserPeerTrustCertificateResource", Subject = fqdn, SubjectAlternativeNames = new string[] { fqdn, hostname, "localhost" } }; var peerCert = certificateGenerator.CreateMachineCertificate(certificateCreationSettings).Certificate; InstallCertificateToTrustedPeopleStore(peerCert, certificateCreationSettings.ValidityType == CertificateValidityType.Valid); } return(s_localCertificate); }
// We generate a local machine certificate for common usage. This method is usded to generate certs for non common usage, such as an expired cert. public static X509Certificate2 CreateAndInstallNonDefaultMachineCertificates(CertificateGenerator certificateGenerator, CertificateCreationSettings certificateCreationSettings, string resourceAddress) { if (certificateCreationSettings == null) { throw new ArgumentException("certificateCreationSettings cannot be null as we are creating a non default certificate"); } if (certificateGenerator == null) { throw new ArgumentNullException("certificateGenerator"); } lock (s_certificateLock) { Trace.WriteLine("[CertificateManager] Installing Non default Machine certificates to machine store."); var rootCertificate = certificateGenerator.AuthorityCertificate.Certificate; var hostCert = certificateGenerator.CreateMachineCertificate(certificateCreationSettings).Certificate; InstallCertificateToRootStore(rootCertificate); InstallCertificateToMyStore(hostCert, certificateCreationSettings.ValidityType == CertificateValidityType.Valid); return(hostCert); } }
private static int Main(string[] args) { ApplyAppSettings(); if (args.Length > 0) { if (string.Compare(args[0], "-Uninstall", true) == 0) { UninstallAllCerts(); return 0; } else if (string.Compare(args[0], "-help", true) == 0) { Usage(); return 0; } else { Usage(); return 1; } } UninstallAllCerts(); CertificateGenerator certificateGenerate = new CertificateGenerator(); certificateGenerate.CertificatePassword = "******"; certificateGenerate.CrlServiceUri = s_fqdn; certificateGenerate.ValidityPeriod = s_ValidatePeriod; if (!string.IsNullOrEmpty(s_testserverbase)) { certificateGenerate.CrlUriRelativePath += "/" + s_testserverbase; } certificateGenerate.CrlUriRelativePath += "/TestHost.svc/Crl"; //Create and install root and server cert CertificateManager.CreateAndInstallLocalMachineCertificates(certificateGenerate); //Create and Install expired cert CertificateCreationSettings certificateCreationSettings = new CertificateCreationSettings() { FriendlyName = "WCF Bridge - TcpExpiredServerCertResource", ValidityType = CertificateValidityType.Expired, ValidityNotBefore = DateTime.UtcNow - TimeSpan.FromDays(4), ValidityNotAfter = DateTime.UtcNow - TimeSpan.FromDays(2), //If you specify multiple subjects, the first one becomes the subject, and all of them become Subject Alt Names. //In this case, the certificate subject is CN=fqdn, OU=..., O=... , and SANs will be fqdn, hostname, localhost //We do this so that a single WCF service setup can deal with all the possible addresses that a client might use. Subject = s_fqdn, SubjectAlternativeNames = new string[] { s_fqdn, s_hostname, "localhost" } }; CreateAndInstallMachineCertificate(certificateGenerate, certificateCreationSettings); //Create and Install TcpCertificateWithServerAltName certificateCreationSettings = new CertificateCreationSettings() { FriendlyName = "WCF Bridge - TcpCertificateWithServerAltNameResource", Subject = "not-real-subject-name", SubjectAlternativeNames = new string[] { "not-real-subject-name", "not-real-subject-name.example.com", s_fqdn, s_hostname, "localhost" } }; CreateAndInstallMachineCertificate(certificateGenerate, certificateCreationSettings); //TcpCertificateWithSubjectCanonicalNameDomainName certificateCreationSettings = new CertificateCreationSettings() { FriendlyName = "WCF Bridge - TcpCertificateWithSubjectCanonicalNameDomainNameResource", Subject = s_hostname, SubjectAlternativeNames = new string[0], ValidityType = CertificateValidityType.NonAuthoritativeForMachine }; CreateAndInstallMachineCertificate(certificateGenerate, certificateCreationSettings); //WCF Bridge - TcpCertificateWithSubjectCanonicalNameFqdn certificateCreationSettings = new CertificateCreationSettings() { FriendlyName = "WCF Bridge - TcpCertificateWithSubjectCanonicalNameFqdnResource", Subject = s_fqdn, SubjectAlternativeNames = new string[0], ValidityType = CertificateValidityType.NonAuthoritativeForMachine }; CreateAndInstallMachineCertificate(certificateGenerate, certificateCreationSettings); //TcpCertificateWithSubjectCanonicalNameLocalhost certificateCreationSettings = new CertificateCreationSettings() { FriendlyName = "WCF Bridge - TcpCertificateWithSubjectCanonicalNameLocalhostResource", Subject = "localhost", SubjectAlternativeNames = new string[0], ValidityType = CertificateValidityType.NonAuthoritativeForMachine }; CreateAndInstallMachineCertificate(certificateGenerate, certificateCreationSettings); //TcpRevokedServerCert certificateCreationSettings = new CertificateCreationSettings() { FriendlyName = "WCF Bridge - TcpRevokedServerCertResource", ValidityType = CertificateValidityType.Revoked, Subject = s_fqdn, SubjectAlternativeNames = new string[] { s_fqdn, s_hostname, "localhost" } }; CreateAndInstallMachineCertificate(certificateGenerate, certificateCreationSettings); //Create and install client cert certificateCreationSettings = new CertificateCreationSettings() { FriendlyName = "WCF Bridge - UserCertificateResource", Subject = "WCF Client Certificate", }; X509Certificate2 certificate = certificateGenerate.CreateUserCertificate(certificateCreationSettings).Certificate; CertificateManager.AddToStoreIfNeeded(StoreName.My, StoreLocation.LocalMachine, certificate); //Create CRL and save it File.WriteAllBytes(s_CrlFileLocation, certificateGenerate.CrlEncoded); return 0; }
private static void CreateAndInstallMachineCertificate(CertificateGenerator certificateGenerate, CertificateCreationSettings certificateCreationSettings) { X509Certificate2 certificate = certificateGenerate.CreateMachineCertificate(certificateCreationSettings).Certificate; CertificateManager.AddToStoreIfNeeded(StoreName.My, StoreLocation.LocalMachine, certificate); }
// Only the ctor should be calling with isAuthority = true // if isAuthority, value for isMachineCert doesn't matter private X509CertificateContainer CreateCertificate(bool isAuthority, bool isMachineCert, X509Certificate signingCertificate, CertificateCreationSettings certificateCreationSettings) { if (certificateCreationSettings == null) { if (isAuthority) { certificateCreationSettings = new CertificateCreationSettings(); } else { throw new Exception("Parameter certificateCreationSettings cannot be null when isAuthority is false"); } } // Set to default cert creation settings if not set if (certificateCreationSettings.ValidityNotBefore == default(DateTime)) { certificateCreationSettings.ValidityNotBefore = _defaultValidityNotBefore; } if (certificateCreationSettings.ValidityNotAfter == default(DateTime)) { certificateCreationSettings.ValidityNotAfter = _defaultValidityNotAfter; } if (!isAuthority ^ (signingCertificate != null)) { throw new ArgumentException("Either isAuthority == true or signingCertificate is not null"); } string subject = certificateCreationSettings.Subject; // If certificateCreationSettings.SubjectAlternativeNames == null, then we should add exactly one SubjectAlternativeName == Subject // so that the default certificate generated is compatible with mainline scenarios // However, if certificateCreationSettings.SubjectAlternativeNames == string[0], then allow this as this is a legit scenario we want to test out if (certificateCreationSettings.SubjectAlternativeNames == null) { certificateCreationSettings.SubjectAlternativeNames = new string[1] { subject }; } string[] subjectAlternativeNames = certificateCreationSettings.SubjectAlternativeNames; if (!isAuthority && string.IsNullOrWhiteSpace(subject)) { throw new ArgumentException("Certificate Subject must not be an empty string or only whitespace", "creationSettings.Subject"); } EnsureInitialized(); s_certGenerator.Reset(); s_certGenerator.SetSignatureAlgorithm(_signatureAlthorithm); // Tag on the generation time to prevent caching of the cert CRL in Linux X509Name authorityX509Name = CreateX509Name(string.Format("{0} {1}", _authorityCanonicalName, DateTime.Now.ToString("s"))); var serialNum = new BigInteger(64 /*sizeInBits*/, _random).Abs(); var keyPair = isAuthority ? _authorityKeyPair : _keyPairGenerator.GenerateKeyPair(); if (isAuthority) { s_certGenerator.SetIssuerDN(authorityX509Name); s_certGenerator.SetSubjectDN(authorityX509Name); var authorityKeyIdentifier = new AuthorityKeyIdentifier( SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(_authorityKeyPair.Public), new GeneralNames(new GeneralName(authorityX509Name)), serialNum); s_certGenerator.AddExtension(X509Extensions.AuthorityKeyIdentifier, false, authorityKeyIdentifier); s_certGenerator.AddExtension(X509Extensions.KeyUsage, false, new KeyUsage(X509KeyUsage.DigitalSignature | X509KeyUsage.KeyAgreement | X509KeyUsage.KeyCertSign | X509KeyUsage.KeyEncipherment | X509KeyUsage.CrlSign)); } else { X509Name subjectName = CreateX509Name(subject); s_certGenerator.SetIssuerDN(PrincipalUtilities.GetSubjectX509Principal(signingCertificate)); s_certGenerator.SetSubjectDN(subjectName); s_certGenerator.AddExtension(X509Extensions.AuthorityKeyIdentifier, false, new AuthorityKeyIdentifierStructure(_authorityKeyPair.Public)); s_certGenerator.AddExtension(X509Extensions.KeyUsage, false, new KeyUsage(X509KeyUsage.DigitalSignature | X509KeyUsage.KeyAgreement | X509KeyUsage.KeyEncipherment)); } s_certGenerator.AddExtension(X509Extensions.SubjectKeyIdentifier, false, new SubjectKeyIdentifierStructure(keyPair.Public)); s_certGenerator.SetSerialNumber(serialNum); s_certGenerator.SetNotBefore(certificateCreationSettings.ValidityNotBefore); s_certGenerator.SetNotAfter(certificateCreationSettings.ValidityNotAfter); s_certGenerator.SetPublicKey(keyPair.Public); s_certGenerator.AddExtension(X509Extensions.BasicConstraints, true, new BasicConstraints(isAuthority)); s_certGenerator.AddExtension(X509Extensions.ExtendedKeyUsage, false, new ExtendedKeyUsage(KeyPurposeID.IdKPServerAuth, KeyPurposeID.IdKPClientAuth)); if (!isAuthority) { if (isMachineCert) { List <Asn1Encodable> subjectAlternativeNamesAsAsn1EncodableList = new List <Asn1Encodable>(); // All endpoints should also be in the Subject Alt Names for (int i = 0; i < subjectAlternativeNames.Length; i++) { if (!string.IsNullOrWhiteSpace(subjectAlternativeNames[i])) { // Machine certs can have additional DNS names subjectAlternativeNamesAsAsn1EncodableList.Add(new GeneralName(GeneralName.DnsName, subjectAlternativeNames[i])); } } s_certGenerator.AddExtension(X509Extensions.SubjectAlternativeName, true, new DerSequence(subjectAlternativeNamesAsAsn1EncodableList.ToArray())); } else { if (subjectAlternativeNames.Length > 1) { var subjectAlternativeNamesAsAsn1EncodableList = new Asn1EncodableVector(); // Only add a SAN for the user if there are any for (int i = 1; i < subjectAlternativeNames.Length; i++) { if (!string.IsNullOrWhiteSpace(subjectAlternativeNames[i])) { Asn1EncodableVector otherNames = new Asn1EncodableVector(); otherNames.Add(new DerObjectIdentifier(_upnObjectId)); otherNames.Add(new DerTaggedObject(true, 0, new DerUtf8String(subjectAlternativeNames[i]))); Asn1Object genName = new DerTaggedObject(false, 0, new DerSequence(otherNames)); subjectAlternativeNamesAsAsn1EncodableList.Add(genName); } } s_certGenerator.AddExtension(X509Extensions.SubjectAlternativeName, true, new DerSequence(subjectAlternativeNamesAsAsn1EncodableList)); } } } if (isAuthority || certificateCreationSettings.IncludeCrlDistributionPoint) { var crlDistributionPoints = new DistributionPoint[1] { new DistributionPoint( new DistributionPointName( new GeneralNames( new GeneralName( GeneralName.UniformResourceIdentifier, string.Format("{0}", _crlUri, serialNum.ToString(radix: 16))))), null, null) }; var revocationListExtension = new CrlDistPoint(crlDistributionPoints); s_certGenerator.AddExtension(X509Extensions.CrlDistributionPoints, false, revocationListExtension); } X509Certificate cert = s_certGenerator.Generate(_authorityKeyPair.Private, _random); switch (certificateCreationSettings.ValidityType) { case CertificateValidityType.Revoked: RevokeCertificateBySerialNumber(serialNum.ToString(radix: 16)); break; case CertificateValidityType.Expired: break; default: EnsureCertificateIsValid(cert); break; } // For now, given that we don't know what format to return it in, preserve the formats so we have // the flexibility to do what we need to X509CertificateContainer container = new X509CertificateContainer(); X509CertificateEntry[] chain = new X509CertificateEntry[1]; chain[0] = new X509CertificateEntry(cert); Pkcs12Store store = new Pkcs12StoreBuilder().Build(); store.SetKeyEntry( certificateCreationSettings.FriendlyName != null ? certificateCreationSettings.FriendlyName : string.Empty, new AsymmetricKeyEntry(keyPair.Private), chain); using (MemoryStream stream = new MemoryStream()) { store.Save(stream, _password.ToCharArray(), _random); container.Pfx = stream.ToArray(); } X509Certificate2 outputCert; if (isAuthority) { // don't hand out the private key for the cert when it's the authority outputCert = new X509Certificate2(cert.GetEncoded()); } else { // Otherwise, allow encode with the private key. note that X509Certificate2.RawData will not provide the private key // you will have to re-export this cert if needed outputCert = new X509Certificate2(container.Pfx, _password, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet); } container.Subject = subject; container.InternalCertificate = cert; container.Certificate = outputCert; container.Thumbprint = outputCert.Thumbprint; Trace.WriteLine("[CertificateGenerator] generated a certificate:"); Trace.WriteLine(string.Format(" {0} = {1}", "isAuthority", isAuthority)); if (!isAuthority) { Trace.WriteLine(string.Format(" {0} = {1}", "Signed by", signingCertificate.SubjectDN)); Trace.WriteLine(string.Format(" {0} = {1}", "Subject (CN) ", subject)); Trace.WriteLine(string.Format(" {0} = {1}", "Subject Alt names ", string.Join(", ", subjectAlternativeNames))); Trace.WriteLine(string.Format(" {0} = {1}", "Friendly Name ", certificateCreationSettings.FriendlyName)); } Trace.WriteLine(string.Format(" {0} = {1}", "HasPrivateKey:", outputCert.HasPrivateKey)); Trace.WriteLine(string.Format(" {0} = {1}", "Thumbprint", outputCert.Thumbprint)); Trace.WriteLine(string.Format(" {0} = {1}", "CertificateValidityType", certificateCreationSettings.ValidityType)); return(container); }
public X509CertificateContainer CreateUserCertificate(CertificateCreationSettings creationSettings) { EnsureInitialized(); return(CreateCertificate(false, false, _authorityCertificate.InternalCertificate, creationSettings)); }
// Only the ctor should be calling with isAuthority = true // if isAuthority, value for isMachineCert doesn't matter private X509CertificateContainer CreateCertificate(bool isAuthority, bool isMachineCert, X509Certificate signingCertificate, CertificateCreationSettings certificateCreationSettings) { if (certificateCreationSettings == null) { if (isAuthority) { certificateCreationSettings = new CertificateCreationSettings(); } else { throw new Exception("Parameter certificateCreationSettings cannot be null when isAuthority is false"); } } // Set to default cert creation settings if not set if (certificateCreationSettings.ValidityNotBefore == default(DateTime)) { certificateCreationSettings.ValidityNotBefore = _defaultValidityNotBefore; } if (certificateCreationSettings.ValidityNotAfter == default(DateTime)) { certificateCreationSettings.ValidityNotAfter = _defaultValidityNotAfter; } if (!isAuthority ^ (signingCertificate != null)) { throw new ArgumentException("Either isAuthority == true or signingCertificate is not null"); } string subject = certificateCreationSettings.Subject; // If certificateCreationSettings.SubjectAlternativeNames == null, then we should add exactly one SubjectAlternativeName == Subject // so that the default certificate generated is compatible with mainline scenarios // However, if certificateCreationSettings.SubjectAlternativeNames == string[0], then allow this as this is a legit scenario we want to test out if (certificateCreationSettings.SubjectAlternativeNames == null) { certificateCreationSettings.SubjectAlternativeNames = new string[1] { subject }; } string[] subjectAlternativeNames = certificateCreationSettings.SubjectAlternativeNames; if (!isAuthority && string.IsNullOrWhiteSpace(subject)) { throw new ArgumentException("Certificate Subject must not be an empty string or only whitespace", "creationSettings.Subject"); } EnsureInitialized(); s_certGenerator.Reset(); s_certGenerator.SetSignatureAlgorithm(_signatureAlthorithm); // Tag on the generation time to prevent caching of the cert CRL in Linux X509Name authorityX509Name = CreateX509Name(string.Format("{0} {1}", _authorityCanonicalName, DateTime.Now.ToString("s"))); var serialNum = new BigInteger(64 /*sizeInBits*/, _random).Abs(); var keyPair = isAuthority ? _authorityKeyPair : _keyPairGenerator.GenerateKeyPair(); if (isAuthority) { s_certGenerator.SetIssuerDN(authorityX509Name); s_certGenerator.SetSubjectDN(authorityX509Name); var authorityKeyIdentifier = new AuthorityKeyIdentifier( SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(_authorityKeyPair.Public), new GeneralNames(new GeneralName(authorityX509Name)), serialNum); s_certGenerator.AddExtension(X509Extensions.AuthorityKeyIdentifier, false, authorityKeyIdentifier); s_certGenerator.AddExtension(X509Extensions.KeyUsage, false, new KeyUsage(X509KeyUsage.DigitalSignature | X509KeyUsage.KeyAgreement | X509KeyUsage.KeyCertSign | X509KeyUsage.KeyEncipherment | X509KeyUsage.CrlSign)); } else { X509Name subjectName = CreateX509Name(subject); s_certGenerator.SetIssuerDN(PrincipalUtilities.GetSubjectX509Principal(signingCertificate)); s_certGenerator.SetSubjectDN(subjectName); s_certGenerator.AddExtension(X509Extensions.AuthorityKeyIdentifier, false, new AuthorityKeyIdentifierStructure(_authorityKeyPair.Public)); s_certGenerator.AddExtension(X509Extensions.KeyUsage, false, new KeyUsage(X509KeyUsage.DigitalSignature | X509KeyUsage.KeyAgreement | X509KeyUsage.KeyEncipherment)); } s_certGenerator.AddExtension(X509Extensions.SubjectKeyIdentifier, false, new SubjectKeyIdentifierStructure(keyPair.Public)); s_certGenerator.SetSerialNumber(serialNum); s_certGenerator.SetNotBefore(certificateCreationSettings.ValidityNotBefore); s_certGenerator.SetNotAfter(certificateCreationSettings.ValidityNotAfter); s_certGenerator.SetPublicKey(keyPair.Public); s_certGenerator.AddExtension(X509Extensions.BasicConstraints, true, new BasicConstraints(isAuthority)); s_certGenerator.AddExtension(X509Extensions.ExtendedKeyUsage, false, new ExtendedKeyUsage(KeyPurposeID.IdKPServerAuth, KeyPurposeID.IdKPClientAuth)); if (!isAuthority) { if (isMachineCert) { List<Asn1Encodable> subjectAlternativeNamesAsAsn1EncodableList = new List<Asn1Encodable>(); // All endpoints should also be in the Subject Alt Names for (int i = 0; i < subjectAlternativeNames.Length; i++) { if (!string.IsNullOrWhiteSpace(subjectAlternativeNames[i])) { // Machine certs can have additional DNS names subjectAlternativeNamesAsAsn1EncodableList.Add(new GeneralName(GeneralName.DnsName, subjectAlternativeNames[i])); } } s_certGenerator.AddExtension(X509Extensions.SubjectAlternativeName, true, new DerSequence(subjectAlternativeNamesAsAsn1EncodableList.ToArray())); } else { if (subjectAlternativeNames.Length > 1) { var subjectAlternativeNamesAsAsn1EncodableList = new Asn1EncodableVector(); // Only add a SAN for the user if there are any for (int i = 1; i < subjectAlternativeNames.Length; i++) { if (!string.IsNullOrWhiteSpace(subjectAlternativeNames[i])) { Asn1EncodableVector otherNames = new Asn1EncodableVector(); otherNames.Add(new DerObjectIdentifier(_upnObjectId)); otherNames.Add(new DerTaggedObject(true, 0, new DerUtf8String(subjectAlternativeNames[i]))); Asn1Object genName = new DerTaggedObject(false, 0, new DerSequence(otherNames)); subjectAlternativeNamesAsAsn1EncodableList.Add(genName); } } s_certGenerator.AddExtension(X509Extensions.SubjectAlternativeName, true, new DerSequence(subjectAlternativeNamesAsAsn1EncodableList)); } } } if (isAuthority || certificateCreationSettings.IncludeCrlDistributionPoint) { var crlDistributionPoints = new DistributionPoint[1] { new DistributionPoint( new DistributionPointName( new GeneralNames( new GeneralName( GeneralName.UniformResourceIdentifier, string.Format("{0}", _crlUri, serialNum.ToString(radix: 16))))), null, null) }; var revocationListExtension = new CrlDistPoint(crlDistributionPoints); s_certGenerator.AddExtension(X509Extensions.CrlDistributionPoints, false, revocationListExtension); } X509Certificate cert = s_certGenerator.Generate(_authorityKeyPair.Private, _random); switch (certificateCreationSettings.ValidityType) { case CertificateValidityType.Revoked: RevokeCertificateBySerialNumber(serialNum.ToString(radix: 16)); break; case CertificateValidityType.Expired: break; default: EnsureCertificateIsValid(cert); break; } // For now, given that we don't know what format to return it in, preserve the formats so we have // the flexibility to do what we need to X509CertificateContainer container = new X509CertificateContainer(); X509CertificateEntry[] chain = new X509CertificateEntry[1]; chain[0] = new X509CertificateEntry(cert); Pkcs12Store store = new Pkcs12StoreBuilder().Build(); store.SetKeyEntry( certificateCreationSettings.FriendlyName != null ? certificateCreationSettings.FriendlyName : string.Empty, new AsymmetricKeyEntry(keyPair.Private), chain); using (MemoryStream stream = new MemoryStream()) { store.Save(stream, _password.ToCharArray(), _random); container.Pfx = stream.ToArray(); } X509Certificate2 outputCert; if (isAuthority) { // don't hand out the private key for the cert when it's the authority outputCert = new X509Certificate2(cert.GetEncoded()); } else { // Otherwise, allow encode with the private key. note that X509Certificate2.RawData will not provide the private key // you will have to re-export this cert if needed outputCert = new X509Certificate2(container.Pfx, _password, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet); } container.Subject = subject; container.InternalCertificate = cert; container.Certificate = outputCert; container.Thumbprint = outputCert.Thumbprint; Trace.WriteLine("[CertificateGenerator] generated a certificate:"); Trace.WriteLine(string.Format(" {0} = {1}", "isAuthority", isAuthority)); if (!isAuthority) { Trace.WriteLine(string.Format(" {0} = {1}", "Signed by", signingCertificate.SubjectDN)); Trace.WriteLine(string.Format(" {0} = {1}", "Subject (CN) ", subject)); Trace.WriteLine(string.Format(" {0} = {1}", "Subject Alt names ", string.Join(", ", subjectAlternativeNames))); Trace.WriteLine(string.Format(" {0} = {1}", "Friendly Name ", certificateCreationSettings.FriendlyName)); } Trace.WriteLine(string.Format(" {0} = {1}", "HasPrivateKey:", outputCert.HasPrivateKey)); Trace.WriteLine(string.Format(" {0} = {1}", "Thumbprint", outputCert.Thumbprint)); Trace.WriteLine(string.Format(" {0} = {1}", "CertificateValidityType", certificateCreationSettings.ValidityType)); return container; }
public X509CertificateContainer CreateUserCertificate(CertificateCreationSettings creationSettings) { EnsureInitialized(); return CreateCertificate(false, false, _authorityCertificate.InternalCertificate, creationSettings); }
// We generate a local machine certificate for common usage. This method is usded to generate certs for non common usage, such as an expired cert. public static X509Certificate2 CreateAndInstallNonDefaultMachineCertificates(CertificateGenerator certificateGenerator, CertificateCreationSettings certificateCreationSettings, string resourceAddress) { if (certificateCreationSettings == null) { throw new ArgumentException("certificateCreationSettings cannot be null as we are creating a non default certificate"); } if (certificateGenerator == null) { throw new ArgumentNullException("certificateGenerator"); } lock (s_certificateLock) { Trace.WriteLine("[CertificateManager] Installing Non default Machine certificates to machine store."); var rootCertificate = certificateGenerator.AuthorityCertificate.Certificate; var hostCert = certificateGenerator.CreateMachineCertificate(certificateCreationSettings).Certificate; InstallCertificateToRootStore(rootCertificate); InstallCertificateToMyStore(hostCert, certificateCreationSettings.ValidityType == CertificateValidityType.Valid); return hostCert; } }
// When called, generates the a cert for the machine DNS name with SAN localhost, and installs both certs // returns thumbprint of the machine certs public static X509Certificate2 CreateAndInstallLocalMachineCertificates(CertificateGenerator certificateGenerator) { if (certificateGenerator == null) { throw new ArgumentNullException("certificateGenerator"); } lock (s_certificateLock) { if (s_localCertificate != null) { return s_localCertificate; } Trace.WriteLine("[CertificateManager] Installing Root and Machine certificates to machine store."); // At this point, we know we haven't generated the certs yet, or the operation is completing on another thread // Certificate generation is time-consuming, so we want to make sure that we don't unnecessarily generate a cert var rootCertificate = certificateGenerator.AuthorityCertificate.Certificate; var fqdn = Dns.GetHostEntry("127.0.0.1").HostName; var hostname = fqdn.Split('.')[0]; // always create a certificate locally for the current machine's fully qualified domain name, // hostname, and "localhost". CertificateCreationSettings certificateCreationSettings = new CertificateCreationSettings() { FriendlyName = "WCF Bridge - Machine certificate generated by the CertificateManager", Subject = fqdn, SubjectAlternativeNames = new string[] { fqdn, hostname, "localhost" } }; var hostCert = certificateGenerator.CreateMachineCertificate(certificateCreationSettings).Certificate; // Since s_myCertificates keys by subject name, we won't install a cert for the same subject twice // only the first-created cert will win InstallCertificateToRootStore(rootCertificate); InstallCertificateToMyStore(hostCert, certificateCreationSettings.ValidityType == CertificateValidityType.Valid); s_localCertificate = hostCert; // Create the PeerTrust cert certificateCreationSettings = new CertificateCreationSettings() { FriendlyName = "WCF Bridge - UserPeerTrustCertificateResource", Subject = fqdn, SubjectAlternativeNames = new string[] { fqdn, hostname, "localhost" } }; var peerCert = certificateGenerator.CreateMachineCertificate(certificateCreationSettings).Certificate; InstallCertificateToTrustedPeopleStore(peerCert, certificateCreationSettings.ValidityType == CertificateValidityType.Valid); } return s_localCertificate; }