Beispiel #1
0
        public static void ECDSA_Signing_RSA()
        {
            using (RSA rsa = RSA.Create())
                using (ECDsa ecdsa = ECDsa.Create())
                {
                    var request = new CertificateRequest(
                        new X500DistinguishedName("CN=Test"),
                        ecdsa,
                        HashAlgorithmName.SHA256);

                    request.CertificateExtensions.Add(
                        new X509BasicConstraintsExtension(true, false, 0, true));

                    DateTimeOffset now = DateTimeOffset.UtcNow;

                    using (X509Certificate2 cert = request.CreateSelfSigned(now, now.AddDays(1)))
                    {
                        X509SignatureGenerator generator =
                            X509SignatureGenerator.CreateForRSA(rsa, RSASignaturePadding.Pkcs1);

                        request = new CertificateRequest(
                            new X500DistinguishedName("CN=Leaf"),
                            rsa,
                            HashAlgorithmName.SHA256,
                            RSASignaturePadding.Pkcs1);

                        byte[] serialNumber = { 1, 1, 2, 3, 5, 8, 13 };

                        AssertExtensions.Throws <ArgumentException>("issuerCertificate", () => request.Create(cert, now, now.AddHours(3), serialNumber));


                        // Passes with the generator
                        using (request.Create(cert.SubjectName, generator, now, now.AddHours(3), serialNumber))
                        {
                        }
                    }
                }
        }
Beispiel #2
0
        public static void PublicKeyEncoding()
        {
            using (RSA rsa = RSA.Create())
            {
                rsa.ImportParameters(TestData.RsaBigExponentParams);

                X509SignatureGenerator signatureGenerator = X509SignatureGenerator.CreateForRSA(rsa, RSASignaturePadding.Pkcs1);
                PublicKey publicKey = signatureGenerator.PublicKey;

                // Irrespective of what the current key thinks, the PublicKey value we encode for RSA will always write
                // DER-NULL parameters, by the guidance of RFC 3447:
                //
                //    The object identifier rsaEncryption identifies RSA public and private
                //    keys as defined in Appendices A.1.1 and A.1.2.  The parameters field
                //    associated with this OID in a value of type AlgorithmIdentifier shall
                //    have a value of type NULL.
                Assert.Equal(new byte[] { 5, 0 }, publicKey.EncodedParameters.RawData);

                string expectedKeyHex =
                    // SEQUENCE
                    "3082010C" +
                    //   INTEGER (modulus)
                    "0282010100" + TestData.RsaBigExponentParams.Modulus.ByteArrayToHex() +
                    //   INTEGER (exponent)
                    "0205" + TestData.RsaBigExponentParams.Exponent.ByteArrayToHex();

                Assert.Equal(expectedKeyHex, publicKey.EncodedKeyValue.RawData.ByteArrayToHex());

                const string rsaEncryptionOid = "1.2.840.113549.1.1.1";
                Assert.Equal(rsaEncryptionOid, publicKey.Oid.Value);
                Assert.Equal(rsaEncryptionOid, publicKey.EncodedParameters.Oid.Value);
                Assert.Equal(rsaEncryptionOid, publicKey.EncodedKeyValue.Oid.Value);

                PublicKey publicKey2 = signatureGenerator.PublicKey;
                Assert.Same(publicKey, publicKey2);
            }
        }
