2

I am trying o create a method that constructs an AsymmetricKeyParameter from a PEM encoded public key. Unfortunately, pemReader.ReadObject() return null.

Here's a working solution for a private key: convert PEM encoded RSA private key to AsymmetricKeyParameter

What is wrong with this method?

static AsymmetricKeyParameter ReadPublicKeyFromPemEncodedString(string pemEncodedKey)
{
    AsymmetricKeyParameter result = null;
    using (var stringReader = new StringReader(pemEncodedKey))
    {
        var pemReader = new PemReader(stringReader);
        var pemObject = pemReader.ReadObject(); // null!
        result = ((AsymmetricCipherKeyPair)pemObject).Public;
    }

    return result;
}

Here is the PEM-encoded public key I am testing with. I have tried without the comment and also removing SSH2.

---- BEGIN SSH2 PUBLIC KEY ----
Comment: "rsa-key-20170608"
AAAAB3NzaC1yc2EAAAABJQAAAQEAk0AmagKx285Ufbri/olc+f3WagL1Ho+DrYdD
SbuU7cJAq+uD9xGvvP9m2JavSP4wO9i9pB/cmCFMPoIj3oGJt1/cnLb/U2juneOw
6Uo0N3F8TXdyXfZNAIPhq/jw0YfIypTFTTvFkKXfTArIwW/bQBW8/dujFR8i5CxP
jRKRDOBEy0PPOLJDD0iUr9GX/h/EO4jQ7B/GszjhPiPx+gJCilaMY+jrSczjxpsK
OXzpZEdT1NqMrzgvIZPHYhQzAiw9vQzov3vezDwKgKcRrUixZ2B8uiEQNn7Wa2Qz
WF3vL+6CGflFNYQcc0leDQBe86baYhCollouP4jfaH9KcMkYYw==
---- END SSH2 PUBLIC KEY ----
Suraj
  • 35,905
  • 47
  • 139
  • 250

1 Answers1

2

Bouncy castle just does not understand this format of public key (SSH2) (you can verify this by looking at source code of PemReader if you would like to). Unfortunately I don't know how to convert it to appropriate format in C#, but you can do that with many tools, for example with ssh-keygen (also available in gitbash for windows), or openssl. Your public key will look like this when converted to PEM:

-----BEGIN RSA PUBLIC KEY-----
MIIBCAKCAQEAk0AmagKx285Ufbri/olc+f3WagL1Ho+DrYdDSbuU7cJAq+uD9xGv
vP9m2JavSP4wO9i9pB/cmCFMPoIj3oGJt1/cnLb/U2juneOw6Uo0N3F8TXdyXfZN
AIPhq/jw0YfIypTFTTvFkKXfTArIwW/bQBW8/dujFR8i5CxPjRKRDOBEy0PPOLJD
D0iUr9GX/h/EO4jQ7B/GszjhPiPx+gJCilaMY+jrSczjxpsKOXzpZEdT1NqMrzgv
IZPHYhQzAiw9vQzov3vezDwKgKcRrUixZ2B8uiEQNn7Wa2QzWF3vL+6CGflFNYQc
c0leDQBe86baYhCollouP4jfaH9KcMkYYwIBJQ==
-----END RSA PUBLIC KEY-----

And it will be correctly handled by your current code, with a little change:

var pemReader = new PemReader(stringReader);
var pemObject = pemReader.ReadObject(); // null!
// it's already AsymmetricKeyParameter
result = ((AsymmetricKeyParameter)pemObject);
Evk
  • 98,527
  • 8
  • 141
  • 191
  • I can't seem to get this to roundtrip. Meaning, for the public key you posted, I was able to get the AsymmetricKeyParameter just fine, but when I use a PemWriter to write it to a string, it's a different string. I put the before/after in a diff tool and the "after" has a chunk of text in the key that doesn't appear in the string above. Also, the "after" starst with "BEGIN PUBLIC KEY" and not "BEGIN RSA PUBLIC KEY" – Suraj Jun 09 '17 at 18:47
  • Well that's yet another format, you can read about differences in this question: https://stackoverflow.com/q/20065304/5311735. It still represents the same public key though. Maybe you can describe what is actually the goal of what you are doing. – Evk Jun 09 '17 at 20:21
  • Thanks! that's helpful! My goal is to unit test a method I wrote to PEM encode an AsymmetricKeyParameter.Public. I figured a good test would be to construct such a key from a PEM encoded string and then pass that to my method and check if it roundtrips. – Suraj Jun 09 '17 at 21:15
  • I'd say it's better to encode this key, then decode it (back to AsymmetricKeyParameter) and then compare original and decoded keys (that is: exponent, modulus etc, not their encoded versions). – Evk Jun 09 '17 at 21:20
  • Agreed, that's a better test. Was being a bit lazy =) – Suraj Jun 09 '17 at 21:27
  • Yeah, this SSH2 format (https://tools.ietf.org/html/rfc4716 I assume) is not compatible with the PEM format that BC supports, although we'd have all the supporting code you'd need to build a parser for it, if anyone feels like contributing such to the project. – Peter Dettman Jun 10 '17 at 04:58