Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 210
Mukta Avatar asked Jan 14 '23 09:01

Mukta


2 Answers

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(":")

like image 71
Paul Kehrer Avatar answered Jan 18 '23 18:01

Paul Kehrer


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.

like image 28
gtrig Avatar answered Jan 18 '23 17:01

gtrig