0

I have to generate a X509Certificate2 certficate at runtime from my web application and store it in my database in bytes format. I am using the solution provided here. Using this solution you may be able to generate the certificate but it will also create it in the machine certificate store. I don't need the certificate to be present in the machine certificate store so i delete it from the certificate store after I get the X509Certificate2 object.

Additionally, as my web application is running under IIS_IUSRS account it did not allow me to create certficates using MachineContext initially so I had to do it under UserContext. To create certficates even under UserContext there is an app-pool property called 'Load User Profile' which should be set to true. Now I am able to get the desired results but I want to check if there are any problems with the approach or in setting 'Load User Profile' to true in the IIS.

Community
  • 1
  • 1
Aashish Upadhyay
  • 840
  • 1
  • 7
  • 22
  • for what purposes you generate certificates? – Crypt32 May 16 '17 at 11:45
  • We will be using these certificates for encryption. These certificates will be stored in the database in an encrypted format. The key to encrypt these certificates will be maintained in a HSM. – Aashish Upadhyay May 16 '17 at 12:59
  • you should use symmetric keys for encryption and protect these keys with master key on HSM. – Crypt32 May 16 '17 at 13:01

1 Answers1

0

If you're able to switch to .NET Core, the 2.0 preview is out and has an in-box solution to certificate creation.

using System.Security.Cryptography.X509Certificates;

...

private static X509Certificate2 MakeLocalhostCert()
{
    using (ECDsa key = ECDsa.Create(ECCurve.NamedCurves.nistP384))
    {
        var request = new CertificateRequest(
            "CN=localhost",
            key,
            HashAlgorithmName.SHA384);

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

        const X509KeyUsageFlags endEntityTypicalUsages =
            X509KeyUsageFlags.DataEncipherment |
            X509KeyUsageFlags.KeyEncipherment |
            X509KeyUsageFlags.DigitalSignature |
            X509KeyUsageFlags.NonRepudiation;

        request.CertificateExtensions.Add(
            new X509KeyUsageExtension(endEntityTypicalUsages, true));

        var sanBuilder = new SubjectAlternativeNameBuilder();
        sanBuilder.AddDnsName("localhost");
        sanBuilder.AddIpAddress(IPAddress.Loopback);
        sanBuilder.AddIpAddress(IPAddress.IPv6Loopback);

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

        request.CertificateExtensions.Add(
            new X509EnhancedKeyUsageExtension(
                new OidCollection
                {
                    // server authentication
                    new Oid("1.3.6.1.5.5.7.3.1"),
                },
                false));

        DateTimeOffset now = DateTimeOffset.UtcNow;

        return request.CreateSelfSigned(now, now.AddDays(90));
    }
}

There's a breaking change to certificates for RSA keys post-preview1, an RSASignaturePadding required parameter was added to the CertificateRequest ctor for RSA.

bartonjs
  • 30,352
  • 2
  • 71
  • 111