← Blog

openssl-win-root: Use the Windows Certificate Store with Ruby

If you run Ruby on Windows, sooner or later you will see an HTTPS request fail with a certificate verification error, even though the same site opens fine in your browser. openssl-win-root is a small gem that helps with exactly that.

First, credit where it’s due: the gem was written by Stas Ukolov, and the original repository is github.com/ukoloff/openssl-win-root. Its first release was in 2015. My part is small, and I describe it further down.

The problem

Ruby’s OpenSSL does not look at the Windows certificate store. It needs its own CA certificates. RubyInstaller ships a cacert.pem file, but as the gem’s README points out, that file is not updated automatically. It is the bundle from the time your Ruby version was built, so newer root certificates can be missing.

Windows, on the other hand, keeps its own trusted root store up to date. That store also contains certificates your company installs, for example through Group Policy. Ruby simply doesn’t see them.

What the gem does

When you require it on Windows, openssl-win-root:

  1. reads the trusted root certificates from the Windows system store (through the crypt32 API, using Fiddle),
  2. writes them as PEM files into a pem folder inside the gem’s directory, named the way OpenSSL expects for a certificate directory,
  3. adds that folder to OpenSSL’s default certificate store and sets the SSL_CERT_DIR environment variable to it.

No network access is needed. On other operating systems the gem does nothing, so it is safe to have in a cross-platform project.

How to use it

Add it to your Gemfile, only for Windows:

gem 'openssl-win-root' if Gem.win_platform?

Then run bundle, or install it directly:

gem install openssl-win-root

Require it before you make HTTPS requests:

require 'openssl/win/root'
require 'net/http'

Net::HTTP.get(URI('https://www.ruby-lang.org/')).length

If your project uses Bundler.require, as Rails does, you don’t need the explicit require.

The exported certificates can also be used outside Ruby. Point SSL_CERT_DIR, or the -CApath option of the openssl command, at the folder returned by:

OpenSSL::Win::Root.path

Things to keep in mind

My role

When Ruby 3.2 came out, the gem stopped working: it called File.exists?, which Ruby 3.2 removed. That is the same issue I wrote about in my post on the file_exists gem. I opened a pull request with the one-word fix.

I am one of the two owners of the gem on RubyGems, and in January 2023 I published version 1.1.2 from my fork. That release changed very little:

Everything else, the actual idea and implementation, is Stas’s work.