1

For example, given the below RSA private key in PKCS#1/PEM format generated using OpenSSL::PKey::RSA.new(2048):

-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEArL7/qAft6XBmEP9JkadhsPYydS7V+wsOLQPpJbtRmvs7rDUG
5hagEjhMKolSksAL8Gh4ZR84iFnATv81xLzoKBbWtHfMmgOohrXJy3Xw1kRrJemh
ZLmoJDbFVyDiCXXIDpfLDxm/9jBFn+hUuESFXMIBpbjhFJ0t12HFqXwFmKVfkNbq
JhwKuq3AEylN8dWn3oQNz4rq2ZCZiqjNBo0X4hny0GlBGvPHADS9Fe8DX/yN8Ggj
IM7MvQeVi3uiZ0u1qhiK7wcaPoTEjXJH4NhbmzZjGRQ/2VznbeXCYdzWzfAHDWjS
ADT6895geYYHTAJi1v7qtBRP2sihpdBhIpihgwIDAQABAoIBADOWxtrzo0V338Nr
uhjZl/81R1RfrF/QqWcgJ9yw2GokZWnEXE8SqrNGRNjfMd3JpMcjK/FnJYby5s+w
v+oFUH/Ick5rCJtmREoWuDEfA9G5lRY5c42VNHW8NasTku2oUxqokmfsFLv9Jo3e
4I43SGyvM7a+Q9nYJvyPomw/MZyoKKUJr7Poa1lYAqFigIWCbU2C0c9sHhsVNQJZ
+t69y9DiNTX7VDRhj8UQ07H0qs8nG06bFjt411Z/jdsKvh59ucLGARHYS0t4OGcr
CkIRUYI1xPF2UPCnCB7EJoeUbJPxtGt9Qb1yrV8U6K2WtezO/Suld7u2u/lX/aey
urkUwAECgYEA47oeArcPVttOJjFRL+YX6g7ixfRblh5SaPxVB19gqN404KrWqPWD
JpdageERr/TprtSXw75B5YZzdE1HjS811RN0gwS7d47uYu41XB/glH0E1u23w5CN
ldVoUKRG5JrK/ebXzUaXTPSelPjDXuucGoNN5X2K7vWBf31qzwKGGAECgYEAwjFp
/w+4vURb1Zzsp2/lDI2Md2Kq49YKIWOYZkPPUtUK0Xoqm0oKZF1Vl04T8ANnSIKk
n1aiNnxwmaYaOMfB2UHVbDbE2F5yLYUIelzVaMqzanxPN5oq0NBCW8UUxE+GPan4
syz5rEzBz/hENR9oFnvxbxewJsR5UjD43wmiWYMCgYEAu/xj0bH0A6s9s+F6N6Ql
kZ2ALhEtmZqmROwn9NITJNNpqxzb3tXs0eqXWCfHRg1S6nOsZHWmSCbZH+S7cBzM
v3wz7gP2DRf8ScaCXe4iofEiEZpi3Bl0B4AHgKpbq1LsxvPMqTPgqjI0xp0kCjNM
xcYmg49DJUedAvUxOnnG4AECgYEAiPXs+jWOZ/6kfn5U8qqac0YKAdGXEWXOc0oZ
HFdLC/Kx1JhDII8R0UN6sGIi8a6U07FAhhjGA4O0rslVySIp+B7UdaQTJT9HbA9d
sV90LJp5++p8vIyBEhEwHCVdxi8IUMlmXIil9v2T3CgPgyAJe4Ii/+VHGbCMmIlt
nXDgDh0CgYEAlmko3ujnfoVwV3f92JgetIZx5IMe5rylJ5FjxyQ3dD3UEaEQgxoz
81j23ZSFVe4Mg8PzyxFgLgEZN7TVj/sjELqpRlRhZUu91io9FjGuU6XZNgfjRAhH
RbgFj9mnr8TV9kETuxXpoGaMD/7MVvetg8Qr1nxpi7m29Ao5L5R5h7g=
-----END RSA PRIVATE KEY-----

