Example #1
0
        public static void ArgumentValidation()
        {
            SubjectAlternativeNameBuilder builder = new SubjectAlternativeNameBuilder();

            Assert.Throws <ArgumentOutOfRangeException>("dnsName", () => builder.AddDnsName(null));
            Assert.Throws <ArgumentOutOfRangeException>("dnsName", () => builder.AddDnsName(string.Empty));
            Assert.Throws <ArgumentOutOfRangeException>("emailAddress", () => builder.AddEmailAddress(null));
            Assert.Throws <ArgumentOutOfRangeException>("emailAddress", () => builder.AddEmailAddress(string.Empty));
            Assert.Throws <ArgumentNullException>("uri", () => builder.AddUri(null));
            Assert.Throws <ArgumentNullException>("ipAddress", () => builder.AddIpAddress(null));
            Assert.Throws <ArgumentOutOfRangeException>("upn", () => builder.AddUserPrincipalName(null));
            Assert.Throws <ArgumentOutOfRangeException>("upn", () => builder.AddUserPrincipalName(string.Empty));
        }
Example #2
0
        public static void DnsNameMatchIgnoresTrailingPeriodFromParameter()
        {
            using (ECDsa key = ECDsa.Create())
            {
                CertificateRequest req = new CertificateRequest(
                    "CN=10.0.0.1",
                    key,
                    HashAlgorithmName.SHA256);

                SubjectAlternativeNameBuilder sanBuilder = new SubjectAlternativeNameBuilder();
                sanBuilder.AddDnsName("fruit.EXAMPLE");
                sanBuilder.AddDnsName("*.FrUIt.eXaMpLE");
                sanBuilder.AddEmailAddress("*****@*****.**");

                req.CertificateExtensions.Add(sanBuilder.Build());

                DateTimeOffset now       = DateTimeOffset.UtcNow;
                DateTimeOffset notBefore = now.AddMinutes(-1);
                DateTimeOffset notAfter  = now.AddMinutes(1);

                using (X509Certificate2 cert = req.CreateSelfSigned(notBefore, notAfter))
                {
                    AssertMatch(true, cert, "aPPlE.fruit.example.");
                    AssertMatch(true, cert, "tOmaTO.FRUIT.example.");
                    AssertMatch(false, cert, "tOmaTO.vegetable.example.");
                    AssertMatch(true, cert, "FRUit.example.");
                    AssertMatch(false, cert, "VEGetaBlE.example.");
                }
            }
        }
        private static CertificateRequest CreateCertificateRequest(RSA key, string emailAddress, string commonName, string countryCode)
        {
            if (emailAddress is null)
            {
                emailAddress = Prompt.Input <string>("Email address:");
            }

            if (commonName is null)
            {
                commonName = Prompt.Input <string>("Common name:");
            }

            if (countryCode is null)
            {
                countryCode = Prompt.Input <string>("Country code:");
            }

            var request = new CertificateRequest($"CN={commonName}, C={countryCode}", key, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);

            //The email address needs to be added to the request as an alternative name
            var alternativeNameBuilder = new SubjectAlternativeNameBuilder();

            alternativeNameBuilder.AddEmailAddress(emailAddress);

            request.CertificateExtensions.Add(alternativeNameBuilder.Build());

            return(request);
        }
Example #4
0
        public static void SanDoesNotMatchIPAddressInDnsName()
        {
            using (ECDsa key = ECDsa.Create())
            {
                CertificateRequest req = new CertificateRequest(
                    "CN=10.0.0.1",
                    key,
                    HashAlgorithmName.SHA256);

                SubjectAlternativeNameBuilder sanBuilder = new SubjectAlternativeNameBuilder();
                sanBuilder.AddDnsName("127.0.0.1");
                sanBuilder.AddEmailAddress("*****@*****.**");

                req.CertificateExtensions.Add(sanBuilder.Build());

                DateTimeOffset now       = DateTimeOffset.UtcNow;
                DateTimeOffset notBefore = now.AddMinutes(-1);
                DateTimeOffset notAfter  = now.AddMinutes(1);

                using (X509Certificate2 cert = req.CreateSelfSigned(notBefore, notAfter))
                {
                    // 127.0.0.1 is an IP Address, but the SAN calls it a dNSName, so it won't match.
                    AssertMatch(false, cert, "127.0.0.1");

                    // Since the SAN contains no iPAddress values, we fall back to the CN.
                    AssertMatch(true, cert, "10.0.0.1");
                }
            }
        }
