3

I am trying (but failing) to create a method that constructs an AsymmetricKeyParameter from a PEM encoded private key. How can I complete this method?

It seems that an older version of BouncyCastle had a pemReader.ReadObject() method whose results could be casted, but that no longer exists.

I have tried various combinations of using PrivateKeyFactory, PrivateKeyInfo, Asn1Object and perhaps 10 other types, but all are throwing an exception at some point.

static AsymmetricKeyParameter ReadPrivateKeyFromPemEncodedString(string pemEncodedKey)
{
    AsymmetricKeyParameter result = null;
    using (var stringReader = new StringReader(pemEncodedKey))
    {
        var pemReader = new PemReader(stringReader);
        var pemObject = pemReader.ReadPemObject();
        // WHAT NEXT???
    }            

    return result;
}

Here is the PEM-encoded key I am testing with:

-----BEGIN RSA PRIVATE KEY-----
MIIEoAIBAAKCAQEAk0AmagKx285Ufbri/olc+f3WagL1Ho+DrYdDSbuU7cJAq+uD
9xGvvP9m2JavSP4wO9i9pB/cmCFMPoIj3oGJt1/cnLb/U2juneOw6Uo0N3F8TXdy
XfZNAIPhq/jw0YfIypTFTTvFkKXfTArIwW/bQBW8/dujFR8i5CxPjRKRDOBEy0PP
OLJDD0iUr9GX/h/EO4jQ7B/GszjhPiPx+gJCilaMY+jrSczjxpsKOXzpZEdT1NqM
rzgvIZPHYhQzAiw9vQzov3vezDwKgKcRrUixZ2B8uiEQNn7Wa2QzWF3vL+6CGflF
NYQcc0leDQBe86baYhCollouP4jfaH9KcMkYYwIBJQKCAQA7sjkWOHGeTLp4KSuX
n3i4X/z6i5POHoF9s2B31mzPF2ZTiP4l5JNadWELsrXDpVHTEq2/E9X4fDOqo3ZT
SUWrNLNiIKyzHLPDd/uc2OS8h/QfZ8aUy6KtLovrxclps5aXURG3hu86pBxBbCff
t7nACNAT42ugx28CjoEdhBFKaCNcw/S3gZOkcotVdDUTCB+epveXNybAoZcuVNtu
Y84hx+st8i0sXY+vpIJ8HOanbpdS/Q9UqDGNvg1zBlvnJ7PGOO4Jnc0EOa1Eoym2
vJNItDAkK59KPKjuBLWTvTz/XLrZirkY57BQgUKnXHU6YGI7bvu8+iDnNAP1C90U
/MllAoGBANstq/L7WOgcOhfbWEmcd59/vBtDbgf0pNwYyhmpIrG2SD6XaljQvOvo
2/2oqNzCG+xZbTnbdkODRIXMDGcCzVkQAEkNvwWYHxb2XHUOhUPr+4zNfGtnJ1gv
o7w6FVI3tD4buSmhcFZUGpNyzSbS+6FdXD37qjOFCPKcJMCY4BSPAoGBAKv9CdXw
Ksyhr62sWqlU2F9FhjDNS9afJ5A7mZjrPraAusVsOkUtwsij9g74SH5agQNIUnFH
NBwNenW+kbYahX6Q5pjNN5s6weG+2kbK8kZyuYo+Fuix0u6bTnL2IH35zP+hYWQS
YM7yNDdBpH1deTWlTVL7vnZeEK/WTldw8PDtAoGAZLQekjwh7hrOlVbxNpP/nE9y
Gl1AZIUpJtr1ErV+pK2yfZ+D454tScvastDzo7MhlhtABdOJXUomZvzjGpKVs0yK
gm4ZfxxhT71NEzAvZGWBajTmI4JsBexf/Iljvf3rB8eMbRLSv+Fz/o6xSTCBc6dv
khmvEMCVaIzuSqca2QMCgYAue714F2WDafghGdNQXB7NpBZuDfjSONpCqFMGvB7J
ipNX87y4wEJ7apWHgV+zcmgOuZm9wDeY4QxXLJYViqCev2DrBwgcHbfcJb5z/3/A
A1S9lD2K/6DK3d3Z4afqsjdnrxNnJ4/JOoqnJn971BLr53yupOdeQu/A0iMC4EEe
hQKBgBCJteVdDk/0gK5c/++q88VIYplEDeDCiO2nIjXK7kHrm0q3DuUsr3D6VOjL
VUViiU2nBKn40R8tNnxagPkL/uec0kZMGnnFsJLLKd48DGr34nQjsrGare0Pr8yo
3uwlkKwtDUg5Zf2vLIIKqcX6tvHSQ2Zc57dAdAPvhpM5TtDJ
-----END RSA PRIVATE KEY-----
Suraj
  • 35,905
  • 47
  • 139
  • 250
  • Actually, Org.BouncyCastle.OpenSsl.PemReader still exists, and its ReadObject() can still do what you need here I think. Perhaps the addition of Org.BouncyCastle.Utilities.IO.Pem.PemReader is causing confusion? – Peter Dettman Jun 09 '17 at 04:28
  • 1
    big sigh. yeah, that was the confusion. thanks so much. Would you mind posting your comment as the answer so I can accept and upvote? I edited my post with the solution. It baffles me that folks think that having two public classes of the same name in the same project is a good idea. These classes should be renamed to OpenSslPemReader and UtilityPemReader so that it's 100% obvious from the name what it does and why it's qualified and you don't have to lean on reading the using directives. Anyways, I doubt that will change based on the maturity of this project. – Suraj Jun 09 '17 at 13:49
  • @PeterDettman - can you help with this one... https://stackoverflow.com/questions/44459497/convert-pem-encoded-rsa-public-key-to-asymmetrickeyparameter – Suraj Jun 09 '17 at 13:53
  • I agree the PemReader name-sharing is less than ideal. We have in other places chosen to include namespace-specific prefixes on classes. There is sometimes (not here) a tension arising from wanting names to exactly match structures in standards documents, which can work against this. I will look into deprecating/duplicating the openssl one in favour of, say OpenSslReader, as the other one is already appropriately named. Unfortunately we must allow for the extensive "external documentation" on sites such as this, using existing class names. – Peter Dettman Jun 10 '17 at 04:51
  • Oh and feel free to self-answer with your working solution. – Peter Dettman Jun 10 '17 at 04:51
  • @PeterDettman - Thanks for considering the rename. I'm just now seeing that PemReader extends PemReader =) so I like the idea of an OpenSslReader that extends a PemReader. I think that OpenSslPemReader would be a slightly better name. I favor using base class names in derived classes so that the "is a kind of" relationship is super clear. OpenSslPemReader is a kind of PemReader. Anyways, just my $.02. – Suraj Jun 11 '17 at 19:00

1 Answers1

2

Here's a working solution:

using Org.BouncyCastle.OpenSsl;

private static AsymmetricKeyParameter ReadPrivateKeyFromPemEncodedString(string pemEncodedKey)
{
    AsymmetricKeyParameter result;
    using (var stringReader = new StringReader(pemEncodedKey))
    {
        var pemReader = new PemReader(stringReader);
        var pemObject = pemReader.ReadObject();
        result = ((AsymmetricCipherKeyPair)pemObject).Private;
    }

    return result;
}
Suraj
  • 35,905
  • 47
  • 139
  • 250