25

I google it from web, find many samples to generate a new x509Certificate2 from a file in .net, but there is no one sample to show how to generate a completely new x509Certificate2 from the beginning in .net.

Is there any one that can tell me how to do it in .net?

Thank you very much.

Luper Rouch
  • 8,683
  • 5
  • 39
  • 55
travellover
  • 261
  • 1
  • 4
  • 5
  • 1
    seems no one know this. Seems like x509Certificate2 in .net is only for reading x509Certificate2 certificates instead of generating ones, right? – travellover Feb 23 '10 at 22:55
  • 1
    Yes, With method and constructor which X509Certificate2 have, we can only import, and get its properties. – pinichi Oct 19 '10 at 08:57

6 Answers6

18

Here's a code you can use:

    static X509Certificate2 GenerateCertificate(string certName)
    {
        var keypairgen = new RsaKeyPairGenerator();
        keypairgen.Init(new KeyGenerationParameters(new SecureRandom(new CryptoApiRandomGenerator()), 1024));

        var keypair = keypairgen.GenerateKeyPair();

        var gen = new X509V3CertificateGenerator();

        var CN = new X509Name("CN=" + certName);
        var SN = BigInteger.ProbablePrime(120, new Random());

        gen.SetSerialNumber(SN);
        gen.SetSubjectDN(CN);
        gen.SetIssuerDN(CN);
        gen.SetNotAfter(DateTime.MaxValue);
        gen.SetNotBefore(DateTime.Now.Subtract(new TimeSpan(7, 0, 0, 0)));
        gen.SetSignatureAlgorithm("MD5WithRSA");
        gen.SetPublicKey(keypair.Public);           

        var newCert = gen.Generate(keypair.Private);

        return new X509Certificate2(DotNetUtilities.ToX509Certificate((Org.BouncyCastle.X509.X509Certificate)newCert));
    }

for this to work, don't forget to add reference to BouncyCastle library

Arsen Zahray
  • 21,834
  • 46
  • 119
  • 205
  • I could be wrong about this, but shouldn't the new Random() be a static readonly Random instance? It will return the same random number in ProbablePrime each time if you create a new instance each time. – Chris Bush Nov 05 '14 at 18:35
  • I have ran BouncyCastle (1.7.1) through VeraCode and I found that it's implementation of BigInteger does not provide enough entropy. This calls into question the validity of the prime number generation the library uses. – Mr. Young Apr 09 '15 at 17:09
  • 1
    @Mr.Young I'd be very interested in more details relating to your above comment, by private message if you prefer. BigInteger is not the source of any entropy used by key generators; we have a SecureRandom class for that. In our latest code, this essentially forwards to the system RNG, but it may be that earlier versions are less than ideal. In BigInteger, the Random class is used only for selecting the Miller-Rabin random bases to test probable primes against. – Peter Dettman Apr 11 '15 at 05:35
3

Open ssl for creating x509 certificate

1.Download the Win64 Openssl from the below link.(Win64 OpenSSL v1.1.0j - 37mb installer) URL - https://slproweb.com/products/Win32OpenSSL.html

2.After installation set the system path environment variable.(path = C:\OpenSSL-Win64\bin)

3.Open command prompt and change the directory to desktop.

4.Command for key creation : Private Key : openssl req -x509 -days 365 -newkey rsa:2048 -keyout cert-key.pem -out cert.pem Enter the command and follow the instruction.

5.Now we have 2 files named cert-key.pem and cert.pem in desktop. To create the .pfx file run the below command openssl pkcs12 -export -in cert.pem -inkey cert-key.pem -out x509-cert.pfx and follow the instruction(enter the same password).

6.Command for public key creation : openssl pkcs12 -in x509-cert.pfx -clcerts -nokeys -out x509-cert-public.pem and follow the instruction.

7.Register the certificate to mmc.

Bjarki Heiðar
  • 3,037
  • 6
  • 25
  • 38
3

You can use PINVOKE to call into Crypt32 to create a self signed certificate. There is some sample code available which will generate one and put it in the certificate store for you.

There's also Keith Brown's certificate generator, which is written in managed code and has a library you can use.

Alternatively you can just use BouncyCastle using the Org.BouncyCastle.X509.X509V3CertificateGenerator and the use the utility methods in Org.BouncyCastle.Security.DotNetUtilities and call ToX509Certificate().

If you want to create a request and have it signed by a CA that's actually easier in .NET, as most of those classes can be imported as COM interop DLLs. But that's a whole other question.

blowdart
  • 52,422
  • 11
  • 102
  • 145
2

Checkout CertificateRequest (Name Space: System.Security.Cryptography.X509Certificates)...

 public static X509Certificate2 GenerateSelfSignedCertificate()
    {
        string secp256r1Oid = "1.2.840.10045.3.1.7";  //oid for prime256v1(7)  other identifier: secp256r1
        
        string subjectName = "Self-Signed-Cert-Example";

        var ecdsa = ECDsa.Create(ECCurve.CreateFromValue(secp256r1Oid));

        var certRequest = new CertificateRequest($"CN={subjectName}", ecdsa, HashAlgorithmName.SHA256);

        //add extensions to the request (just as an example)
        //add keyUsage
        certRequest.CertificateExtensions.Add(new X509KeyUsageExtension(X509KeyUsageFlags.DigitalSignature, true));

        X509Certificate2 generatedCert = certRequest.CreateSelfSigned(DateTimeOffset.Now.AddDays(-1), DateTimeOffset.Now.AddYears(10)); // generate the cert and sign!

        X509Certificate2 pfxGeneratedCert = new X509Certificate2(generatedCert.Export(X509ContentType.Pfx)); //has to be turned into pfx or Windows at least throws a security credentials not found during sslStream.connectAsClient or HttpClient request...

     return pfxGeneratedCert;
}
0

I think you can't do it using that API. But you can create one using Bouncy Castle (http://www.bouncycastle.org) and later convert that object to a X509Certificate2 object (BC has some utility class for doing that).

-edit- Take a look at these BC classes: X509V3CertificateGenerator and X509Certificate

The BC utility class that later will convert a BC X509Certificate object to a regular X509Certificate2 object is: DotNetUtilities

Żubrówka
  • 694
  • 1
  • 8
  • 24
-4
public X509Certificate2 GetCertificate()
{
    var config = InitConfiguration();
    var certificateSubject = "X509Subject";
    var certificateStoreName = "X509StoreName";
    var certificateStoreLocation = "X509StoreLocation";
    var thumbPrint = "ThumbPrint";

    var storeName = (StoreName)Enum.Parse(typeof(StoreName), certificateStoreName, true);
    var storeLocation = (StoreLocation)Enum.Parse(typeof(StoreLocation), certificateStoreLocation, true);

    var certificateStore = new X509Store(storeName, storeLocation);
    certificateStore.Open(OpenFlags.ReadOnly);

    foreach (var storeCertificate in certificateStore.Certificates)
    {
        if (storeCertificate.Thumbprint.ToLower(System.Globalization.CultureInfo.CurrentCulture) == thumbPrint.ToLower(System.Globalization.CultureInfo.CurrentCulture))
        {return storeCertificate;
        }
    }
certificateStore.Close();
    return null;
}