Example #5
0
        public static void IPv6InCommonNameIsTextMatch()
        {
            using (ECDsa key = ECDsa.Create())
            {
                CertificateRequest req = new CertificateRequest(
                    "CN=[fe80::1]",
                    key,
                    HashAlgorithmName.SHA256);

                SubjectAlternativeNameBuilder sanBuilder = new SubjectAlternativeNameBuilder();
                sanBuilder.AddDnsName("huckleberry.fruit.example");
                sanBuilder.AddEmailAddress("*****@*****.**");

                req.CertificateExtensions.Add(sanBuilder.Build());

                DateTimeOffset now       = DateTimeOffset.UtcNow;
                DateTimeOffset notBefore = now.AddMinutes(-1);
                DateTimeOffset notAfter  = now.AddMinutes(1);

                using (X509Certificate2 cert = req.CreateSelfSigned(notBefore, notAfter))
                {
                    // Various text forms of fe80::1.  These would all match under IP-ID, but
                    // only the first couple match under CN-ID (case-insensitive exact)
                    AssertMatch(true, cert, "[fe80::1]");
                    AssertMatch(true, cert, "[fE80::1]");
                    AssertMatch(true, cert, "[FE80::1]");
                    AssertMatch(true, cert, "[Fe80::1]");

                    AssertMatch(false, cert, "fe80::1");
                    AssertMatch(false, cert, "[fe80:0000::1]");
                    AssertMatch(false, cert, "[fe80:0000::01]");
                }
            }
        }
Example #6
0
        public static void WildcardRequiresSuffixToMatch()
        {
            using (ECDsa key = ECDsa.Create())
            {
                CertificateRequest req = new CertificateRequest(
                    "CN=potato.vegetable.example",
                    key,
                    HashAlgorithmName.SHA256);

                SubjectAlternativeNameBuilder sanBuilder = new SubjectAlternativeNameBuilder();
                sanBuilder.AddDnsName("*");
                sanBuilder.AddDnsName("*.");
                sanBuilder.AddEmailAddress("*****@*****.**");

                req.CertificateExtensions.Add(sanBuilder.Build());

                DateTimeOffset now       = DateTimeOffset.UtcNow;
                DateTimeOffset notBefore = now.AddMinutes(-1);
                DateTimeOffset notAfter  = now.AddMinutes(1);

                using (X509Certificate2 cert = req.CreateSelfSigned(notBefore, notAfter))
                {
                    AssertMatch(false, cert, "example");
                    AssertMatch(false, cert, "example.");
                }
            }
        }
Example #7
0
        public void AddSubjectAlternativeName(CertificateRequest request, SubjectAlternativeName subjectAlternativeName)
        {
            foreach (var dnsName in subjectAlternativeName.DnsName)
            {
                if (UriHostNameType.Unknown == Uri.CheckHostName(dnsName))
                {
                    throw new ArgumentException("Must be a valid DNS name", nameof(dnsName));
                }
            }

            var sanBuilder = new SubjectAlternativeNameBuilder();

            foreach (var dnsName in subjectAlternativeName.DnsName)
            {
                sanBuilder.AddDnsName(dnsName);
            }

            if (!string.IsNullOrEmpty(subjectAlternativeName.Email))
            {
                sanBuilder.AddEmailAddress(subjectAlternativeName.Email);
            }

            var sanExtension = sanBuilder.Build();

            request.CertificateExtensions.Add(sanExtension);
        }
