Search code examples
c#rsabouncycastlekey-pair

How to convert RSA public key to string using BouncyCastle c#


I'm trying to save RsaKeyParameter Public Key into an SQL database. I get an error that Bouncy Castle can't convert RsaKeyParameters to bytes.

Using BouncyCastle c#.

I've generate an RSA key pair, extracted the private and public keys into variables. I then need to store the public key for verification at a later stage in the application.

I found a post on converting to byte then string as follows;

byte[] serializedPublicBytes = 
publicKeyInfo.ToAsn1Object().GetDerEncoded();
string serializedPublic = Convert.ToBase64String(serializedPublicBytes);

but it doesn't like ToAsn1Object. Just to add this is an example, I'm aware my variable names are different.

        RsaKeyPairGenerator rsaKeyPairGen = new RsaKeyPairGenerator();
        rsaKeyPairGen.Init(new KeyGenerationParameters(new SecureRandom(), 2048));
        AsymmetricCipherKeyPair keyPair = rsaKeyPairGen.GenerateKeyPair();

        RsaKeyParameters PrivateKey = (RsaKeyParameters)keyPair.Private;
        RsaKeyParameters PublicKey = (RsaKeyParameters)keyPair.Public;

The public key should to byte, then string, to save into the database.


Solution

  • The public key can be converted to the X.509/SubjectPublicKeyInfo-ASN.1/DER-format using BouncyCastle. This is a binary format from which a string can be generated using Base64-encoding:

    byte[] publicKeyDer = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(publicKey).GetDerEncoded();
    String publicKeyDerBase64 = Convert.ToBase64String(publicKeyDer);
    

    Here, publicKey is the public key stored in the RsaKeyParameters-instance. The reverse process is:

    byte[] publicKeyDerRestored = Convert.FromBase64String(publicKeyDerBase64);
    RsaKeyParameters publicKeyRestored = (RsaKeyParameters)PublicKeyFactory.CreateKey(publicKeyDerRestored);
    

    Detailed descriptions of the X.509/SubjectPublicKeyInfo- and ASN.1/DER-format can be found here and here, respectively.

    Both, publicKeyDer (as hex-string) and publicKeyDerBase64, can be displayed in an ASN.1-Editor, e.g. https://lapo.it/asn1js/

    Another approach is to create the PEM-format using the Org.BouncyCastle.OpenSsl.PEMWriter- and Org.BouncyCastle.OpenSsl.PEMReader-class (not to be confused with Org.BouncyCastle.Utilities.IO.Pem.PEMWriter/PEMReader):

    TextWriter textWriter = new StringWriter();
    PemWriter pemWriter = new PemWriter(textWriter);
    pemWriter.WriteObject(publicKey);
    pemWriter.Writer.Flush();
    String publicKeyPEM = textWriter.ToString();
    

    and the reverse is:

    TextReader textReader = new StringReader(publicKeyPEM);
    PemReader pemReader = new PemReader(textReader);
    RsaKeyParameters publicKeyRestored = (RsaKeyParameters)pemReader.ReadObject();
    

    The PEM-format is essentially a textual representation of the DER-format using an implicit Base64-encoding (e.g. explained here) and a header (-----BEGIN PUBLIC KEY-----) and footer (-----END PUBLIC KEY-----). Therefore, the Base64-encoded part is identical (if line breaks are ignored) for both, publicKeyDerBase64 and publicKeyPEM.