Question

I want to access Twitter and upon using Net::HTTP's POST function I get this error.

SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed

Yes I know everyone gets this message.

Here are viable solutions I found.

First, manually set the cert file:

#! /usr/bin/env ruby
require 'net/https'
require 'uri'
 
uri = URI.parse(ARGV[0] || 'https://localhost/')
http = Net::HTTP.new(uri.host, uri.port)
if uri.scheme == "https"
  http.use_ssl = true
  http.verify_mode = OpenSSL::SSL::VERIFY_PEER
  http.ca_file = File.join(File.dirname(__FILE__), "cacert.pem")
end
http.start {
  http.request_get(uri.path) {|res|
    print res.body
  }
}

This was provided by Ariejan de Vroom: https://www.kabisa.nl/tech/ruby-and-ssl-certificate-validation/

Many people have given a similar answer to this. This did not work for me.

Then I found something that brought me along the right path. This guy Mislav Marohnić https://mislav.net/2013/07/ruby-openssl/ nailed the area of concern. It has to do with OpenSSL::X509::DEFAULT_CERT_FILE and OpenSSL::X509::DEFAULT_CERT_DIR. Which turns out are hard coded into my Ruby 1.9.3 through it's source code. Mislav gives his workaround like so:

require 'https'

http = Net::HTTP.new('example.com', 443)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_PEER

http.cert_store = OpenSSL::X509::Store.new
http.cert_store.set_default_paths
http.cert_store.add_file('/path/to/cacert.pem')
# ...or:
cert = OpenSSL::X509::Certificate.new(File.read('mycert.pem'))
http.cert_store.add_cert(cert)

I dabbled around with this and I would always get this error:

OpenSSL::X509::StoreError: cert already in hash table

Bah humbug and all that stuff!

I should also mention he has written a script that should help debug what's going on. It may help you, but not in my case. The link is on his page.

I also set

ENV['SSL_CERT_FILE']
ENV['SSL_CERT_DIR']

in my ruby code without success.

Then I proceeded to set the environment variables in windows by Start -> Control Panel -> System -> Advanced System Settings -> Advanced(tab) -> Environment Variables -> System variables New and added the SSL_CERT_DIR and SSL_CERT_FILE. This didn't work either.

And the certified gem didn't work for me... https://github.com/stevegraham/certified

So I will now provide you with my hack answer for all you Windows 7 users out there below.

Was it helpful?

Solution

So I dug around and basically stared at the hard coded path of the certs. By typing this at the command line

ruby -ropenssl -e 'puts OpenSSL::X509::DEFAULT_CERT_FILE'

I got the following...

c:/Users/Luis/Code/openknapsack/knap-build/var/knapsack/software/x86-windows/openssl/1.0.0k/ssl/cert.pem

So my solution was to first download cacert.pem from http://curl.haxx.se/ca/cacert.pem to c:\ . Then open up Windows Control Panel -> Administrative Tools -> Windows PowerShell Modules. Then I proceeded to type out:

cd \
cd users
mkdir Luis
cd Luis
mkdir Code
cd Code
mkdir openknapsack
cd openknapsack
mkdir knap-build
cd knap-build
mkdir var
cd var
mkdir knapsack
cd knapsack
mkdir software
cd software
mkdir x86-windows
cd x86-windows
mkir openssl
cd openssl
mkdir 1.0.0k
cd 1.0.0k
mkdir ssl
cd ssl
cp c:\cacert.pem .\cert.pem

And now everything works! Yes it's a cheap hack and it's ugly. But now both you and I can get back to doing serious coding and not worry about pesky problems.

I know it's not a great fix, but it's the only thing that worked for me, and it should for you too.

If some one would like to write a PowerShell script to auto install the cert file into this directory then you could more easily deploy your Ruby project to Windows 7. Just a thought.

By the way, you can duplicate this process for any operating system should the need arise. Just find the path the cert file belongs in with:

ruby -ropenssl -e 'puts OpenSSL::X509::DEFAULT_CERT_FILE'

And be sure to rename the file as it appears in the ouput!

OTHER TIPS

If you are facing this problem then download http://curl.haxx.se/ca/cacert.pem and export to your bash_profile

export SSL_CERT_FILE=PATH_TO_THe_DOWNLOADED_FILE/cacert.pem

This works for me :-)

If you already have downloaded Git for Windows, it has a CA-bundle which you can use.

Set SSL_CERT_DIR to the location where Git was installed, which will be C:\Program Files\Git\mingw32\ssl\certs (if on a 32-bit system) or C:\Program Files\Git\mingw64\ssl\certs (if on a 64-bit system). Also, you will need to set SSL_CERT_FILE to C:\Program Files\Git\mingw32\ssl\cert.pem (if on a 32-bit system) or C:\Program Files\Git\mingw64\ssl\cert.pem (if on a 64-bit system).

just found this made by @photonstorm. Worked for me:

1 - Download R1 GlobalSign Root Certificate: https://secure.globalsign.net/cacert/Root-R1.crt

2- Save it somewhere local, so you can easily access it from a command prompt. It should save with the name Root-R1.crt.

3- Convert to a PEM file. Here is where the post above didn't work for me, but this did: openssl x509 -in Root-R1.crt -out mycert.pem -outform PEM -inform DEF

4- Copy the new mycert.pem file that it creates into: D:\Ruby23-x64\lib\ruby\2.3.0\rubygems\ssl_certs <-- this path will obviously be different depending on where you've got Ruby installed!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top