require "openssl" # Certificate: the constructor reads PEM or DER; to_der and to_pem write eithercert = OpenSSL::X509::Certificate.new(File.binread("cert.pem"))File.binwrite("cert.der", cert.to_der)File.write("cert-again.pem", OpenSSL::X509::Certificate.new(File.binread("cert.der")).to_pem) # Private key: private_to_der / private_to_pem write PKCS#8 for every key typekey = OpenSSL::PKey.read(File.binread("key.pem")) # PEM or DER; pass a password for encrypted keysFile.binwrite("key.der", key.private_to_der)File.write("key-again.pem", OpenSSL::PKey.read(File.binread("key.der")).private_to_pem) # Public key: SubjectPublicKeyInfo DERFile.binwrite("pub.der", key.public_to_der) How it works
OpenSSL::X509::Certificate.new(File.binread(path))takes PEM or DER;to_derwrites the 563-byte DER,to_pemthe PEM — identical to the original file.OpenSSL::PKey.readloads any key type from PEM or DER (pass a password as the second argument for encrypted keys);private_to_derwrites PKCS#8 DER (138 bytes here).public_to_derwrites the SubjectPublicKeyInfo — the public key in the form other libraries import.- Use
File.binread/File.binwritefor DER, so no encoding conversion touches the bytes.
Gotchas
key.to_derandkey.to_pemon an EC key write SEC1, not PKCS#8: 121 bytes, version INTEGER1, and-----BEGIN EC PRIVATE KEY-----in PEM. Useprivate_to_der/private_to_pemfor PKCS#8.OpenSSL::X509::Certificate.newreads one certificate; for a bundle,OpenSSL::X509::Certificate.load(text)returns all of them (2 in the run), each with its ownto_der.
Related recipes
- How to convert a certificate and a private key between PEM and DER in PHP
- How to convert a certificate and a private key between PEM and DER in Python
- How to convert a certificate and a private key between PEM and DER with OpenSSL
- How to export a public key as PEM in Ruby
- How to decode an X.509 certificate in Ruby