Example #8
0
        public static void NoPartialWildcards()
        {
            using (ECDsa key = ECDsa.Create())
            {
                CertificateRequest req = new CertificateRequest(
                    "CN=10.0.0.1",
                    key,
                    HashAlgorithmName.SHA256);

                SubjectAlternativeNameBuilder sanBuilder = new SubjectAlternativeNameBuilder();
                sanBuilder.AddDnsName("*berry.fruit.example");
                sanBuilder.AddDnsName("cran*.fruit.example");
                sanBuilder.AddEmailAddress("*****@*****.**");

                req.CertificateExtensions.Add(sanBuilder.Build());

                DateTimeOffset now       = DateTimeOffset.UtcNow;
                DateTimeOffset notBefore = now.AddMinutes(-1);
                DateTimeOffset notAfter  = now.AddMinutes(1);

                using (X509Certificate2 cert = req.CreateSelfSigned(notBefore, notAfter))
                {
                    AssertMatch(false, cert, "cranberry.fruit.example");
                    AssertMatch(false, cert, "cranapple.fruit.example");
                    AssertMatch(false, cert, "strawberry.fruit.example");
                }
            }
        }
Example #9
0
        public static void SanWithNoDnsMeansDoCommonNameFallback()
        {
            using (ECDsa key = ECDsa.Create())
            {
                CertificateRequest req = new CertificateRequest(
                    "CN=zalzalak.fruit.example",
                    key,
                    HashAlgorithmName.SHA256);

                SubjectAlternativeNameBuilder sanBuilder = new SubjectAlternativeNameBuilder();
                sanBuilder.AddIpAddress(IPAddress.Loopback);
                sanBuilder.AddEmailAddress("*****@*****.**");

                req.CertificateExtensions.Add(sanBuilder.Build());

                DateTimeOffset now       = DateTimeOffset.UtcNow;
                DateTimeOffset notBefore = now.AddMinutes(-1);
                DateTimeOffset notAfter  = now.AddMinutes(1);

                using (X509Certificate2 cert = req.CreateSelfSigned(notBefore, notAfter))
                {
                    AssertMatch(false, cert, "yumberry.fruit.example");
                    AssertMatch(true, cert, "127.0.0.1");

                    // Since the SAN contains no dNSName values, we fall back to the CN.
                    AssertMatch(true, cert, "zalzalak.fruit.example");
                    AssertMatch(false, cert, "zalzalak.fruit.example", allowCommonName: false);
                }
            }
        }
        public static void MultiValue()
        {
            // This produces the same value as the "ComplexGetNameInfo" certificate/test suite.
            //   Subject Alternative Names:
            //     DNS Name=dns1.subject.example.org
            //     DNS Name=dns2.subject.example.org
            //     RFC822 [email protected]
            //     RFC822 [email protected]
            //     Other Name:
            //       Principal [email protected]
            //     Other Name:
            //       Principal [email protected]
            //     URL=http://uri1.subject.example.org/
            //     URL=http://uri2.subject.example.org/

            const string expectedHex =
                "3081F88218646E73312E7375626A6563742E6578616D706C652E6F7267821864" +
                "6E73322E7375626A6563742E6578616D706C652E6F7267811573616E656D6169" +
                "6C31406578616D706C652E6F7267811573616E656D61696C32406578616D706C" +
                "652E6F7267A027060A2B060104018237140203A0190C177375626A6563747570" +
                "6E31406578616D706C652E6F7267A027060A2B060104018237140203A0190C17" +
                "7375626A65637475706E32406578616D706C652E6F72678620687474703A2F2F" +
                "757269312E7375626A6563742E6578616D706C652E6F72672F8620687474703A" +
                "2F2F757269322E7375626A6563742E6578616D706C652E6F72672F";

            SubjectAlternativeNameBuilder builder = new SubjectAlternativeNameBuilder();

            builder.AddDnsName("dns1.subject.example.org");
            builder.AddDnsName("dns2.subject.example.org");
            builder.AddEmailAddress("*****@*****.**");
            builder.AddEmailAddress("*****@*****.**");
            builder.AddUserPrincipalName("*****@*****.**");
            builder.AddUserPrincipalName("*****@*****.**");
            builder.AddUri(new Uri("http://uri1.subject.example.org/"));
            builder.AddUri(new Uri("http://uri2.subject.example.org/"));

            X509Extension extension = builder.Build();

            Assert.Equal(SubjectAltNameOid, extension.Oid.Value);

            Assert.Equal(
                expectedHex,
                extension.RawData.ByteArrayToHex());
        }
        public static void SingleValue_EmailAddress_Unicode()
        {
            // There's not a good example of what an IDNA-converted email address
            // looks like, so this isn't easy to verify.  For now let it be restricted to IA5.
            SubjectAlternativeNameBuilder builder = new SubjectAlternativeNameBuilder();

            // [nihongo]@[nihongo].example.org
            Assert.Throws <CryptographicException>(
                () => builder.AddEmailAddress("\u65E5\u672C\u8A8E@\u65E5\u672C\u8A8E.example.org"));
        }