I can generate it's SHA256 fingerprint like so using openssl:

$ openssl rsa -in rsa_private_test.pem -pubout -outform DER | openssl sha256 -binary | openssl base64
writing RSA key
8T0BsSCXlbxqFGekWsIuGhj6/ca/6VpLjDqzT4X3TBQ=

How can I do the same in Ruby? My assumption is that both approaches i.e. via OpenSSL in Ruby and the openssl should yield the same result.

King'ori Maina
  • 4,440
  • 3
  • 26
  • 38
  • sha256 of the payload is my guess. You might find this interesting https://stackoverflow.com/questions/22030264/how-can-i-create-a-sha256-fingerprint-in-openssl – Allan Wind Feb 27 '21 at 09:11
  • 1
    In the first part, the OpenSSL statement exports the public key (X.509/SPKI format, DER encoded) from the posted private key (PKCS#1 format, PEM encoded). From this (i.e. from the public, not the private key) the SHA256 hash is generated in the second step, which is finally Base64 encoded in the third step. – Topaco Feb 27 '21 at 09:50
  • @Topaco Thanks. That actually helped me realise part of the problem. Posted the final solution that worked for me. – King'ori Maina Feb 27 '21 at 10:12

3 Answers3

3

sorry I don't have the permission to directly comment on your answer.

I faced the same problem, and I also tried your answer but couldn't get the expected answer. May I know how did you get the rsa_public? Thank you.

Here is my ruby code:

pkey = OpenSSL::PKey::RSA.new(File.read('rsa_private_test.pem'))

sha256 = OpenSSL::Digest::SHA256.new

digest = sha256.digest(pkey.public_key.to_der)

puts Base64.encode64(digest) 
user633912
  • 41
  • 1
  • 5
2

So, from this other post and @Topaco's comment here I figured out what I was doing wrong.

Part of the problem is that .hexdigest always returns text and the output in the second part of the openssl returns output that needs to be in binary form. And you should get the DER of the public key since the first part of the openssl command returns the public key.

You can see it's working now ...

pry(main)> sha256 = OpenSSL::Digest::SHA256.new
=> #<OpenSSL::Digest::SHA256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855>
pry(main)> digest = sha256.digest(rsa_public.to_der)
=> "\xF1=\x01\xB1 \x97\x95\xBCj\x14g\xA4Z\xC2.\x1A\x18\xFA\xFD\xC6\xBF\xE9ZK\x8C:\xB3O\x85\xF7L\x14"
pry(main)> Base64.encode64(digest) 
=> "8T0BsSCXlbxqFGekWsIuGhj6/ca/6VpLjDqzT4X3TBQ=\n"

As opposed to what I was getting before ...

pry(main)> digest = OpenSSL::Digest::SHA256.hexdigest(rsa_public.to_der).to_s
=> "f13d01b1209795bc6a1467a45ac22e1a18fafdc6bfe95a4b8c3ab34f85f74c14"
pry(main)> Base64.encode64(digest)
=> "ZjEzZDAxYjEyMDk3OTViYzZhMTQ2N2E0NWFjMjJlMWExOGZhZmRjNmJmZTk1\nYTRiOGMzYWIzNGY4NWY3NGMxNA==\n"
King'ori Maina
  • 4,440
  • 3
  • 26
  • 38
1

You could achieve it by OpenSSL::Digest:

require 'openssl'

pem = OpenSSL::PKey::RSA.new(2048)

fingerprint = OpenSSL::Digest::SHA256.new(pem.to_der).to_s
# => "9a7c94fd90bf88d0b52aa48739b552bc6afc39e4a7d6949aa0ad1c110852906d"
eux
  • 3,072
  • 5
  • 14
  • Tried that actually, when I load the private key I shared into `OpenSSL::PKey::RSA.new` I don't get the same value I got when using `openssl` which is what I expect. – King'ori Maina Feb 27 '21 at 09:31