Click here to Skip to main content
15,881,380 members
Articles / Programming Languages / C#
Tip/Trick

Generate PKI using Bouncy Castle: An Example

Rate me:
Please Sign up or sign in to vote.
4.05/5 (4 votes)
4 Jan 2018CPOL 19.2K   579   11   4
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:

Image 1

The Code

PKI Model

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

C#
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:

C#
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:

C#
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

C#
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

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
United States United States
while (live) {
try {
learn();
code();
food();
...
} catch (Exception ex) {
recover();
}
}

Comments and Discussions

 
QuestionHow can I add to the CSR the EnhancedKeyUsageExtension attribute Pin
Member 556120620-Feb-20 9:38
Member 556120620-Feb-20 9:38 
QuestionAdd extentions to the csr like a san list Pin
Member 140465868-Nov-18 1:20
Member 140465868-Nov-18 1:20 
QuestionMã hóa dùng BouncyCastle Pin
M I N C A4-Oct-18 10:53
M I N C A4-Oct-18 10:53 
GeneralMy vote of 4 Pin
RickZeeland4-Jan-18 23:16
mveRickZeeland4-Jan-18 23:16 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.