Example #12
0
        public static void CreateBrokerTlsCert(this X509Certificate2 CACertificate, string domainname, IPAddress iP, string pubfile, string pivfile, string email)
        {
            var build = new SubjectAlternativeNameBuilder();

            build.AddDnsName(domainname);
            build.AddIpAddress(iP);
            build.AddEmailAddress(email ?? "*****@*****.**");
            string name   = $"C=CN,CN={iP.ToString()},ST=IoTSharp,O={Dns.GetHostName()},OU= CA_{MethodBase.GetCurrentMethod().Module.Assembly.GetName().Name}";
            var    broker = CACertificate.CreateTlsClientRSA(name, build);

            broker.SavePem(pubfile, pivfile);
        }
        public static void SingleValue_EmailAddress_Ascii()
        {
            SubjectAlternativeNameBuilder builder = new SubjectAlternativeNameBuilder();

            builder.AddEmailAddress("*****@*****.**");

            X509Extension extension = builder.Build();

            Assert.Equal(SubjectAltNameOid, extension.Oid.Value);

            Assert.Equal("3012811075736572406578616D706C652E6F7267", extension.RawData.ByteArrayToHex());
        }
Example #14
0
        public static void NameConstraintViolation_InvalidGeneralNames()
        {
            SubjectAlternativeNameBuilder builder = new SubjectAlternativeNameBuilder();

            builder.AddEmailAddress("///");

            // permitted RFC822 name constraint with GeneralName of ///.
            string nameConstraints = "3009A007300581032F2F2F";

            TestNameConstrainedChain(nameConstraints, builder, (bool result, X509Chain chain) => {
                Assert.False(result, "chain.Build");
                Assert.Equal(PlatformNameConstraints(X509ChainStatusFlags.InvalidNameConstraints), chain.AllStatusFlags());
            });
        }
Example #15
0
        public static void SanWithIPAddressMeansNoCommonNameFallback()
        {
            using (ECDsa key = ECDsa.Create())
            {
                CertificateRequest req = new CertificateRequest(
                    "CN=10.0.0.1",
                    key,
                    HashAlgorithmName.SHA256);

                SubjectAlternativeNameBuilder sanBuilder = new SubjectAlternativeNameBuilder();
                sanBuilder.AddIpAddress(IPAddress.Loopback);
                sanBuilder.AddIpAddress(IPAddress.IPv6Loopback);
                sanBuilder.AddIpAddress(IPAddress.Parse("[fe80::1]"));
                sanBuilder.AddEmailAddress("*****@*****.**");

                req.CertificateExtensions.Add(sanBuilder.Build());

                DateTimeOffset now       = DateTimeOffset.UtcNow;
                DateTimeOffset notBefore = now.AddMinutes(-1);
                DateTimeOffset notAfter  = now.AddMinutes(1);

                using (X509Certificate2 cert = req.CreateSelfSigned(notBefore, notAfter))
                {
                    AssertMatch(true, cert, "127.0.0.1");
                    // Various text forms of IPv6Loopback
                    AssertMatch(true, cert, "[::1]");
                    AssertMatch(true, cert, "::1");
                    AssertMatch(true, cert, "[::01]");
                    AssertMatch(true, cert, "[0000::1]");
                    // Various text forms of fe80::1
                    AssertMatch(true, cert, "[fe80::1]");
                    AssertMatch(true, cert, "[FE80::1]");
                    AssertMatch(true, cert, "fe80::1");
                    AssertMatch(true, cert, "[fe80:0000::1]");
                    AssertMatch(true, cert, "[fe80:0000::01]");
                    // Various text forms of fe80::
                    AssertMatch(false, cert, "[fe80::]");
                    AssertMatch(false, cert, "fe80::");
                    AssertMatch(false, cert, "[fe80::0]");
                    AssertMatch(false, cert, "[fe80:0000::]");

                    // Since the SAN has an iPAddress value, we do not fall back to the CN.
                    AssertMatch(false, cert, "10.0.0.1");
                }
            }
        }
