3

I'm trying to generate RSA keypairs in Ruby, mostly using the examples from this blog post. Here is my slightly modified code:

def generate_keypair(passphrase)
   rsa_key = OpenSSL::PKey::RSA.new(2048)
   cipher =  OpenSSL::Cipher::Cipher.new('aes-256-cbc')
   private_key = rsa_key.to_pem(cipher, passphrase)
   public_key = rsa_key.public_key.to_pem
   return private_key, public_key
end

This successfully generates a private key and a public key, and I can write those out to files on the filesystem.

irb(main):002:0> private_key1, public_key1 = generate_keypair('test')
[...output of keys...]
irb(main):003:0> File.open("key.pem","w") {|f| f.write(private_key1) }
=> 1766
irb(main):004:0> File.open("pubkey.pem","w") {|f| f.write(public_key1) }
=> 426

However, OpenSSL complains when I try to use this public key:

$ openssl rsautl -encrypt -inkey pubkey.pem -pubin -in text.txt -out text.ssl
unable to load Public Key

If I use the openssl tool to extract the public key from the private key then everything works:

$ openssl rsa -in key.pem -pubout -out pubkey2.pem
Enter pass phrase for key.pem:
writing RSA key
$ openssl rsautl -encrypt -inkey pubkey2.pem -pubin -in text.txt -out text.ssl
$ openssl rsautl -decrypt -inkey key.pem -in text.ssl 
Enter pass phrase for key.pem:
this is a 
file that
needs to be
encrypted

The public key that the Ruby OpenSSL library produced is different from the public key that the openssl cli tool extracted from the private key:

$ cat pubkey.pem 
-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEAzgNcsEL7yGBoLBYBXFYrDL6oLP8ZbW9+VwdoXyNG6Qt/NEhEx4Ww
5yOxtXAbqeUwyvbTUxRrJ02dQcb4FGcSMDgz2QHIZyCuDJkgC9Wj7KI1Q7g0GV+7
DcZvLcwPZOhLXqUzlcZXjDWM1PZ+az734qEribgyI+87LB8TujG8v5iOvdzT/Je4
JAllToZVGC3RddfTc6ww37gB39B++FYNzPg+nrIEU45KgEWPo2eJxBpX29lACh6q
EEBCQr9xyLxOC2eomYIl3dG2dV7nGGH7Pur2HjppgJphBvNkwxIWUa/pD6hAnOQ4
MkDDFGwWv7eJLb4UZuZjafTbqokHved3bwIDAQAB
-----END RSA PUBLIC KEY-----

$ cat pubkey2.pem 
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzgNcsEL7yGBoLBYBXFYr
DL6oLP8ZbW9+VwdoXyNG6Qt/NEhEx4Ww5yOxtXAbqeUwyvbTUxRrJ02dQcb4FGcS
MDgz2QHIZyCuDJkgC9Wj7KI1Q7g0GV+7DcZvLcwPZOhLXqUzlcZXjDWM1PZ+az73
4qEribgyI+87LB8TujG8v5iOvdzT/Je4JAllToZVGC3RddfTc6ww37gB39B++FYN
zPg+nrIEU45KgEWPo2eJxBpX29lACh6qEEBCQr9xyLxOC2eomYIl3dG2dV7nGGH7
Pur2HjppgJphBvNkwxIWUa/pD6hAnOQ4MkDDFGwWv7eJLb4UZuZjafTbqokHved3
bwIDAQAB
-----END PUBLIC KEY-----

I'm not quite sure what is going on here, but it seems as if the Ruby OpenSSL library is producing an invalid public key pem file. Am I doing something wrong?

corywright
  • 95
  • 2
  • 5
  • See the answer to my own similar question at http://stackoverflow.com/a/36302768/232250 – raphink Mar 30 '16 at 07:53
  • Also see [Use OpenSSL RSA key with .Net](http://stackoverflow.com/q/30475758). It discusses how to use OpenSSL to save a key with both PKCS and Traditional encodings (`BEGIN RSA PUBLIC KEY` versus `BEGIN PUBLIC KEY`). – jww Mar 31 '16 at 02:51

1 Answers1

3

It seems that OSSL doesn't support that format. What "openssl rsa" generates is an RSA_PUBKEY structure: a PUBKEY record which is ASN.1-"tagged" (with an OID) to indicate that it's an RSA key. What Ruby generates is a "raw" RSA key (where the bytes don't indicate that it is RSA; so you have to declare that in the PEM header).

OSSL should use an API function like PEM_write_bio_RSA_PUBKEY (or the generic PEM_write_bio_PUBKEY), instead of/in addition to PEM_write_bio_RSAPublicKey.

Martin v. Löwis
  • 124,830
  • 17
  • 198
  • 235
  • Thanks, that's very helpful. I've been looking around for documentation about ways to add this information to the PEM header, but haven't found anything. Do you have any recommendations? I'd prefer to avoid having to shell out to openssl, but could as a last resort. – corywright Jan 08 '11 at 21:20
  • @corywright: Report this bug to OSSL. If you can, produce a patch that offers an alternative way to encode the public key. In principle, it would be possible to convert the two forms in pure Ruby, but you'll have to be an expert on ASN.1 DER to do that. – Martin v. Löwis Jan 08 '11 at 21:26