65.9K
CodeProject is changing. Read more.
Home

Generate PKI using Bouncy Castle: An Example

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.05/5 (4 votes)

Jan 4, 2018

CPOL
viewsIcon

20176

downloadIcon

584

Generate Key Pair and Cert Request

Introduction

I've been given a task similar to this. After searching documentation and code examples, I came up with this solution. Now I'd like to share with you.

Setup

Create the project (either .NET Console, WPF or .NET Core Console, UWP). Then add Bouncy Castle Nuget package:

The Code

PKI Model

The PKI is modeled to contain the Key-Pair and CSR:

    public class Pki
    {
        public string PrivateKey { get; set; }
        public string PublicKey { get; set; }
        public string Csr { get; set; }
    }

The Input

First comes the Key Length and Hashing Algorithm:

    public enum RsaKeyLength
    {
        Length2048Bits = 2048, Length3072Bits = 3072, Length4096Bits = 4096
    }

    public enum SignatureAlgorithm
    {
        SHA1, SHA256, SHA512
    }

You can provide additional options if needed, SHA384 for example.

Then additional input, such as: common name (Fully Qualified Domain Name, FQDN), organization, city, state, country, email address, etc. So, the out main method signature is as follows:

            Pki pki = GenPki(commonName: "mail.google.com",
                organization: "Google Inc.",
                organizationalUnit: "Information Technology",
                locality: "San Diego",
                state: "California",
                countryIso2Characters: "US",
                emailAddress: "support@google.com",
                signatureAlgorithm: SignatureAlgorithm.SHA256,
                rsaKeyLength: RsaKeyLength.Length2048Bits);

The Generator

        public static Pki GenPki(
            string commonName,
            string organization,
            string organizationalUnit,
            string locality,
            string state,
            string countryIso2Characters = "US",
            string emailAddress = "",
            SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.SHA256,
            RsaKeyLength rsaKeyLength = RsaKeyLength.Length2048Bits)
        {
            Pki pki = new Pki();

            #region Determine Signature Algorithm

            string signatureAlgorithmStr;
            switch (signatureAlgorithm)
            {
                case SignatureAlgorithm.SHA1:
                    signatureAlgorithmStr = PkcsObjectIdentifiers.Sha1WithRsaEncryption.Id;
                    break;

                case SignatureAlgorithm.SHA256:
                    signatureAlgorithmStr = PkcsObjectIdentifiers.Sha256WithRsaEncryption.Id;
                    break;

                case SignatureAlgorithm.SHA512:
                    signatureAlgorithmStr = PkcsObjectIdentifiers.Sha512WithRsaEncryption.Id;
                    break;

                default:
                    signatureAlgorithmStr = PkcsObjectIdentifiers.Sha256WithRsaEncryption.Id;
                    break;
            }

            #endregion Determine Signature Algorithm

            #region Cert Info

            IDictionary attrs = new Hashtable();

            attrs.Add(X509Name.CN, commonName);
            attrs.Add(X509Name.O, organization);
            attrs.Add(X509Name.OU, organizationalUnit);
            attrs.Add(X509Name.L, locality);
            attrs.Add(X509Name.ST, state);
            attrs.Add(X509Name.C, countryIso2Characters);
            attrs.Add(X509Name.EmailAddress, emailAddress);

            X509Name subject = new X509Name(new ArrayList(attrs.Keys), attrs);

            #endregion Cert Info

            #region Key Generator

            RsaKeyPairGenerator rsaKeyPairGenerator = new RsaKeyPairGenerator();
            rsaKeyPairGenerator.Init(new KeyGenerationParameters
               (new SecureRandom(new CryptoApiRandomGenerator()), (int)rsaKeyLength));
            AsymmetricCipherKeyPair pair = rsaKeyPairGenerator.GenerateKeyPair();

            #endregion Key Generator

            #region CSR Generator

            Asn1SignatureFactory signatureFactory = new Asn1SignatureFactory
                                             (signatureAlgorithmStr, pair.Private);

            Pkcs10CertificationRequest csr = new Pkcs10CertificationRequest
                             (signatureFactory, subject, pair.Public, null, pair.Private);

            #endregion CSR Generator

            #region Convert to PEM and Output

            #region Private Key

            StringBuilder privateKeyStrBuilder = new StringBuilder();
            PemWriter privateKeyPemWriter = new PemWriter(new StringWriter(privateKeyStrBuilder));
            privateKeyPemWriter.WriteObject(pair.Private);
            privateKeyPemWriter.Writer.Flush();

            pki.PrivateKey = privateKeyStrBuilder.ToString();

            #endregion Private Key

            #region Public Key

            StringBuilder publicKeyStrBuilder = new StringBuilder();
            PemWriter publicKeyPemWriter = new PemWriter(new StringWriter(publicKeyStrBuilder));
            publicKeyPemWriter.WriteObject(pair.Private);
            publicKeyPemWriter.Writer.Flush();

            pki.PublicKey = publicKeyStrBuilder.ToString();

            #endregion Public Key

            #region CSR

            StringBuilder csrStrBuilder = new StringBuilder();
            PemWriter csrPemWriter = new PemWriter(new StringWriter(csrStrBuilder));
            csrPemWriter.WriteObject(csr);
            csrPemWriter.Writer.Flush();

            pki.Csr = csrStrBuilder.ToString();

            #endregion CSR

            #endregion Convert to PEM and Output

            return pki;
        }