Example #16
0
        public static void WildcardsDoNotMatchAfterFirstPosition()
        {
            using (ECDsa key = ECDsa.Create())
            {
                CertificateRequest req = new CertificateRequest(
                    "CN=10.0.0.1",
                    key,
                    HashAlgorithmName.SHA256);

                SubjectAlternativeNameBuilder sanBuilder = new SubjectAlternativeNameBuilder();
                sanBuilder.AddDnsName("fruit.example");
                sanBuilder.AddDnsName("*.fruit.example");
                sanBuilder.AddDnsName("*.*.fruit.example");
                sanBuilder.AddDnsName("apple.*.fruit.example");
                sanBuilder.AddDnsName("rambutan.fruit.example");
                sanBuilder.AddEmailAddress("*****@*****.**");

                req.CertificateExtensions.Add(sanBuilder.Build());

                DateTimeOffset now       = DateTimeOffset.UtcNow;
                DateTimeOffset notBefore = now.AddMinutes(-1);
                DateTimeOffset notAfter  = now.AddMinutes(1);

                using (X509Certificate2 cert = req.CreateSelfSigned(notBefore, notAfter))
                {
                    AssertMatch(true, cert, "apple.fruit.example");
                    AssertMatch(true, cert, "blackberry.fruit.example");
                    AssertMatch(true, cert, "pome.fruit.example");
                    AssertMatch(true, cert, "pomme.fruit.example");
                    AssertMatch(true, cert, "rambutan.fruit.example");
                    AssertMatch(false, cert, "apple.pome.fruit.example");
                    AssertMatch(false, cert, "apple.pomme.fruit.example");

                    AssertMatch(false, cert, "apple.fruit.example", allowWildcards: false);
                    AssertMatch(false, cert, "blackberry.fruit.example", allowWildcards: false);
                    AssertMatch(false, cert, "pome.fruit.example", allowWildcards: false);
                    AssertMatch(false, cert, "pomme.fruit.example", allowWildcards: false);
                    // This one has a redundant dNSName after the wildcard
                    AssertMatch(true, cert, "rambutan.fruit.example", allowWildcards: false);

                    AssertMatch(true, cert, "fruit.example");
                    AssertMatch(true, cert, "fruit.example", allowWildcards: false);
                }
            }
        }
