digitalbazaar / forge

A native implementation of TLS in Javascript and tools to write crypto-based and network-heavy webapps
https://digitalbazaar.com/
Other
5.06k stars 779 forks source link

publicKeyTo/FromPem issue #58

Closed Ayms closed 11 years ago

Ayms commented 11 years ago

Hi,

The following public key pem:

-----BEGIN RSA PUBLIC KEY----- MIGJAoGBALRbNcv5vHKpaRvM53E/Dl4QGGO7CjhsHBld8v6Lgx4I2OGVvNCaAop4 rk2GfMmI48gnGEm+dtWAO7n4FEv9FgtV2xFMyBIQFud0y19Yr6pYfb4L9GIBNTCi vT/+poRHuDHlIyMk636t0ep4iWKR468az514tKZfyWY8pUsk8apTAgMBAAE= -----END RSA PUBLIC KEY-----

gives an error if we use publicKeyFromPem.

The same key (modulus: 8bd0a81286858b11f2856ac2f3efd8a5e538b2f851a4c02cc717c94ea52418c587cc69515e46b5381d17cd2299cb4c59fae38250898eab31c9b8acfcf02110a96f0f03442ecd34f1befb0604e1ffbb981848534da9f3f23795ed7df047730cb9dab711722ad6504b893cebda2de4b41123d667474a166eba3ead7df8267dda15) gives with publicKeyToPem:

-----BEGIN PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCL0KgShoWLEfKFasLz79il5Tiy +FGkwCzHF8lOpSQYxYfMaVFeRrU4HRfNIpnLTFn644JQiY6rMcm4rPzwIRCpbw8D RC7NNPG++wYE4f+7mBhIU02p8/I3le198EdzDLnatxFyKtZQS4k869ot5LQRI9Zn R0oWbro+rX34Jn3aFQIDAQAB -----END PUBLIC KEY-----

But openssl for example does not decode the second one, so probably the first one is correct.

I am wondering if the issue is not affecting certificateToPem too (could it be?), since I am having quite a hard time to make something work while everything looks correct, the only thing that I did not check is to decode a certificate pem with something else than forge.

Regards

Aymeric

dlongley commented 11 years ago

So there was a bug that caused a problem with parsing RSA PUBLIC KEY pem files, but that's been fixed now. However, I couldn't reproduce the openSSL behavior that it seemed you were suggesting, rather I get the opposite. Specifically, the PEM with a header containing RSA PUBLIC KEY will not load with openSSL but the one with the header containing just PUBLIC KEY will.

openssl rsa -in <filename> -pubin -text yields an error for the RSA PUBLIC KEY case because it's expecting just PUBLIC KEY. See the docs here: http://www.openssl.org/docs/apps/rsa.html

Ayms commented 11 years ago

Strange, indeed your test shows the contrary.

The openssl doc does maybe not reflect the standard because openssl itself fails doing : BIO *bio = LoadBIO(args[0]);rsa = PEM_read_bio_RSAPublicKey(bio, NULL, NULL, NULL);

The use case comes for Tor descriptors, something like:

router idideditheconfig 46.4.35.2 9001 0 0 platform Tor 0.2.3.25 on Linux opt protocols Link 1 2 Circuit 1 published 2013-07-24 18:59:32 opt fingerprint FD62 26E0 1ED9 C4FE 881D C3C2 166D FECE CB56 5B25 uptime 17899962 bandwidth 10485760 20971520 3416140 opt extra-info-digest FF3BE669C63A74BC7BCCCD3FD3886ABF4C5A3C7C onion-key -----BEGIN RSA PUBLIC KEY----- MIGJAoGBALuzml0Wah8BBklTD+uZ1T/Xgue83Et4b4gjeVBB4OLmKfsXkz860xlT rl2T47ge4J8+4cN+Yi0FkMKWBRUmxrI4qiIZnsUnR6VgLhAjcteCYqaxOLcSDQJR dJz8HaSML1IBcTuIkxzkC/KDfX/x7TJ+15f6DXDsljSriy6SIqoJAgMBAAE= -----END RSA PUBLIC KEY----- signing-key -----BEGIN RSA PUBLIC KEY----- MIGJAoGBAK50veVYPAfmo5tPcMCeF/onEu8orWKB8eOsPlxv9GiwzjRsuG26yabA N/irKy4BvEfm9EwMX3XDoYTaBbuThnkYMpASdg3253TXXcZEbofgXHrkCp7lEXK7 kVUwMcKfJYtYJy8Ii+f4EtQxY0AN/1fh45XlqEkbEjgfsdVCJninAgMBAAE= -----END RSA PUBLIC KEY----- opt hidden-service-dir contact Random Person reject : router-signature -----BEGIN SIGNATURE----- SdwXpqcoYJ2jQ4+heAzzqnYknfJbsMCieuOSr3RPIKm2Zb80NeVDmwHk/UOcgSRI u397FB5GEU1eShNGnJ0cIxa+fzKllWEW3butLzjzxMvPa3dlwhYWSCmRu3Pm55ij PNLPM/x0ZhFlQIQ+cBRXxkJcSq5fLXjJG2qCdkRHq4M= -----END SIGNATURE-----

