Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Ruby OpenSSL to download and read certificates

Tags:

ruby

ssl

openssl

I'm trying to work out how to download a certificate from a web address/uri using OpenSSL in the stdlib and then make use of it in an alerting application.

At the moment, I'm essentially calling the openssl executable using s_client and parsing the response to get the certificate but it just feels silly/clunky to be doing so when I've got a whole lib to handle this (and that I know for sure already DOES this).

I've spent a bit of time trying to wrap my head around the openssl source in Ruby but I feel fairly defeated by it; also the internet appears to be flooded with many rubyists trying to bypass their SSL (wince) rather than helpful information on OpenSSL itself so I'm not having much luck there either.

Would someone be able to point me in the right direction at all? Perhaps via the documentation or something similar to be able handle this particular task? If you have an example that would be even better but I'd much prefer to try and get my head around it myself.

Thanks in advance.

like image 713
Jamie Pirie Avatar asked Jan 04 '16 22:01

Jamie Pirie


2 Answers

It's pretty simple actually. To get remote certificate, you need to try to establish an SSL connection, then just read the peer certificate from there,

# Get OpenSSL context
ctx = OpenSSL::SSL::SSLContext.new

# Get remote TCP socket
sock = TCPSocket.new(remote_host, 443)

# pass that socket to OpenSSL
ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx)

# establish connection, if possible
ssl.connect

# get peer certificate and do things with it
cert = ssl.peer_cert
cert.version
cert.subject.to_s

Now, this simple method doesn't work with SNI, but it will get you started.

like image 50
user3427419 Avatar answered Oct 18 '22 05:10

user3427419


I'll assume "from a web address" means HTTPS. You could then just use net/http.

require 'net/http'
cert = Net::HTTP.start(host, '443', use_ssl: true) { |http| http.peer_cert }

This would also work behind a proxy server, if http_proxy env var is set.

  • https://ruby-doc.org/stdlib/libdoc/net/http/rdoc/Net/HTTP.html
  • https://ruby-doc.org/stdlib/libdoc/openssl/rdoc/OpenSSL/X509/Certificate.html
like image 3
xoryves Avatar answered Oct 18 '22 07:10

xoryves