Beispiel #3
0
        public void CreateIssuerRSACngWithSuppliedKeyPair()
        {
            if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                Assert.Ignore("Cng provider only available on windows");
            }
            X509Certificate2 issuer = null;
            CngKey           cngKey = CngKey.Create(CngAlgorithm.Rsa);

            using (RSA rsaKeyPair = new RSACng(cngKey))
            {
                // create cert with supplied keys
                var generator = X509SignatureGenerator.CreateForRSA(rsaKeyPair, RSASignaturePadding.Pkcs1);
                using (var cert = CertificateBuilder.Create("CN=Root Cert")
                                  .SetCAConstraint(-1)
                                  .SetRSAPublicKey(rsaKeyPair)
                                  .CreateForRSA(generator))
                {
                    Assert.NotNull(cert);
                    issuer = new X509Certificate2(cert.RawData);
                    WriteCertificate(cert, "Default root cert with supplied RSA cert");
                    CheckPEMWriter(cert);
                }

                // now sign a cert with supplied private key
                using (var appCert = CertificateBuilder.Create("CN=App Cert")
                                     .SetIssuer(issuer)
                                     .CreateForRSA(generator))
                {
                    Assert.NotNull(appCert);
                    Assert.AreEqual(issuer.SubjectName.Name, appCert.IssuerName.Name);
                    Assert.AreEqual(issuer.SubjectName.RawData, appCert.IssuerName.RawData);
                    WriteCertificate(appCert, "Signed RSA app cert");
                    CheckPEMWriter(appCert);
                }
            }
        }
        public static void ReproduceBigExponentCsr()
        {
            X509Extension sanExtension = new X509Extension(
                "2.5.29.17",
                "302387047F00000187100000000000000000000000000000000182096C6F63616C686F7374".HexToByteArray(),
                false);

            byte[] autoCsr;
            byte[] csr;
            string csrPem;
            string autoCsrPem;

            using (RSA rsa = RSA.Create())
            {
                rsa.ImportParameters(TestData.RsaBigExponentParams);

                CertificateRequest request = new CertificateRequest(
                    "CN=localhost, OU=.NET Framework (CoreFX), O=Microsoft Corporation, L=Redmond, S=Washington, C=US",
                    rsa,
                    HashAlgorithmName.SHA256,
                    RSASignaturePadding.Pkcs1);

                request.CertificateExtensions.Add(sanExtension);

                autoCsr    = request.CreateSigningRequest();
                autoCsrPem = request.CreateSigningRequestPem();

                X509SignatureGenerator generator = X509SignatureGenerator.CreateForRSA(rsa, RSASignaturePadding.Pkcs1);
                csr    = request.CreateSigningRequest(generator);
                csrPem = request.CreateSigningRequestPem(generator);
            }

            AssertExtensions.SequenceEqual(TestData.BigExponentPkcs10Bytes, autoCsr);
            AssertExtensions.SequenceEqual(TestData.BigExponentPkcs10Bytes, csr);
            Assert.Equal(TestData.BigExponentPkcs10Pem, autoCsrPem);
            Assert.Equal(TestData.BigExponentPkcs10Pem, csrPem);
        }
Beispiel #5
0
 public static void RsaPkcsSignatureGeneratorCtor_Exceptions()
 {
     AssertExtensions.Throws <ArgumentNullException>(
         "key",
         () => X509SignatureGenerator.CreateForRSA(null, RSASignaturePadding.Pkcs1));
 }
Beispiel #6
0
        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);

                CertificateRequest request = new CertificateRequest(subject, rsa, HashAlgorithmName.SHA256);
                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 static PSD2Certificate createRSAKeysAndCertificate(PSD2CertificateParameters parameters)
        {
            var context           = new ValidationContext(parameters, null, null);
            var validationResults = new List <ValidationResult>();

            bool valid = Validator.TryValidateObject(parameters, context, validationResults, true);

            if (!valid)
            {
                throw new ValidationException("Invalid Request", new AggregateException(validationResults.Select(validationResult => new ValidationException(validationResult.ErrorMessage))));
            }

            var subjectDN = CreateDistinguishedName(new Dictionary <string, string>
            {
                { "O", parameters.Subject.Organization },
                { "CN", parameters.Subject.CommonName },
                { "C", parameters.Subject.Country },
                { OID_organizationIdentifier, parameters.Subject.OrganizationIdentifier },
            });
            var issuerDN = CreateDistinguishedName(new Dictionary <string, string>
            {
                { OID_emailAddress, parameters.Issuer.EmailAddress },
                { "CN", parameters.Issuer.CommonName },
                { "OU", parameters.Issuer.OrganizationUnit },
                { "O", parameters.Issuer.Organization },
                { "L", parameters.Issuer.Locality },
                { "ST", parameters.Issuer.State },
                { "C", parameters.Issuer.Country },
            });
            var issuerDnsName = parameters.IssuerDnsName;

            using (RSA rsa = RSA.Create(2048))
            {
                var request = new CertificateRequest(subjectDN, rsa, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);

                request.CertificateExtensions.Add(new X509KeyUsageExtension(X509KeyUsageFlags.DigitalSignature | X509KeyUsageFlags.NonRepudiation | X509KeyUsageFlags.KeyCertSign | X509KeyUsageFlags.CrlSign, false));
                if (parameters.CertificateType == PSD2CertificateType.QWAC) // only for qwac
                {
                    request.CertificateExtensions.Add(new X509EnhancedKeyUsageExtension(new OidCollection {
                        new Oid(OID_serverAuth), new Oid(OID_clientAuth)
                    }, false));
                }
                request.CertificateExtensions.Add(new X509QcStatmentExtension(parameters.Roles, parameters.CertificateType, parameters.RetentionPeriod, parameters.NcaName, parameters.NcaId, false));

                var sanBuilder = new SubjectAlternativeNameBuilder();
                sanBuilder.AddDnsName(issuerDnsName);
                request.CertificateExtensions.Add(sanBuilder.Build());

                using (RSA issuerRSA = RSA.Create(4096))
                {
                    var certificate = request.Create(issuerDN, X509SignatureGenerator.CreateForRSA(issuerRSA, RSASignaturePadding.Pkcs1), DateTimeOffset.Now, DateTimeOffset.Now.AddMonths(39), new byte[] { 1, 2, 3, 4 });

                    return(new PSD2Certificate
                    {
                        PublicKey = PemExporter.ExportPublicKeyPKCS1(rsa),
                        PrivateKey = PemExporter.ExportPrivateKeyPKCS8(rsa),
                        Certificate = PemExporter.ToPem("CERTIFICATE", certificate.Export(X509ContentType.Cert))
                    });
                }
            }
        }