But forge.pki.pemToDer(* RSA PUBLIC KEY ) works! As well as forge.pki.pemToDer(** PUBLIC KEY ***), but does not give the same result.

I don't know who invented this stuff, quite annoying, not sure who is right or wrong here, maybe you can figure it out, thanks to let me know if there is an impact on certificateToPem too.

dlongley commented 11 years ago

forge.pki.pemToDer It wouldn't yield the same result because it's not the same ASN.1 structure. When just PUBLIC KEY is used, a ASN.1 SubjectPublicKeyInfo structure is used as a wrapper for the ASN.1 RSAPublicKey structure. Otherwise, it's just the latter. Anyway, are you able to load the RSA PUBLIC KEY using the latest version of forge now? If so, can we close this issue or is there another problem?

Note that you can also do forge.pki.publicKeyToRSAPublicKeyPem to produce the RSA PUBLIC KEY pems via forge. There shouldn't be any problems with certificateToPem, but if you encounter any, please create a new issue.

Ayms commented 11 years ago

No, it's not possible to load RSA public key with the latest version of forge (please see at the end of the code provided for #58).

forge.pki.publicKeyToRSAPublicKeyPem works but returns:

-----BEGIN RSA PUBLIC KEY----- MIGJAoGBAIvQqBKGhYsR8oVqwvPv2KXlOLL4UaTALMcXyU6lJBjFh8xpUV5GtTgd F80imctMWfrjglCJjqsxybis/PAhEKlvDwNELs008b77BgTh/7uYGEhTTanz8jeV 7X3wR3MMudq3EXIq1lBLiTzr2i3ktBEj1mdHShZuuj6tffgmfdoVAgMBAAE= -----END RSA PUBLIC KEY-----

Which is different from what I have and can not be read either by publicKeyFromPem

Ayms commented 11 years ago

I meant #59 of course for the code

dlongley commented 11 years ago

@Ayms, when I import the PUBLIC KEY from the code from #59 I get the correct modulus. If I output to a PEM with the RSA PUBLIC KEY header and then import using forge.pki.publicKeyFromPem I get the same modulus again. What exactly isn't working for you? It seems to be working just fine on my end.

var forge = require('forge');
var assert = require('assert');

var pub = '-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCL0KgShoWLEfKFasLz79il5Tiy\n+FGkwCzHF8lOpSQYxYfMaVFeRrU4HRfNIpnLTFn644JQiY6rMcm4rPzwIRCpbw8D\nRC7NNPG++wYE4f+7mBhIU02p8/I3le198EdzDLnatxFyKtZQS4k869ot5LQRI9Zn\nR0oWbro+rX34Jn3aFQIDAQAB\n-----END PUBLIC KEY-----';

var publicKey1 = forge.pki.publicKeyFromPem(pub);
console.log('publicKey1: ' + publicKey1.n.toString(16));

var rsaKeyPem = forge.pki.publicKeyToRSAPublicKeyPem(publicKey1);
console.log('pem: ' + rsaKeyPem);

var publicKey2 = forge.pki.publicKeyFromPem(rsaKeyPem);
console.log('publicKey2: ' + publicKey2.n.toString(16));

assert.equal(publicKey1.n.toString(16), publicKey2.n.toString(16));
dlongley commented 11 years ago

@Ayms, I just checked your code from #59 -- and it is not the latest code from forge. It does not contain the bug fix I submitted for this issue. Please update and try again.

Ayms commented 11 years ago

@dlongley Yes! I did not realize that you made this change about the same time I was posting this issue and after I synced forge, it's OK now, I close it.