I just spent a long time diagnosing an RSA public key exchange problem. Google was of very little help so hopefully this article will get picked up save someone else the trouble in the future.
The problem is this an RSA public key PEM or DER generated by
Ruby’s OpenSSL::PKey::RSA are unreadable by
OpenSSL, Bouncy Castle and probably other crypto tools.
For example, if you try to load a public key PEM file generated by
OpenSSL::PKey::RSA with the openssl command you get the following
error
$ openssl rsa -text -pubin < my_pub_key.pem
unable to load Public Key
16879:error:0906D06C:PEM routines:PEM_read_bio:no start line:pem_lib.c:647:Expecting: PUBLIC KEY
and if you try to load a DER generated by OpenSSL::PKey::RSA you get this error
$ openssl rsa -text -pubin -inform DER < my_pub_key.cer
unable to load Public Key
16880:error:0D0680A8:asn1 encoding routines:ASN1_CHECK_TLEN:wrong tag:tasn_dec.c:1294:
16880:error:0D07803A:asn1 encoding routines:ASN1_ITEM_EX_D2I:nested asn1 error:tasn_dec.c:380:Type=X509_ALGOR
16880:error:0D08303A:asn1 encoding routines:ASN1_TEMPLATE_NOEXP_D2I:nested asn1 error:tasn_dec.c:749:Field=algor, Type=X509_PUBKEY
The actual issue is that Ruby’s OpenSSL::PKey::RSA#to_pem and
#to_der generate a PKCS#1 public key format
while the openssl rsa command only works PKCS#8 formatted
public keys. Both of the forms are grammars in the dreaded ASN.1
binary format which completely obscures the differences between them.
Both formats encode the exact same information
but the PCKS#8 style does it in a more complicated way.
I have not found a good solution to this problem. There does not seem
to be any way to make OpenSSL::PKey::RSA#to_pem generate anything
other than a PKCS#1 style key. I suspect that OpenSSL is able to
handle PKCS#1 public keys but there does not seem to be any way to get
the openssl command to do so. Similarly, it seems from Bouncy
Castle’s API docs that you should be able to coerce it into accepting
PKCS#1 public keys does not do so by default.
Fortunately, OpenSSL::PKey::RSA#new works just fine if handed a
PKCS#8 PEM. That has allowed me to work around this issue by using
the openssl command to generate the PKCS#8 style PEM files (both
private and public using openssl genrsa and openssl rsa -pubout
respectively) and then just reading/serving those files as needed. It is
not great but it does work.
Post a Comment