8

I'm trying to load a particular private key encoded in binary DER format (PKCS#8) into Ruby.

However, OpenSSL::PKey won't recognize it. I can make it work by doing some console work and transforming it into a PEM like so:

openssl pkcs8 -inform DER -in file.key -passin pass:xxxxxxxx >private_key.pem

After this, the key can correctly be read.

However, since I would like for the whole process to be done in memory instead of writing and reading files.

So my question is: Is it possible to load private keys from the binary encoded DER format into Ruby/OpenSSL?

Thank you for your time,

Fernando

2 Answers 2

4

Yes, you can indirectly load PKCS#8 DER-encoded private keys using Ruby OpenSSL.

OpenSSL::PKey::RSA.new will only handle PEM-formatted PKCS#8, but it is easy to read the binary DER and convert it to a PEM-formatted string and then load from the string.

For example, with these DER-encoded private keys:

$ openssl genrsa | openssl pkcs8 -topk8 -outform DER \
    -nocrypt -out pkcs8.key
$ openssl genrsa | openssl pkcs8 -topk8 -outform DER \
    -v2 des3 -passout pass:secret -out pkcs8_des3.key

You can do something like this:

require 'openssl'
require 'base64'

def box(tag, lines)
  lines.unshift "-----BEGIN #{tag}-----"
  lines.push "-----END #{tag}-----"
  lines.join("\n")
end

def der_to_pem(tag, der)
  box tag, Base64.strict_encode64(der).scan(/.{1,64}/)
end

pem = der_to_pem('PRIVATE KEY', File.read('pkcs8.key'))
key = OpenSSL::PKey::RSA.new(pem)

pem2 = der_to_pem('ENCRYPTED PRIVATE KEY', File.read('pkcs8_des3.key'))
key2 = OpenSSL::PKey::RSA.new(pem2, 'secret')

Read the DER bytes, Base64 them and put the PEM tags on top and bottom, and then load the key.

Sign up to request clarification or add additional context in comments.

Comments

-1

Certificate is capable of handling DER-encoded certificates and certificates encoded in OpenSSL's PEM format.

You could find documentation about OpenSSL implementation for Ruby here :

3 Comments

That is incorrect. For PEM, the Ruby source calls PEM_read_bio_RSAPrivateKey, which calls PEM_read_bio_PrivateKey, which yes, handles PKCS#8. However, when DER, the Ruby source calls d2i_RSAPrivateKey_bio, which calls ASN1_item_i2d_bio(ASN1_ITEM_rptr(RSAPrivateKey), bp, rsa) (openssl-1.0.1m/crypto/rsa/rsa_asn1.c: ASN1_SEQUENCE_cb(RSAPrivateKey, rsa_cb) = { ASN1_SIMPLE(RSA, version, LONG), ...) which will not read PKCS#8. DER-encoded PKCS#8 cannot be loaded directly using OpenSSL::PKey::RSA.new.
My bad. I didnt know that the implementation of OpenSSL in ruby was different than what is said in the OpenSSL documentation...
Pretty sure that certificates and keys are different things, too...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.