Example #17
0
        public void SetUp()
        {
            SetUpProvider();
            _context = new DefaultHttpContext();
            X509Certificate2 certificate;

            using (RSA rsa = RSA.Create())
            {
                var certReq    = new CertificateRequest("CN=eventstoredb-node", rsa, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
                var sanBuilder = new SubjectAlternativeNameBuilder();
                sanBuilder.AddEmailAddress("*****@*****.**");
                sanBuilder.AddUserPrincipalName("*****@*****.**");
                sanBuilder.AddUri(new Uri("http://localhost"));
                certReq.CertificateExtensions.Add(sanBuilder.Build());
                certificate = certReq.CreateSelfSigned(DateTimeOffset.UtcNow.AddMonths(-1), DateTimeOffset.UtcNow.AddMonths(1));
            }

            _context.Connection.ClientCertificate = certificate;
            _authenticateResult = _provider.Authenticate(_context, out _authenticateRequest);
        }
Example #18
0
        public static void OnlyValidHostnamesAccepted(bool addSanExt)
        {
            using (ECDsa key = ECDsa.Create())
            {
                CertificateRequest req = new CertificateRequest(
                    "CN=John Smith",
                    key,
                    HashAlgorithmName.SHA256);

                DateTimeOffset now       = DateTimeOffset.UtcNow;
                DateTimeOffset notBefore = now.AddMinutes(-1);
                DateTimeOffset notAfter  = now.AddMinutes(1);

                if (addSanExt)
                {
                    SubjectAlternativeNameBuilder sanBuilder = new SubjectAlternativeNameBuilder();
                    sanBuilder.AddDnsName("fruit.example");
                    sanBuilder.AddDnsName("*.fruit.example");
                    sanBuilder.AddDnsName("*.*.fruit.example");
                    sanBuilder.AddDnsName("apple.*.fruit.example");
                    sanBuilder.AddDnsName("rambutan.fruit.example");
                    sanBuilder.AddEmailAddress("*****@*****.**");

                    req.CertificateExtensions.Add(sanBuilder.Build());
                }

                using (X509Certificate2 cert = req.CreateSelfSigned(notBefore, notAfter))
                {
                    Assert.Throws <ArgumentException>("hostname", () => cert.MatchesHostname("John Smith"));
                    Assert.Throws <ArgumentException>("hostname", () => cert.MatchesHostname("*.pomme.fruit.example"));
                    Assert.Throws <ArgumentException>("hostname", () => cert.MatchesHostname(".pomme.fruit.example"));
                    Assert.Throws <ArgumentException>("hostname", () => cert.MatchesHostname("*berry.fruit.example"));
                    Assert.Throws <ArgumentException>("hostname", () => cert.MatchesHostname("cran*.fruit.example"));
                    Assert.Throws <ArgumentException>("hostname", () => cert.MatchesHostname("cran*.fruit.example"));
                    Assert.Throws <ArgumentException>("hostname", () => cert.MatchesHostname(""));
                    Assert.Throws <ArgumentException>("hostname", () => cert.MatchesHostname("."));
                    Assert.Throws <ArgumentException>("hostname", () => cert.MatchesHostname("*."));
                    Assert.Throws <ArgumentException>("hostname", () => cert.MatchesHostname("*"));
                }
            }
        }
Example #19
0
        public IActionResult InstallCertificate([FromBody] CertificateDot dot)
        {
            IActionResult actionResult = NoContent();

            try
            {
                if (_options.CACertificate == null || _options.BrokerCertificate == null)
                {
                    StringBuilder builder = new StringBuilder();
                    if (!string.IsNullOrEmpty(dot.C))
                    {
                        builder.Append($"C={dot.C},");
                    }
                    builder.Append($"CN={dot.CN},");
                    if (!string.IsNullOrEmpty(dot.ST))
                    {
                        builder.Append($"ST={dot.ST},");
                    }
                    if (!string.IsNullOrEmpty(dot.O))
                    {
                        builder.Append($"O={dot.O},");
                    }
                    if (!string.IsNullOrEmpty(dot.OU))
                    {
                        builder.Append($"OU={dot.OU},");
                    }
                    var ca = new X509Certificate2().CreateCA(builder.ToString().TrimEnd(','));
                    ca.SavePem(_options.CACertificateFile, _options.CAPrivateKeyFile);
                    var build = new SubjectAlternativeNameBuilder();
                    build.AddDnsName(dot.ServerName);
                    if (!string.IsNullOrEmpty(dot.IPAddress))
                    {
                        build.AddIpAddress(IPAddress.Parse(dot.IPAddress));
                    }
                    if (!string.IsNullOrEmpty(dot.Email))
                    {
                        build.AddEmailAddress(dot.Email);
                    }
                    StringBuilder builderserver = new StringBuilder();
                    if (!string.IsNullOrEmpty(dot.C))
                    {
                        builderserver.Append($"C={dot.C},");
                    }
                    builderserver.Append($"CN={dot.ServerName},");
                    if (!string.IsNullOrEmpty(dot.ST))
                    {
                        builderserver.Append($"ST={dot.ST},");
                    }
                    if (!string.IsNullOrEmpty(dot.O))
                    {
                        builderserver.Append($"O={dot.O},");
                    }
                    if (!string.IsNullOrEmpty(dot.OU))
                    {
                        builderserver.Append($"OU={dot.OU},");
                    }
                    var broker = ca.CreateTlsClientRSA(builderserver.ToString().TrimEnd(','), build);
                    broker.SavePem(_options.CertificateFile, _options.PrivateKeyFile);
                    actionResult = Ok(new { code = 0, msg = "OK", data = new { CAName = ca.GetNameInfo(X509NameType.SimpleName, true), BrokerName = broker.GetNameInfo(X509NameType.SimpleName, false) } });
                }
                else
                {
                    actionResult = Ok(new { code = -1, msg = Resources.TheCertificateIsInstalled, data = new { CAName = _options.CACertificate.GetNameInfo(X509NameType.SimpleName, true), BrokerName = _options.BrokerCertificate.GetNameInfo(X509NameType.SimpleName, false) } });
                }
            }
            catch (System.Exception ex)
            {
                actionResult = BadRequest(new { code = -2, msg = ex.Message });
                _logger.LogError(ex, "InstallCertificate:" + ex.Message);
            }
            return(actionResult);
        }
        public async Task <IActionResult> Register([FromBody] RegisterDto model)
        {
            IActionResult actionResult = NoContent();

            try
            {
                if (_options.CACertificate == null && model.TLS)
                {
                    actionResult = BadRequest(new { code = -1, msg = "There is no root certificate, please initialize the server first" });
                }
                else
                {
                    var user = new IdentityUser
                    {
                        UserName = model.UserName,
                        Email    = model.Email
                    };
                    var result = await _userManager.CreateAsync(user, model.Password);

                    if (result.Succeeded)
                    {
                        await _signInManager.SignInAsync(user, false);

                        await _signInManager.UserManager.AddClaimAsync(user, new Claim(ClaimTypes.GivenName, model.ClientId));

                        await _signInManager.UserManager.AddClaimAsync(user, new Claim(ClaimTypes.Email, model.Email));

                        int _StoreCertPem = 0;
                        if (model.TLS)
                        {
                            SubjectAlternativeNameBuilder altNames = new SubjectAlternativeNameBuilder();
                            altNames.AddDnsName(model.ClientId);
                            altNames.AddEmailAddress(model.Email);
                            altNames.AddUserPrincipalName(model.UserName);
                            altNames.AddUri(new Uri($"mqtt://{_options.BrokerCertificate.GetNameInfo(X509NameType.DnsName, false)}:{_options.SSLPort}"));
                            string name      = $"CN={model.ClientId},C=CN, O={_options.BrokerCertificate.GetNameInfo(X509NameType.SimpleName, false)},OU={model.ClientId}";
                            var    tlsclient = _options.CACertificate.CreateTlsClientRSA(name, altNames);
                            tlsclient.SavePem(out string x509CRT, out string x509Key);
                            _context.StoreCertPem.Add(new StoreCertPem()
                            {
                                Id         = user.Id,
                                ClientCert = x509CRT,
                                ClientKey  = x509Key
                            });
                            _StoreCertPem = _context.SaveChanges();
                            await _signInManager.UserManager.AddClaimAsync(user, new Claim(ClaimTypes.Thumbprint, tlsclient.Thumbprint));
                        }
                        actionResult = Ok(new { code = 0, msg = "OK", data = GenerateJwtToken(model.UserName, user), model.TLS, StoreTLS = _StoreCertPem > 0 });
                    }
                    else
                    {
                        var msg = from e in result.Errors select $"{e.Code}:{e.Description}\r\n";
                        actionResult = BadRequest(new { code = -3, msg = string.Join(';', msg.ToArray()) });
                    }
                }
            }
            catch (Exception ex)
            {
                actionResult = BadRequest(new { code = -2, msg = ex.Message, data = ex });
                _logger.LogError(ex, ex.Message);
            }

            return(actionResult);
        }
        public FileContentResult get_ssl_certificate(DistinguishedName dName)
        {
            var rootCA = CertUtil.getInstance().getRootCA();
            var rsa    = RSA.Create();

            var request = new CertificateRequest(dName.getX509DistinguishedName(), rsa, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);

            var subjectANB = new SubjectAlternativeNameBuilder();

            subjectANB.AddDnsName(dName.DNS);
            subjectANB.AddEmailAddress(dName.E);
            request.CertificateExtensions.Add(subjectANB.Build());
            request.CertificateExtensions.Add(new X509BasicConstraintsExtension(false, false, 0, false));
            request.CertificateExtensions.Add(new X509KeyUsageExtension(
                                                  X509KeyUsageFlags.DigitalSignature |
                                                  X509KeyUsageFlags.KeyCertSign |
                                                  X509KeyUsageFlags.KeyEncipherment |
                                                  X509KeyUsageFlags.DataEncipherment |
                                                  X509KeyUsageFlags.NonRepudiation, false)
                                              );

            // set the AuthorityKeyIdentifier. There is no built-in
            // support, so it needs to be copied from the Subject Key
            // Identifier of the signing certificate and massaged slightly.
            // AuthorityKeyIdentifier is "KeyID="
            var issuerSubjectKey = rootCA.Extensions["Subject Key Identifier"].RawData;
            var segment          = new byte[issuerSubjectKey.Length - 2];

            Buffer.BlockCopy(issuerSubjectKey, 2, segment, 0, issuerSubjectKey.Length - 2);
            var authorityKeyIdentifer = new byte[segment.Length + 4];
            // these bytes define the "KeyID" part of the AuthorityKeyIdentifer
            var KeyID = new byte[] { 0x30, 0x16, 0x80, 0x14 };

            KeyID.CopyTo(authorityKeyIdentifer, 0);
            segment.CopyTo(authorityKeyIdentifer, 4);
            request.CertificateExtensions.Add(new X509Extension("2.5.29.35", authorityKeyIdentifer, false));

            request.CertificateExtensions.Add(new X509EnhancedKeyUsageExtension(
                                                  new OidCollection {
                new Oid("1.3.6.1.5.5.7.3.8"),     // Timestamping
                new Oid("1.3.6.1.5.5.7.3.2"),     // TLS Client auth
                new Oid("1.3.6.1.5.5.7.3.1")      // TLS Server auth
            }, false)
                                              );
            request.CertificateExtensions.Add(new X509SubjectKeyIdentifierExtension(request.PublicKey, false));

            // Add Time and Key
            X509Certificate2 sslCert = request.Create(rootCA, DateTimeOffset.Now, DateTimeOffset.Now.AddYears(1), BitConverter.GetBytes(DateTimeOffset.Now.Ticks));

            sslCert = sslCert.CopyWithPrivateKey(rsa);

            // Create PFX (PKCS #12) with private key
            byte[] p12Cert = sslCert.Export(X509ContentType.Pkcs12, "password");
            // Create Base 64 encoded CER (public key only)
            string cerCert = "-----BEGIN CERTIFICATE-----\r\n" + Convert.ToBase64String(sslCert.Export(X509ContentType.Cert), Base64FormattingOptions.InsertLineBreaks) + "\r\n-----END CERTIFICATE-----";

            byte[] pfxCert = sslCert.Export(X509ContentType.Pfx, "password");

            String CertID = DateTimeOffset.Now.Ticks.ToString();

            // Write to disk
            System.IO.File.WriteAllBytes(AppContext.BaseDirectory + "/" + CertID + ".p12", p12Cert);
            System.IO.File.WriteAllText(AppContext.BaseDirectory + "/" + CertID + ".cer", cerCert);
            System.IO.File.WriteAllBytes(AppContext.BaseDirectory + "/" + CertID + ".pfx", pfxCert);


            FileContentResult fcResult = File(p12Cert, "application/octet-stream", CertID + ".p12");

            //FileContentResult fcResult = File(System.Text.Encoding.ASCII.GetBytes(cerCert), "application/octet-stream", "176743490865.cer");
            return(fcResult);
        }
Example #22
0
        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());
            }
        }