The code above is self-explanatory. Put a break point, you will get the result similar to something like this:

-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEAns6T98tJ1MkDsP58np7oHs09fyhcGTFpLJ09z7xCwYaoUebB
vditQkboq33TNSEdDk31I97kosTsv/yB9amVgrh5hV2lRiPq3Lj6f6gNbJtQhC5E
HJyU5PYIW92wZ/d9JEbgiFHjeEk7/jg7CBfaQHcZv+Lo+lvYGeBDYHW4bj9RcYxy
zL76xsQfM9quPWwQ1+DRR2Fmrt7rHUSIjPpmzfLp/5kfsvAuV7mOG9v7dJBAA9wg
pOJ9dKXDVJkkvtR45FuFtrz2ptudO2sXTM48Ek0mbQxzdGRK/lFwgC9OSH6jzDBu
wJNt22WwA3yIAoKae7hsRdh+nzalvxsVDaVe9wIDAQABAoIBAB7JS3QxS8ndgkKw
wzX49mTqQu7Aw0H7Czmj7hS0mXhtA3qFMq/8LnJ3zqlYRja5ial5QXnHvyky5fa+
G++lBaAG5UAOjHjRg7lwftd6m8efQHevhHLLhC3y6GHu00EEgJUkzGiA/4kVIXVC
L2d9QElZDXveoG3Qmk9B463yhGOSwno6BhTtxknNiBqepP6CbA/z/SS+tLykxc5s
EGR+Jf+/ZPawqzURlpS8PYGrX+UFnIRbp4vmjHtr1+XgsnAxO4rLJ2jsx1cjZ6/l
ZAG2VMPm+J3+KvYA6kVEEdRIgP9zf/N25HOiqitWtD53HIxtWDnGjSkoUgTwWEfw
l++enHECgYEA199NbBbx7xVHXuubPAzKAM3MMrQ9IqsB9lHjcKh2tZ8N6ifl6bM/
TNf4oAZ8NVqReuAboaO28v2lhwk7y3yUuRv4n5LDt5mGjdGuWPxkJG/g+nCZ/u3X
ePq6jZ5ki/+u3qoxONAxcoBLkYJxD4RMq1SA+TNr5jPN2uEcri3SV8kCgYEAvFO2
SQDM65+twbW0iviHQJJzn2LYon1A/VqlKYhMl+XItxnbwP7jmrUIWvQMlcuK9bNf
3F3Lroh78oMqugTmeMudysF1bDBRJ5tIkCZBOCvZB4QjcyG+kGdIUj3O7Jlwp/T8
aV7CdjpNFfUPCXAg2Dh4Fyz94+UBKK1/Dyi24L8CgYB+3VHPyzBFlJjMFOS3BsEU
dd2iksA3Bo7xprBmfeq91ArGaMo6bMgvreEEkqseY+qJbvluJhuXdC96S5fjf4Sb
wO99QDBbTxN/dxHiY/mqXEG4jMJDyp1OEPPf1I08pXesjhK9U8UriHBgxGsTdmnk
apYdXfX0ZM9+6bsENhOe2QKBgFhIXdFHIMjr58ZA6cujybOJc84pxigV01txHK+l
h1JFk5vR8WQ9mHCzoKEServV2ORpG+zvw0WkEYaT2nmtRmUl/mhH3EXFOKX6cz+v
zy8Hzwto9D1KekyzPgHfm5rqKxdxDspOc5Z8qho68LuZ5qu1fQZQPwyQE8T/3+o5
SdF9AoGAUeLHda9eqYKhjzO/xNPPhb7+xRE27DbX12gnvY1KfH19iuerlQSn2ltM
5RrxJUTTvaUPO25FKnMh1gD4d2y2Vln43xT0InXtAQmA9l6cyeGvX8QUnnAu/R6v
6oNa4FdYqPrJ/ty81gTnYjvhHPdlPdPc66K/DKFyZxgUxChQBO8=
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE REQUEST-----
MIIC7jCCAdYCAQAwgaoxCzAJBgNVBAYTAlVTMR8wHQYDVQQLDBZJbmZvcm1hdGlv
biBUZWNobm9sb2d5MRgwFgYDVQQDDA9tYWlsLmdvb2dsZS5jb20xEjAQBgNVBAcM
CVNhbiBEaWVnbzEUMBIGA1UECgwLR29vZ2xlIEluYy4xITAfBgkqhkiG9w0BCQEW
EnN1cHBvcnRAZ29vZ2xlLmNvbTETMBEGA1UECAwKQ2FsaWZvcm5pYTCCASIwDQYJ
KoZIhvcNAQEBBQADggEPADCCAQoCggEBAJ7Ok/fLSdTJA7D+fJ6e6B7NPX8oXBkx
aSydPc+8QsGGqFHmwb3YrUJG6Kt90zUhHQ5N9SPe5KLE7L/8gfWplYK4eYVdpUYj
6ty4+n+oDWybUIQuRByclOT2CFvdsGf3fSRG4IhR43hJO/44OwgX2kB3Gb/i6Ppb
2BngQ2B1uG4/UXGMcsy++sbEHzParj1sENfg0UdhZq7e6x1EiIz6Zs3y6f+ZH7Lw
Lle5jhvb+3SQQAPcIKTifXSlw1SZJL7UeORbhba89qbbnTtrF0zOPBJNJm0Mc3Rk
Sv5RcIAvTkh+o8wwbsCTbdtlsAN8iAKCmnu4bEXYfp82pb8bFQ2lXvcCAwEAATAN
BgkqhkiG9w0BAQsFAAOCAQEATd2cFmef9SYxjYM0chKz0msHuoqfRlM5vaV13Rtm
zy7oFb9DHpuiPCOSxZvQYm5zKPPJtRBcM00yX+Bve9KiMK0ch5QFGT2Djn7De/d6
upi8kfs2DR7iSWVj6NkbVqydkfQqNpVk4hU15ikQY/FCWzfpIs7Pw/l5C8AFik/B
ZFjk9K52ZSndtRtojBMu9d8iODxPTGckA0EYsca79TuOHp8WhkQ+oHx5UN23v627
Y86uFPDM1ZoR2eT6583hE3WjC8aXpQxPQLyYhOIBP6e/KGPgv6X4nuz32L/6YWiS
qBazoB1DJ7PhBr4WdqiQy3fVN70n33cMEwEzq9OPSt5rOA==
-----END CERTIFICATE REQUEST-----

Done