Back to Home

What is OpenSSL and how is it related to Ruby

Because of security vulnerabilites like Heartbleed, Poodle and DROWN, I grew more familiar with OpenSSL in recent years. This post is a summary of my understanding of OpenSSL and its relation to Ruby.

What is OpenSSL?

OpenSSL is a project that implements the TLS protocol, the SSL protocol and a number of functions related to cryptography. The project provides

  1. A C library that implements the TLS protocol, the SSL protocol and a number of functions related to cryptography
  2. A command line tool for using the crypgraphy related functions from the command line

Here’s an example of the openssl command line tool in action. The command prints the SHA1 hash of the word hello

% echo -n "hello" > greeting
% openssl sha1 greeting
SHA1(greeting)= aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d

The same can be achieved with the openssl C library. The C program below uses the openssl C library to print the SHA1 hash of the word hello

// Borrowed from https://pragmaticjoe.blogspot.com/2015/02/how-to-generate-sha1-hash-in-c.html

#include <openssl/evp.h>
#include <stdio.h>

int main(int argn, char *argv[]) {
    const unsigned char text[] = "hello";
    EVP_MD_CTX *message_digest_context;
    const EVP_MD *message_digest;
    unsigned char message_digest_value[EVP_MAX_MD_SIZE];
    unsigned int message_digest_length;

    message_digest = EVP_sha1();
    message_digest_context = EVP_MD_CTX_create();
    EVP_DigestInit_ex(message_digest_context, message_digest, NULL);
    EVP_DigestUpdate(message_digest_context, text, sizeof(text) - 1);
    EVP_DigestFinal_ex(message_digest_context, message_digest_value, &message_digest_length);
    for (int i = 0; i < message_digest_length; i++) {
      printf("%02x", message_digest_value[i]);
    }
    printf("\n");
    EVP_cleanup();
}
% gcc compute_sha1.c -lssl -lcrypto
% ./a.out
aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d

Ruby’s OpenSSL class

Ruby has an OpenSSL class that is a wrapper around the openssl C library.  Its subclasses and methods wrap over functions in openssl library. Here’s a Ruby program that is the equivalent of the C program above. It uses the OpenSSL class to compute the SHA1 hash of the word hello.

require "openssl"
puts OpenSSL::Digest::SHA1.new("hello").to_s
% puts compute_sha1.rb
aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d

The constant OpenSSL::OPENSSL_VERSION specifies the the openssl library version that the OpenSSL class wraps

% ruby -e "require 'openssl'; puts OpenSSL::OPENSSL_VERSION"
"OpenSSL 1.0.1j 15 Oct 2014"

Configure Ruby to use a newer openssl library

When a new security vulnerability is discovered in the openssl library or in an ssl protocol, Ruby has to be upgraded to use latest openssl library to protect applications from the security vulnerability. Here’s how the upgrade can be done. Upgrade the  libssl and the libssl-dev packages

apt-get update
apt-get install libssl libssl-dev

The libssl package provides the openssl library as a shared library/object (libssl.so) And the libssl-dev package provides the C header files like evp.hssl.h etc. Programs like Ruby, curl etc. include these header files in their source code https://github.com/ruby/ruby/blob/879b42b043806a88c3f61e33ed4b9468b7b156e7/ext/openssl/ossl.h#L41 Recompile Ruby so the ruby binary links to updated ssl binary. If you’ve installed Ruby with RVM, run

MY_RUBY_VERSION=2.2.3
rvm reinstall --disable-binary $MY_RUBY_VERSION

If you’ve installed Ruby with rbenv, run

MY_RUBY_VERSION=2.2.3
rbenv uninstall $RUBY_VERSION
rbenv install $RUBY_VERSION

I hope this was a helpful summary of what OpenSSL is and its relation to Ruby. If you’re interested in understanding OpenSSL and its capabilities further, the openssl command line tool’s manual page is a great place to start.

Built with Hugo & Notion. Source code is available at GitHub.