public static void ReproduceBigExponentCert() { DateTimeOffset notBefore = new DateTimeOffset(2016, 3, 2, 1, 48, 0, TimeSpan.Zero); DateTimeOffset notAfter = new DateTimeOffset(2017, 3, 2, 1, 48, 0, TimeSpan.Zero); byte[] serialNumber = "9B5DE6C15126A58B".HexToByteArray(); var subject = new X500DistinguishedName( "CN=localhost, OU=.NET Framework (CoreFX), O=Microsoft Corporation, L=Redmond, S=Washington, C=US"); X509Extension skidExtension = new X509SubjectKeyIdentifierExtension( "78A5C75D51667331D5A96924114C9B5FA00D7BCB", false); X509Extension akidExtension = new X509Extension( "2.5.29.35", "3016801478A5C75D51667331D5A96924114C9B5FA00D7BCB".HexToByteArray(), false); X509Extension basicConstraints = new X509BasicConstraintsExtension(true, false, 0, false); X509Certificate2 cert; using (RSA rsa = RSA.Create()) { rsa.ImportParameters(TestData.RsaBigExponentParams); var request = new CertificateRequest(subject, rsa, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); request.CertificateExtensions.Add(skidExtension); request.CertificateExtensions.Add(akidExtension); request.CertificateExtensions.Add(basicConstraints); var signatureGenerator = X509SignatureGenerator.CreateForRSA(rsa, RSASignaturePadding.Pkcs1); cert = request.Create(subject, signatureGenerator, notBefore, notAfter, serialNumber); } const string expectedHex = "308203EB308202D3A0030201020209009B5DE6C15126A58B300D06092A864886" + "F70D01010B050030818A310B3009060355040613025553311330110603550408" + "130A57617368696E67746F6E3110300E060355040713075265646D6F6E64311E" + "301C060355040A13154D6963726F736F667420436F72706F726174696F6E3120" + "301E060355040B13172E4E4554204672616D65776F726B2028436F7265465829" + "31123010060355040313096C6F63616C686F7374301E170D3136303330323031" + "343830305A170D3137303330323031343830305A30818A310B30090603550406" + "13025553311330110603550408130A57617368696E67746F6E3110300E060355" + "040713075265646D6F6E64311E301C060355040A13154D6963726F736F667420" + "436F72706F726174696F6E3120301E060355040B13172E4E4554204672616D65" + "776F726B2028436F726546582931123010060355040313096C6F63616C686F73" + "7430820124300D06092A864886F70D010101050003820111003082010C028201" + "0100AF81C1CBD8203F624A539ED6608175372393A2837D4890E48A19DED36973" + "115620968D6BE0D3DAA38AA777BE02EE0B6B93B724E8DCC12B632B4FA80BBC92" + "5BCE624F4CA7CC606306B39403E28C932D24DD546FFE4EF6A37F10770B2215EA" + "8CBB5BF427E8C4D89B79EB338375100C5F83E55DE9B4466DDFBEEE42539AEF33" + "EF187B7760C3B1A1B2103C2D8144564A0C1039A09C85CF6B5974EB516FC8D662" + "3C94AE3A5A0BB3B4C792957D432391566CF3E2A52AFB0C142B9E0681B8972671" + "AF2B82DD390A39B939CF719568687E4990A63050CA7768DCD6B378842F18FDB1" + "F6D9FF096BAF7BEB98DCF930D66FCFD503F58D41BFF46212E24E3AFC45EA42BD" + "884702050200000441A350304E301D0603551D0E0416041478A5C75D51667331" + "D5A96924114C9B5FA00D7BCB301F0603551D2304183016801478A5C75D516673" + "31D5A96924114C9B5FA00D7BCB300C0603551D13040530030101FF300D06092A" + "864886F70D01010B0500038201010077756D05FFA6ADFED5B6D4AFB540840C6D" + "01CF6B3FA6C973DFD61FCAA0A814FA1E2469019D94B1D856D07DD2B95B8550DF" + "D2085953A494B99EFCBAA7982CE771984F9D4A445FFEE062E8A049736A39FD99" + "4E1FDA0A5DC2B5B0E57A0B10C41BC7FE6A40B24F85977302593E60B98DD4811D" + "47D948EDF8D6E6B5AF80A1827496E20BFD240E467674504D4E4703331D64705C" + "36FB6E14BABFD9CBEEC44B33A8D7B36479900F3C5BBAB69C5E453D180783E250" + "8051B998C038E4622571D2AB891D898E5458828CF18679517D28DBCABF72E813" + "07BFD721B73DDB1751123F99D8FC0D533798C4DBD14719D5D8A85B00A144A367" + "677B48891A9B56F045334811BACB7A"; Assert.Equal(expectedHex, cert.RawData.ByteArrayToHex()); }
public void CreateForECDsaWithGeneratorTest( ECCurveHashPair ecCurveHashPair ) { // default signing cert with custom key X509Certificate2 signingCert = CertificateBuilder.Create(Subject) .SetCAConstraint() .SetHashAlgorithm(HashAlgorithmName.SHA512) .SetECCurve(ecCurveHashPair.Curve) .CreateForECDsa(); WriteCertificate(signingCert, $"Signing ECDsa {signingCert.GetECDsaPublicKey().KeySize} cert"); using (ECDsa ecdsaPrivateKey = signingCert.GetECDsaPrivateKey()) { var generator = X509SignatureGenerator.CreateForECDsa(ecdsaPrivateKey); var cert = CertificateBuilder.Create("CN=App Cert") .SetIssuer(new X509Certificate2(signingCert.RawData)) .CreateForRSA(generator); Assert.NotNull(cert); WriteCertificate(cert, "Default signed ECDsa cert"); } using (ECDsa ecdsaPrivateKey = signingCert.GetECDsaPrivateKey()) using (ECDsa ecdsaPublicKey = signingCert.GetECDsaPublicKey()) { var generator = X509SignatureGenerator.CreateForECDsa(ecdsaPrivateKey); var cert = CertificateBuilder.Create("CN=App Cert") .SetHashAlgorithm(ecCurveHashPair.HashAlgorithmName) .SetIssuer(new X509Certificate2(signingCert.RawData)) .SetECDsaPublicKey(ecdsaPublicKey) .CreateForECDsa(generator); Assert.NotNull(cert); WriteCertificate(cert, "Default signed ECDsa cert with Public Key"); } using (ECDsa ecdsaPrivateKey = signingCert.GetECDsaPrivateKey()) { var generator = X509SignatureGenerator.CreateForECDsa(ecdsaPrivateKey); var cert = CertificateBuilder.Create("CN=App Cert") .SetHashAlgorithm(ecCurveHashPair.HashAlgorithmName) .SetIssuer(new X509Certificate2(signingCert.RawData)) .SetECCurve(ecCurveHashPair.Curve) .CreateForECDsa(generator); Assert.NotNull(cert); WriteCertificate(cert, "Default signed RSA cert"); CheckPEMWriter(cert); } // ensure invalid path throws argument exception Assert.Throws <NotSupportedException>(() => { using (ECDsa ecdsaPrivateKey = signingCert.GetECDsaPrivateKey()) { var generator = X509SignatureGenerator.CreateForECDsa(ecdsaPrivateKey); var cert = CertificateBuilder.Create("CN=App Cert") .SetHashAlgorithm(ecCurveHashPair.HashAlgorithmName) .SetECCurve(ecCurveHashPair.Curve) .CreateForECDsa(generator); } }); }
public static void RsaPkcsSignatureGeneratorCtor_Exceptions() { AssertExtensions.Throws <ArgumentNullException>( "key", () => X509SignatureGenerator.CreateForRSA(null, RSASignaturePadding.Pkcs1)); }
internal RSASha1Pkcs1SignatureGenerator(RSA rsa) { _realRsaGenerator = X509SignatureGenerator.CreateForRSA(rsa, RSASignaturePadding.Pkcs1); }
/// <summary> /// Creates a KeyVault signed certificate. /// </summary> /// <returns>The signed certificate</returns> public static Task <X509Certificate2> CreateSignedCertificate( string subjectName, ushort keySize, DateTime notBefore, DateTime notAfter, ushort hashSizeInBits, X509Certificate2 issuerCAKeyCert, RSA publicKey, X509SignatureGenerator generator, bool caCert = false) { if (publicKey == null) { throw new NotSupportedException("Need a public key and a CA certificate."); } if (publicKey.KeySize != keySize) { throw new NotSupportedException(string.Format("Public key size {0} does not match expected key size {1}", publicKey.KeySize, keySize)); } // new serial number byte[] serialNumber = new byte[SerialNumberLength]; RandomNumberGenerator.Fill(serialNumber); serialNumber[0] &= 0x7F; var subjectDN = new X500DistinguishedName(subjectName); var request = new CertificateRequest(subjectDN, publicKey, GetRSAHashAlgorithmName(hashSizeInBits), RSASignaturePadding.Pkcs1); // Basic constraints request.CertificateExtensions.Add( new X509BasicConstraintsExtension(caCert, caCert, 0, true)); // Subject Key Identifier var ski = new X509SubjectKeyIdentifierExtension( request.PublicKey, X509SubjectKeyIdentifierHashAlgorithm.Sha1, false); request.CertificateExtensions.Add(ski); // Authority Key Identifier if (issuerCAKeyCert != null) { request.CertificateExtensions.Add(BuildAuthorityKeyIdentifier(issuerCAKeyCert)); } else { request.CertificateExtensions.Add(BuildAuthorityKeyIdentifier(subjectDN, serialNumber.Reverse().ToArray(), ski)); } if (caCert) { request.CertificateExtensions.Add( new X509KeyUsageExtension( X509KeyUsageFlags.DigitalSignature | X509KeyUsageFlags.KeyCertSign | X509KeyUsageFlags.CrlSign, true)); } else { // Key Usage X509KeyUsageFlags defaultFlags = X509KeyUsageFlags.DigitalSignature | X509KeyUsageFlags.DataEncipherment | X509KeyUsageFlags.NonRepudiation | X509KeyUsageFlags.KeyEncipherment; request.CertificateExtensions.Add(new X509KeyUsageExtension(defaultFlags, true)); // Enhanced key usage request.CertificateExtensions.Add( new X509EnhancedKeyUsageExtension( new OidCollection { new Oid("1.3.6.1.5.5.7.3.1"), new Oid("1.3.6.1.5.5.7.3.2") }, true)); } if (issuerCAKeyCert != null) { if (notAfter > issuerCAKeyCert.NotAfter) { notAfter = issuerCAKeyCert.NotAfter; } if (notBefore < issuerCAKeyCert.NotBefore) { notBefore = issuerCAKeyCert.NotBefore; } } var issuerSubjectName = issuerCAKeyCert != null ? issuerCAKeyCert.SubjectName : subjectDN; X509Certificate2 signedCert = request.Create( issuerSubjectName, generator, notBefore, notAfter, serialNumber ); return(Task.FromResult(signedCert)); }
public static void ECDsaX509SignatureGeneratorCtor_Exceptions() { Assert.Throws <ArgumentNullException>( "key", () => X509SignatureGenerator.CreateForECDsa(null)); }
public void CreateForRSAWithGeneratorTest( KeyHashPair keyHashPair ) { // default signing cert with custom key using (X509Certificate2 signingCert = CertificateBuilder.Create(Subject) .SetCAConstraint() .SetHashAlgorithm(HashAlgorithmName.SHA512) .SetRSAKeySize(2048) .CreateForRSA()) { WriteCertificate(signingCert, $"Signing RSA {signingCert.GetRSAPublicKey().KeySize} cert"); using (RSA rsaPrivateKey = signingCert.GetRSAPrivateKey()) { var generator = X509SignatureGenerator.CreateForRSA(rsaPrivateKey, RSASignaturePadding.Pkcs1); using (var issuer = new X509Certificate2(signingCert.RawData)) using (var cert = CertificateBuilder.Create("CN=App Cert") .SetIssuer(issuer) .CreateForRSA(generator)) { Assert.NotNull(cert); WriteCertificate(cert, "Default signed RSA cert"); } } using (RSA rsaPrivateKey = signingCert.GetRSAPrivateKey()) using (RSA rsaPublicKey = signingCert.GetRSAPublicKey()) { var generator = X509SignatureGenerator.CreateForRSA(rsaPrivateKey, RSASignaturePadding.Pkcs1); using (var issuer = new X509Certificate2(signingCert.RawData)) using (var cert = CertificateBuilder.Create("CN=App Cert") .SetHashAlgorithm(keyHashPair.HashAlgorithmName) .SetIssuer(issuer) .SetRSAPublicKey(rsaPublicKey) .CreateForRSA(generator)) { Assert.NotNull(cert); WriteCertificate(cert, "Default signed RSA cert with Public Key"); } } using (RSA rsaPrivateKey = signingCert.GetRSAPrivateKey()) { var generator = X509SignatureGenerator.CreateForRSA(rsaPrivateKey, RSASignaturePadding.Pkcs1); using (var issuer = new X509Certificate2(signingCert.RawData)) using (var cert = CertificateBuilder.Create("CN=App Cert") .SetHashAlgorithm(keyHashPair.HashAlgorithmName) .SetIssuer(issuer) .SetRSAKeySize(keyHashPair.KeySize) .CreateForRSA(generator)) { Assert.NotNull(cert); WriteCertificate(cert, "Default signed RSA cert"); } } // ensure invalid path throws argument exception Assert.Throws <NotSupportedException>(() => { using (RSA rsaPrivateKey = signingCert.GetRSAPrivateKey()) { var generator = X509SignatureGenerator.CreateForRSA(rsaPrivateKey, RSASignaturePadding.Pkcs1); _ = CertificateBuilder.Create("CN=App Cert") .SetHashAlgorithm(keyHashPair.HashAlgorithmName) .SetRSAKeySize(keyHashPair.KeySize) .CreateForRSA(generator); } }); } }
public static void FractionalSecondsNotWritten(bool selfSigned) { using (X509Certificate2 savedCert = new X509Certificate2(TestData.PfxData, TestData.PfxDataPassword)) using (RSA rsa = savedCert.GetRSAPrivateKey()) { X500DistinguishedName subjectName = new X500DistinguishedName("CN=Test"); var request = new CertificateRequest( subjectName, rsa, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); // notBefore is a date before 2050 UTC (encoded using UTC TIME), // notAfter is a date after 2050 UTC (encoded using GENERALIZED TIME). DateTimeOffset notBefore = new DateTimeOffset(2049, 3, 4, 5, 6, 7, 89, TimeSpan.Zero); DateTimeOffset notAfter = notBefore.AddYears(2); Assert.NotEqual(0, notAfter.Millisecond); DateTimeOffset normalizedBefore = notBefore.AddMilliseconds(-notBefore.Millisecond); DateTimeOffset normalizedAfter = notAfter.AddMilliseconds(-notAfter.Millisecond); byte[] manualSerialNumber = { 3, 2, 1 }; X509Certificate2 cert; if (selfSigned) { cert = request.CreateSelfSigned(notBefore, notAfter); } else { cert = request.Create( subjectName, X509SignatureGenerator.CreateForRSA(rsa, RSASignaturePadding.Pkcs1), notBefore, notAfter, manualSerialNumber); } using (cert) { Assert.Equal(normalizedBefore.DateTime.ToLocalTime(), cert.NotBefore); Assert.Equal(normalizedAfter.DateTime.ToLocalTime(), cert.NotAfter); if (selfSigned) { // The serial number used in CreateSelfSigned is random, so find the issuer name, // and the validity period is the next 34 bytes. Verify it was encoded as expected. // // Since the random serial number is at most 9 bytes and the subjectName encoded // value is 17 bytes, there's no chance of an early false match. byte[] encodedCert = cert.RawData; byte[] needle = subjectName.RawData; int index = encodedCert.AsSpan().IndexOf(needle); Assert.Equal( "3020170D3439303330343035303630375A180F32303531303330343035303630375A", encodedCert.AsSpan(index + needle.Length, 34).ByteArrayToHex()); } else { // The entire encoding is deterministic in this mode. Assert.Equal( "308201953081FFA0030201020203030201300D06092A864886F70D01010B0500" + "300F310D300B06035504031304546573743020170D3439303330343035303630" + "375A180F32303531303330343035303630375A300F310D300B06035504031304" + "5465737430819F300D06092A864886F70D010101050003818D00308189028181" + "00B11E30EA87424A371E30227E933CE6BE0E65FF1C189D0D888EC8FF13AA7B42" + "B68056128322B21F2B6976609B62B6BC4CF2E55FF5AE64E9B68C78A3C2DACC91" + "6A1BC7322DD353B32898675CFB5B298B176D978B1F12313E3D865BC53465A11C" + "CA106870A4B5D50A2C410938240E92B64902BAEA23EB093D9599E9E372E48336" + "730203010001300D06092A864886F70D01010B0500038181000095ABC7CC7B01" + "9C2A88A7891165B6ACCDBC5137D80C0A5151B11FD4D789CCE808412ABF05FFB1" + "D9BE097776147A6D4C3EE177E5F9C2C9E8C005D72A6473F9904185B95634BFB4" + "EA80B232B271DC1BF20A2FDC46FC93771636B618F29417C31D5F602236FDB414" + "CDC1BEDE700E31E80DC5E7BB7D3F367420B72925605C916BDA", cert.RawData.ByteArrayToHex()); } } } }
private static void CreateAndTestChain( AsymmetricAlgorithm rootPrivKey, AsymmetricAlgorithm intermed1PrivKey, AsymmetricAlgorithm intermed2PrivKey, AsymmetricAlgorithm leafPubKey) { const string RootDN = "CN=Experimental Root Certificate"; const string Intermed1DN = "CN=First Intermediate Certificate, O=Experimental"; const string Intermed2DN = "CN=Second Intermediate Certificate, O=Experimental"; const string LeafDN = "CN=End-Entity Certificate, O=Experimental"; CertificateRequest rootRequest = CreateChainRequest(RootDN, rootPrivKey, HashAlgorithmName.SHA512, true, null); CertificateRequest intermed1Request = CreateChainRequest(Intermed1DN, intermed1PrivKey, HashAlgorithmName.SHA384, true, null); CertificateRequest intermed2Request = CreateChainRequest(Intermed2DN, intermed2PrivKey, HashAlgorithmName.SHA384, true, 0); CertificateRequest leafRequest = CreateChainRequest(LeafDN, leafPubKey, HashAlgorithmName.SHA256, false, null); leafRequest.CertificateExtensions.Add( new X509EnhancedKeyUsageExtension(new OidCollection { new Oid("1.3.6.1.5.5.7.3.1") }, false)); X509SignatureGenerator rootGenerator = OpenGenerator(rootPrivKey); X509SignatureGenerator intermed2Generator = OpenGenerator(intermed2PrivKey); X509Certificate2 rootCertWithKey = null; X509Certificate2 intermed1CertWithKey = null; X509Certificate2 intermed2CertWithKey = null; X509Certificate2 leafCert = null; try { DateTimeOffset now = DateTimeOffset.UtcNow; DateTimeOffset rootEnd = now + TimeSpan.FromDays(10000); DateTimeOffset intermedEnd = now + TimeSpan.FromDays(366 * 4); DateTimeOffset leafEnd = now + TimeSpan.FromDays(366 * 1.3); rootCertWithKey = rootRequest.CreateSelfSigned(now, rootEnd); byte[] intermed1Serial = new byte[10]; byte[] intermed2Serial = new byte[10]; byte[] leafSerial = new byte[10]; intermed1Serial[1] = 1; intermed2Serial[1] = 2; leafSerial[1] = 1; using (RandomNumberGenerator rng = RandomNumberGenerator.Create()) { rng.GetBytes(intermed1Serial, 2, intermed1Serial.Length - 2); rng.GetBytes(intermed2Serial, 2, intermed2Serial.Length - 2); rng.GetBytes(leafSerial, 2, leafSerial.Length - 2); } X509Certificate2 intermed1Tmp = intermed1Request.Create(rootCertWithKey.SubjectName, rootGenerator, now, intermedEnd, intermed1Serial); X509Certificate2 intermed2Tmp = intermed2Request.Create(rootCertWithKey.SubjectName, rootGenerator, now, intermedEnd, intermed1Serial); intermed1CertWithKey = CloneWithPrivateKey(intermed1Tmp, intermed1PrivKey); intermed2CertWithKey = CloneWithPrivateKey(intermed2Tmp, intermed2PrivKey); intermed1Tmp.Dispose(); intermed2Tmp.Dispose(); leafCert = leafRequest.Create( intermed2CertWithKey.SubjectName, intermed2Generator, now, leafEnd, leafSerial); using (X509Chain chain = new X509Chain()) { chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; chain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority; chain.ChainPolicy.ExtraStore.Add(intermed1CertWithKey); chain.ChainPolicy.ExtraStore.Add(intermed2CertWithKey); chain.ChainPolicy.ExtraStore.Add(rootCertWithKey); RunChain(chain, leafCert, true, "Initial chain build"); try { // Intermediate 1 plays no part. Assert.Equal(3, chain.ChainElements.Count); Assert.Equal(LeafDN, chain.ChainElements[0].Certificate.Subject); Assert.Equal(Intermed2DN, chain.ChainElements[1].Certificate.Subject); Assert.Equal(RootDN, chain.ChainElements[2].Certificate.Subject); } finally { DisposeChainCerts(chain); } // Server Auth EKU, expect true. chain.ChainPolicy.ApplicationPolicy.Add(new Oid("1.3.6.1.5.5.7.3.1")); RunChain(chain, leafCert, true, "Server auth EKU chain build"); DisposeChainCerts(chain); // Client Auth EKU, expect false chain.ChainPolicy.ApplicationPolicy.Add(new Oid("1.3.6.1.5.5.7.3.2")); RunChain(chain, leafCert, false, "Server and Client auth EKU chain build"); DisposeChainCerts(chain); } } finally { leafCert?.Dispose(); intermed2CertWithKey?.Dispose(); intermed1CertWithKey?.Dispose(); rootCertWithKey?.Dispose(); } }
public static void SignatureAlgorithm_Encoding(string hashAlgorithmName) { // PSS-MGF1-with-SHA-2-* end up differing in only three bytes: // 1) hashAlgorithm.algorithmId's last byte // 2) mgf.parameters.algorithmId's last byte // 3) saltLen. byte lastOidByte; byte saltLenByte; switch (hashAlgorithmName) { case "SHA256": lastOidByte = 0x01; saltLenByte = 256 / 8; break; case "SHA384": lastOidByte = 0x02; saltLenByte = 384 / 8; break; case "SHA512": lastOidByte = 0x03; saltLenByte = 512 / 8; break; default: throw new ArgumentOutOfRangeException(nameof(hashAlgorithmName)); } string expectedHex = // SEQUENCE (AlgorithmIdentifier) "303D" + // OBJECT IDENTIFIER (AlgorithmIdentifier.algorithm == Oids.RsaPss) "06092A864886F70D01010A" + // SEQUENCE (AlgorithmIdentifier.params == RSASSA-PSS-params) "3030" + // CONSTRUCTED CONTEXT SPECIFIC 0 (params.hashAlgorithm) "A00D" + // SEQUENCE (AlgorithmIdentifier) "300B" + // OBJECT IDENTIFIER (params.hashAlgorithm.algorithm) "06096086480165030402" + lastOidByte.ToString("X2") + // CONSTRUCTED CONTEXT SPECIFIC 1 (params.maskGenAlgorithm) "A11A" + // SEQUENCE (MaskGenAlgorithm) "3018" + // OBJECT IDENTIFIER (MaskGenAlgorithm.algorithm == Oids.Mgf1) "06092A864886F70D010108" + // SEQUENCE (MaskGenAlgorithm.params) "300B" + // OBJECT IDENTIFIER (MGF PRF == same hash algorithm as above) "06096086480165030402" + lastOidByte.ToString("X2") + // CONSTRUCTED CONTEXT SPECIFIC 2 (params.saltLength) "A203" + // INTEGER (saltLength == size of hash) "0201" + saltLenByte.ToString("X2"); using (RSA rsa = RSA.Create()) { RSAParameters parameters = TestData.RsaBigExponentParams; rsa.ImportParameters(parameters); HashAlgorithmName hashAlgorithm = new HashAlgorithmName(hashAlgorithmName); var signatureGenerator = X509SignatureGenerator.CreateForRSA(rsa, RSASignaturePadding.Pss); byte[] sigAlg = signatureGenerator.GetSignatureAlgorithmIdentifier(hashAlgorithm); Assert.Equal(expectedHex, sigAlg.ByteArrayToHex()); } }
internal static void MakeTestChain( ReadOnlySpan <RSA> keys, Span <X509Certificate2> certs, IEnumerable <X509Extension> endEntityExtensions, IEnumerable <X509Extension> intermediateExtensions, IEnumerable <X509Extension> rootExtensions, string testName) { if (keys.Length < 2) { throw new ArgumentException(nameof(keys)); } if (keys.Length != certs.Length) { throw new ArgumentException(nameof(certs)); } rootExtensions ??= new X509Extension[] { new X509BasicConstraintsExtension(true, false, 0, true), new X509KeyUsageExtension( X509KeyUsageFlags.CrlSign | X509KeyUsageFlags.KeyCertSign | X509KeyUsageFlags.DigitalSignature, false) }; intermediateExtensions ??= new X509Extension[] { new X509BasicConstraintsExtension(true, false, 0, true), new X509KeyUsageExtension( X509KeyUsageFlags.CrlSign | X509KeyUsageFlags.KeyCertSign | X509KeyUsageFlags.DigitalSignature, false) }; endEntityExtensions ??= new X509Extension[] { new X509BasicConstraintsExtension(false, false, 0, true), new X509KeyUsageExtension( X509KeyUsageFlags.DigitalSignature | X509KeyUsageFlags.NonRepudiation | X509KeyUsageFlags.KeyEncipherment, false) }; TimeSpan notBeforeInterval = TimeSpan.FromDays(30); TimeSpan notAfterInterval = TimeSpan.FromDays(90); DateTimeOffset eeStart = DateTimeOffset.UtcNow.AddDays(-7); DateTimeOffset eeEnd = eeStart.AddDays(45); byte[] serialBuf = new byte[16]; int rootIndex = keys.Length - 1; HashAlgorithmName hashAlgorithm = HashAlgorithmName.SHA256; RSASignaturePadding signaturePadding = RSASignaturePadding.Pkcs1; CertificateRequest rootReq = new CertificateRequest( $"CN=Test Root, O=\"{testName}\"", keys[rootIndex], hashAlgorithm, signaturePadding); foreach (X509Extension extension in rootExtensions) { rootReq.CertificateExtensions.Add(extension); } X509SignatureGenerator lastGenerator = X509SignatureGenerator.CreateForRSA(keys[rootIndex], RSASignaturePadding.Pkcs1); X500DistinguishedName lastSubject = rootReq.SubjectName; certs[rootIndex] = rootReq.Create( lastSubject, lastGenerator, eeStart - (notBeforeInterval * rootIndex), eeEnd + (notAfterInterval * rootIndex), CreateSerial()); int presentationNumber = 0; for (int i = rootIndex - 1; i > 0; i--) { presentationNumber++; CertificateRequest intermediateReq = new CertificateRequest( $"CN=Intermediate Layer {presentationNumber}, O=\"{testName}\"", keys[i], hashAlgorithm, signaturePadding); foreach (X509Extension extension in intermediateExtensions) { intermediateReq.CertificateExtensions.Add(extension); } certs[i] = intermediateReq.Create( lastSubject, lastGenerator, eeStart - (notBeforeInterval * i), eeEnd + (notAfterInterval * i), CreateSerial()); lastSubject = intermediateReq.SubjectName; lastGenerator = X509SignatureGenerator.CreateForRSA(keys[i], RSASignaturePadding.Pkcs1); } CertificateRequest eeReq = new CertificateRequest( $"CN=End-Entity, O=\"{testName}\"", keys[0], hashAlgorithm, signaturePadding); foreach (X509Extension extension in endEntityExtensions) { eeReq.CertificateExtensions.Add(extension); } certs[0] = eeReq.Create(lastSubject, lastGenerator, eeStart, eeEnd, CreateSerial()); }