TvE 2100

At 2100 feet above Santa Barbara

Verifying SSL Certs When Using Net:HTTP

What good is an HTTPS web service if you’re not verifying the certificate presented by the web service? That’s what I was wondering when I started to use the Amazon Elastic Compute Cloud web service and used a sample that used simple HTTP. So I looked into the docs and quickly found that the trick is to set http.verify_mode = OpenSSL::SSL::VERIFY_PEER when creating the https connection object. Unfortunately that turned out not to be so simple, because the only effect I got is an error on every connection attempt telling me that the peer’s certificate cannot be validated. Very useful!

Black-necked Stilts
Black-necked Stilts, Devereux Slough, Santa Barbara, CA ©2005 Thorsten von Eicken

Of course my next step was a Google search, but after a long time all I found is that everyone turns the verification off! I then proceeded to look at the source code to figure out what is going on, and I finally gave up after a couple of hours. Finally, the Pragmatic Studio alumni mailing list came to the rescue: Devin Mullins gave me the critical tip that made it work: one has to give the certificate file a special name, duuuh. Here is in detail what I did to get it to work:

I have a file ‘cacert.pem’ that has all the root certs I care about. I ran the following command:

# openssl x509 -hash < cacert.pem

The trick is that the file basename must be the hash printed out by the above command plus an appended .0! So my next move was:

# mv cacert.pem f73e89fd.0

I then adjusted my code as follows:

  http =, link.port)
  if link.scheme == 'https'
    http.use_ssl = true
    http.verify_mode = OpenSSL::SSL::VERIFY_PEER
    http.ca_file = "#{RAILS_ROOT}/lib/ec2/f73e89fd.0"
  response = http.get(link.request_uri)

This now works like a charm! Phew!


Upon further inspection, it looks like the above only works for the first certificate in my original cacert.pem file and I was lucky that that’s the one I need for EC2. What I need to do to use all the certs in the file is break it up, one cert per file, use openssl to figure out the filenames, and then use http.ca_path instead of http.ca_file to point to the directory with all the cert files.