Ruby SSL with Twitter failed on cert OpenSSL issue on Windows 7

openssl, ruby, ssl-certificate, windows, x509certificate

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!

Problem

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.

Original source