What is OpenSSL and how is it related to Ruby
October 21, 2018
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
- A C library that implements the TLS protocol, the SSL protocol and a number of functions related to cryptography
- 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.h
, ssl.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.