Bouncy Castle is a pretty powerful cryptographic library. Unfortunately, one of its failings is a lack of proper documentation (Although there is a pretty comprehensive test project suite). As documentation is lacking, it can feel pretty good when you finally get Bouncy Castle to do something useful.
In this article I explain how to use Bouncy Castle (C# .NET variant) to create a simple certificate. For a source code example, please refer to my Certificate Generator tool (Certificate.cs)
For additional information on Bouncy Castle See these previous articles:
- Bouncy Castle C# Homepage [bouncycastle.org]
- Is it possible to programatically generate an X509 certificate using only C#? [stackoverflow.com]
- How can constructing an X509Certificate2 from a PKCS#12 byte array... [stackoverflow.com]
- What is a good Windows hex editor / Viewer? [stackoverflow.com]
- Information on Certificate formats [publib.boulder.ibm.com]
- Distinguished Encoding Rules (DER) [wikipedia.org]
Before jumping into the actual code, I want to point out what will need to be done to generate a Certificate and save it in either DER or PKCS12 format. This is done so you have an at-a-glance view of what needs to be coded to make this work. The steps below are bouncy castle specific, although the general principles probably apply to a number of crypto APIs.
Generate the keys and the Certificate:
- Create an Asymmetric keypair Generator
- Generate the Asymmetric keypair
- Create a Certificate Generator
- Assign properties to the Certificate generator (CN, Bitstrength, Validity period, etc...)
- Generate a Certificate signed by the issuer's private certificate (we'll be doing self signed here)
Package as a DER:
- Grab a DER encoded byte array from the certificate
- Use a .NET FileStream to write the bytes out to the Hard drive. That's it!
Package as a PKCS12:
- Create a new PKCS12 Store builder
- Add a Certificate entry to the store
- Add a private key entry to the store
- Write out the PKCS12 store to a .NET MemoryStream
- Save the bytes to a FileStream (You could probably save directly to a FileStream)
Section 0: .NET using statements
One thing that bugs me a lot about Stack Overflow is that sometimes your questions get edited to remove the using statements that go at the top of the source file. This is frustrating since sometimes it can be difficult to find out which namespace a class 'lives' in. In this article I'm going to list the using statements that will be needed to make a Certificate in Bouncy Castle:
Create the Asymmetric keys and the Certificate
First, create a keypair generator. In this example we are instantiating a new instance of RsaKeyPairGenerator and feeding it the appropriate KeyGenerationParameters and the Bit Strength of the resulting keys:
Generate the keypair using the GenerateKeyPair() method:
Instantiate a new X509V3CertificateGenerator and assign it the Certificate Properties you want the final certificate to have. In this example we create a couple of X509Name objects that hold the Common Name (Certificate DN) and IssuerDN. We also use a BigInteger to come up with a serial number and a couple of DateTime objects to store the valid from/to dates:
Generate a Certificate signed by the issuer's private key. In this case we're making a self-signed certificate so we'll use the private key that was generated above:
Congratulations! At this point you have valid X509 Certificate. Read on for how to get the bytes written out to the file system.
Note: This is NOT the same as a .NET X509Certificate2. Conversions need to be done when working with both types (outside the scope of this article)
Option 1: Package and save as a DER encoded file
This is the easiest format to save your certificate in. It involves obtaining the DER encoded bytes of the certificate object and writing them out to the file system.
Get the encoded bytes with the GetEncoded() method that is available on all certificate objects:
Now, write the bytes out to the file system using a FileStream:
If everything works you should be able to double-click on the file in the Windows Explorer and import the certificate using the Cert import wizard.
Option 2: Package and save as a PKCS12 file (Includes the private key)
This is a little bit more complex since we need to create a PKCS12 store before writing anything out. On the whole it is not too difficult, though.
Create AND build a new Pkcs12Store object. This will let us create the actual PKCS12 store:
Add a certificate entry to the store. The certificate needs to be converted to an X509CertificateEntry object for this to work. Once we have the data in the correct type, we can use the SetCertificateEntry method to add the cert data to the PKCS#12 store. It needs to have an alias so I set it to the certificate's DN in this example:
Next add an entry for the Certificate's Private key. This is like the CertificateEntry where we need to give it an alias. I just use the Certificate's DN + "_key" and it seems to work for me. One additional thing here is that you need to include the X509CertificateEntry that are associated with the private key in an array form. Since we only have a self-signed certificate this example will only have one certificate in the 'chain'. I'm not sure how this would work with more than one certificate:
At this point you have everything you need to save the PKCS#12 store to the file system. You just need to write it out. Here is a quick way to perform the 'save' operation:
- We use the Save() method that is avaialble on the BouncyCastle Pkcs12Store object to write out to a FileStream
- Be sure to specify a password you can remember. You will be prompted for the password when you use the store.
Appendix: Hash Types supported by Bouncy Castle (C#.NET)
This enum can be used to simplify your code. Rather than passing in "SHA1withDSA" (String literal) you can do HashType.SHA1withDSA.ToString()
I like to use enums where possible since it restricts the number of 'magic literals' in my code.