Ruby OpenSSL pkcs8 .key to .pem - ruby

We run this command via Gem.
openssl pkcs8 -inform DER -in file_init.key -passin pass:secret -out file_key.pem
All works fine on shell, we wanna convert this line to openssl with ruby, we tried:
key_file = OpenSSL::PKey::RSA.new File.read('file_init'), 'secret'
puts key_file.to_pem_pkcs8
But we get:
`initialize': Neither PUB key nor PRIV key: nested asn1 error (OpenSSL::PKey::RSAError)
Any advice?

Ruby's openssl implementation doesn't handle pkcs8 encrypted der key-file.
There is a workaround (converting the der to PEM by base64 encoding the der + adding correct headers) here:
Load PKCS#8 binary key into Ruby

Related

Convert openssl command in ruby language using OpenSSL-Gem

i'm going crazy
I need to convert this openssl command
openssl smime -verify -in mysignedfile.xml.p7m -inform der -noverify -out simplefile.xml
into Ruby / RoR language. It's working as expected in console but I can't find the way to use it in ruby.
looking at the OpenSSL document, I can not succeed
this is an example of code
myfile = File.read "mysignedfile.xml.p7m"
OpenSSL::PKCS7::read_smime(myfile)
Response:
OpenSSL::PKCS7::PKCS7Error: no content type
The file was successfully opened (i can read it), but i think read_smime expect for some value as content_type

How do I convert a SSH2 PUBLIC KEY (rsa-key file) to PEM? (Base-64 encoded public key of X.509 certificate)

I have a private/public key that was generated by Putty in the following format:
SSH2 PUBLIC KEY rsa-key
However, I am trying to get it to work with Docebo API using the JWT Grant Type, which requires a different format (according to this post).
How would I convert my key(s) to work with that format? Is there a way within Putty?
I figured out the steps to take to get the proper format of key using OpenSSL:
openssl genrsa -out private.key 1024
openssl req -new -x509 -key private.key -out publickey.cer
openssl x509 -in publickey.cer -out publickey.pem

ruby openssl smime encryption

I am looking for ruby code to mimic below openssl smime encryption. I looked up other related topics but mostly were around signing. In snippet below cert.pem is a PEM-encoded X.509 certificate containing the PEM public key. token.txt file is the file to be encrypted.
openssl smime -encrypt -out encrypted.p7m -in token.txt cert.pem
Figured it.
token_plain_text = File.read("/path/to/token.txt")
cert = X509::Certificate.new("/path/to/cert.pem")
encrypted_object = OpenSSL::PKCS7.encrypt([cert], token_plain_text)
Got the encrypted string by outputting above object to string.
encrypted_str = encrypted_object.to_str

OpenSSL::PKCS7::PKCS7Error: decrypt error

smime = OpenSSL::PKCS7.read_smime(File.read('encrypted_smime.p7m'))
p_key = OpenSSL::PKey::RSA.new(File.read('pr_key.pem'))
cert = OpenSSL::X509::Certificate.new(File.read('cert.pem'))
smime.decrypt(p_key, cert)
In the decrypt line above, I am getting the error OpenSSL::PKCS7::PKCS7Error: decrypt error.
I am not sure why this error is causing, as I am able to decrypt the smime using openssl command line tool properly. Also I have verified that the cert I am using is signed using the same private key that I am using in p_key.
Following is the command which is getting me the expected output -
openssl smime -decrypt -in encrypted_smime.p7m -inkey pr_key.pem -out decrypt_smime.pem
What is the problem, and how do I fix it?

Ruby code for openssl to generate fingerprint

I need the ruby equivalent of the following:
openssl x509 -sha1 -fingerprint -noout -in cert.pem
The code that I wrote is:
data = File.read("cert.pem")
data["-----BEGIN CERTIFICATE-----\n"]=""
data["-----END CERTIFICATE-----\n"]=""
OpenSSL::Digest::SHA1.new(Base64.encode64(data))
This code does not generate the same fingerprint as the openssl cli command does.
Any idea what I may be doing wrong?
As gtrig mentions, the OpenSSL command line builds the fingerprint by hashing the DER encoding of the certificate, not the Base64 PEM representation. You can parse this using pure OpenSSL:
file_data = File.read("cert.pem")
cert = OpenSSL::X509::Certificate.new(file_data)
puts OpenSSL::Digest::SHA1.new(cert.to_der).to_s
Shameless plug: r509 can also do this like so:
cert = R509::Cert.load_from_file("cert.pem")
puts cert.fingerprint('sha1')
If you need it to be in colon separated form you can just take the hash and do something like "fingerprint".scan(/../).map{ |s| s.upcase }.join(":")
Try Base64.decode64.
OpenSSL::Digest::SHA1.new(Base64.decode64(data))
Certificates in PEM format are Base 64 encoded versions of a binary DER format, so they need to be DEcoded before the SHA1 hash is taken.
Alternatively, you could convert the PEM file to DER format with OpenSSL like this:
openssl x509 -in cert.pem -out cert.der -outform der
Then your Ruby code would look like this:
data2 = File.read("cert.der")
print OpenSSL::Digest::SHA1.new(data2)
Either way works.

Resources