Beispiel #8
0
 internal RSASha1Pkcs1SignatureGenerator(RSA rsa)
 {
     _realRsaGenerator = X509SignatureGenerator.CreateForRSA(rsa, RSASignaturePadding.Pkcs1);
 }
        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());
            }
        }
        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());
                        }
                    }
                }
        }
Beispiel #11
0
        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 IActionResult IssueCertificate(CertRequest certRequest)
        {
            if (certRequest.CertPassphrase.Length < Constants.MinPassphraseLength)
            {
                _logger.LogWarning(
                    string.Format(
                        "User {} tried to issue new certificate with too short passphrase.",
                        certRequest.Uid
                        )
                    );
                return(BadRequest("Too short passphrase"));
            }

            CipherSuite cipherSuite = certRequest.RequestedCipherSuite;

            if (!cipherSuite.IsValidCipherSuite())
            {
                _logger.LogWarning("Invalid cipher suite:\n" + cipherSuite);
                return(BadRequest("Invalid cipher suite."));
            }

            User user = _userDBAuthenticator.AuthenticateAndGetUser(certRequest.Uid, certRequest.Password);

            if (user != null)
            {
                // Load the certificate
                X509Certificate2 coreCACert = new X509Certificate2(CAConfig.CoreCACertPath);

                HashAlgorithmName   hashAlg = new HashAlgorithmName(cipherSuite.HashAlg);
                AsymmetricAlgorithm privKey = null;
                string privKeyExport        = null;

                CertificateRequest req = null;

                if (cipherSuite.Alg.Equals(EncryptionAlgorithms.RSA))
                {
                    privKey       = RSA.Create(cipherSuite.KeySize);
                    privKeyExport = ((RSA)privKey).ToPem();

                    req = new CertificateRequest(
                        "CN=" + user.Id,
                        (RSA)privKey,
                        hashAlg,
                        RSASignaturePadding.Pss
                        );
                }
                else if (cipherSuite.Alg.Equals(EncryptionAlgorithms.ECDSA))
                {
                    privKey       = ECDsa.Create();
                    privKeyExport = ((ECDsa)privKey).ToPem();

                    req = new CertificateRequest(
                        "CN=" + user.Id,
                        (ECDsa)privKey,
                        hashAlg
                        );
                }
                else
                {
                    _logger.LogError(
                        string.Format(
                            "Unknown encryption algorithm '{0}'.",
                            cipherSuite.Alg
                            )
                        );
                    throw new CryptographicUnexpectedOperationException();
                }

                // Add email as SAN
                SubjectAlternativeNameBuilder sanBuilder = new SubjectAlternativeNameBuilder();
                sanBuilder.AddEmailAddress(user.Email);
                req.CertificateExtensions.Add(sanBuilder.Build());

                // Arguments: Is no CA, no restricted nr of path levels, (nr of path levels), is not critical
                req.CertificateExtensions.Add(
                    new X509BasicConstraintsExtension(false, false, 0, false)
                    );

                req.CertificateExtensions.Add(
                    new X509SubjectKeyIdentifierExtension(req.PublicKey, false)
                    );

                req.CertificateExtensions.Add(
                    new X509KeyUsageExtension(
                        X509KeyUsageFlags.KeyEncipherment
                        | X509KeyUsageFlags.DigitalSignature
                        | X509KeyUsageFlags.NonRepudiation,
                        false
                        )
                    );

                OidCollection oidCollection = new OidCollection();
                // Set Client Authentication Oid
                oidCollection.Add(new Oid("1.3.6.1.5.5.7.3.2"));
                // Set Secure Email / Email protection Oid
                oidCollection.Add(new Oid("1.3.6.1.5.5.7.3.4"));

                req.CertificateExtensions.Add(
                    new X509EnhancedKeyUsageExtension(
                        oidCollection,
                        false
                        )
                    );

                // Add CRL Distribution Point (CDP)
                req.CertificateExtensions.Add(
                    new System.Security.Cryptography.X509Certificates.X509Extension(
                        new Oid(X509Extensions.CrlDistributionPoints.Id),
                        new CrlDistPoint(
                            new[] {
                    new DistributionPoint(
                        new DistributionPointName(
                            new GeneralNames(
                                new GeneralName(
                                    GeneralName.UniformResourceIdentifier,
                                    CAConfig.CrlDistributionPoint
                                    )
                                )
                            ),
                        null,
                        null
                        )
                }
                            ).GetDerEncoded(),
                        false
                        )
                    );

                X509Certificate2 coreCaPublicCert = new X509Certificate2(coreCACert.Export(X509ContentType.Cert));
                if (coreCaPublicCert.HasPrivateKey)
                {
                    _logger.LogError("Core CA public certificate exported with private key!");
                    throw new CryptographicUnexpectedOperationException();
                }

                // Use transaction to prevent race conditions on the serial number
                X509Certificate2 userCert;

                using (
                    IDbContextTransaction scope = _caDBModifier.GetScope()
                    )
                {
                    SerialNumber serialNr = _caDBModifier.GetMaxSerialNr();

                    // It is necessary to use this constructor to be able to sign keys
                    // that use different algorithms than the one for the core CA's key
                    userCert = req.Create(
                        coreCACert.SubjectName,
                        X509SignatureGenerator.CreateForRSA(
                            (RSA)coreCACert.PrivateKey,
                            RSASignaturePadding.Pss
                            ),
                        DateTimeOffset.UtcNow,
                        DateTimeOffset.UtcNow.AddDays(CAConfig.UserCertValidityPeriod),
                        serialNr.SerialNrBytes
                        );

                    _caDBModifier.RevokeAllCertificatesOfUser(user);

                    // Add certificate to DB
                    _caDBModifier.AddCertificate(
                        new PublicCertificate {
                        SerialNr    = serialNr.SerialNr,
                        Uid         = user.Id,
                        Certificate = Convert.ToBase64String(
                            userCert.Export(X509ContentType.Cert)
                            ),
                        IsRevoked = false
                    }
                        );

                    scope.Commit();
                }

                var collection = new X509Certificate2Collection();

                X509Certificate2 userCertWithPrivKey;
                if (privKey is RSA rsa)
                {
                    userCertWithPrivKey = userCert.CopyWithPrivateKey(rsa);
                }
                else if (privKey is ECDsa dsa)
                {
                    userCertWithPrivKey = userCert.CopyWithPrivateKey(dsa);
                }
                else
                {
                    throw new CryptographicUnexpectedOperationException();
                }

                collection.Add(userCertWithPrivKey);
                collection.Add(coreCaPublicCert);

                BackupPrivateKey(privKeyExport, user.Id + '_' + userCert.Thumbprint + ".pem.enc");

                byte[] certBytes        = collection.Export(X509ContentType.Pkcs12, certRequest.CertPassphrase);
                string pkcs12ArchiveB64 = Convert.ToBase64String(certBytes);

                // Add encrypted private key to DB
                _caDBModifier.AddPrivateKey(
                    new PrivateKey {
                    Uid       = user.Id,
                    KeyPkcs12 = pkcs12ArchiveB64
                }
                    );

                _logger.LogInformation("Successfully issued new certificate for user " + user.Id);

                return(Ok(
                           new UserCertificate {
                    Pkcs12Archive = pkcs12ArchiveB64
                }
                           ));
            }
            else
            {
                _logger.LogWarning(
                    "Unauthorized attempt to issue certificate for user "
                    + certRequest.Uid
                    );
                return(Unauthorized());
            }
        }
Beispiel #13
0
        internal static void MakeTestChain(
            ReadOnlySpan <RSA> keys,
            Span <X509Certificate2> certs,
            IEnumerable <X509Extension> endEntityExtensions,
            IEnumerable <X509Extension> intermediateExtensions,
            IEnumerable <X509Extension> rootExtensions)
        {
            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",
                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}",
                    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",
                keys[0],
                hashAlgorithm,
                signaturePadding);

            foreach (X509Extension extension in endEntityExtensions)
            {
                eeReq.CertificateExtensions.Add(extension);
            }

            certs[0] = eeReq.Create(lastSubject, lastGenerator, eeStart, eeEnd, CreateSerial());
        }