Symmetric Encryption for Ruby Projects using OpenSSL

Any project that wants to meet PCI compliance has to ensure that the data is encrypted whilst in flight and at rest. Amongst many other requirements all passwords in configuration files have to be encrypted.

Symmetric Encryption helps achieve compliance by supporting encryption of data in a simple and consistent way for Ruby and Rails projects.

Symmetric Encryption uses OpenSSL to encrypt and decrypt data, and can therefore expose all the encryption algorithms supported by OpenSSL.

Examples

Encryption

SymmetricEncryption.encrypt "Sensitive data"

Decryption

SymmetricEncryption.decrypt "JqLJOi6dNjWI9kX9lSL1XQ=="

Features

Encryption of

Security

Validations

Files and Streams

Compression

Backgound Job Processing

The sister-project Rocket Job uses Symmetric Encryption to encrypt job data to keep it secure.

Command Line Interface

Symmetric Encryption v4 introduces an extensive command line interface to:

Encrypting Passwords in configuration files

Passwords can be encrypted in any YAML configuration file.

For example config/database.yml

---
production:
  adapter:  mysql
  host:     db1w
  database: myapp_production
  username: admin
  password: <%= SymmetricEncryption.try_decrypt "JqLJOi6dNjWI9kX9lSL1XQ==\n" %>

Notes

    config_file = Rails.root.join('config', 'redis.yml')
    raise "redis config not found. Create a config file at: config/redis.yml" unless config_file.file?

    cfg = YAML.load(ERB.new(File.new(config_file).read).result)[Rails.env]
    raise("Environment #{Rails.env} not defined in redis.yml") unless cfg

Large File Encryption

Example: Read and decrypt a line at a time from a file

SymmetricEncryption::Reader.open('encrypted_file') do |file|
  file.each_line do |line|
     puts line
  end
end

Example: Encrypt and write data to a file

SymmetricEncryption::Writer.open('encrypted_file') do |file|
  file.write "Hello World\n"
  file.write "Keep this secret"
end

Example: Compress, Encrypt and write data to a file

SymmetricEncryption::Writer.open('encrypted_compressed.zip', compress: true) do |file|
  file.write "Hello World\n"
  file.write "Compress this\n"
  file.write "Keep this safe and secure\n"
end

Ruby Platform Support

Installation

Add the following line to Gemfile

gem 'symmetric-encryption'

Install the Gem with bundler

bundle install

Using without extensions

By default symmetric-encryption extends ORMs (ActiveRecord) and loads a Railstie to integrate with Rails configuration. However you may want to disable this behavior and instead use classes provided by Symmetric Encryption and perform configuration by yourself. To do this you should disable automatic require of the gem in your Gemfile:

gem 'symmetric-encryption', require: false

And then you should manually require Symmetric Encryption library core module which just loads the library classes without any extensions at the place where you use it:

require 'symmetric_encryption/core'

Support

Security

Many solutions that encrypt data require the encryption keys to be stored in the applications source code or leave it up to the developer to secure the keys on the application servers. Symmetric Encryption takes care of securing the symmetric encryption keys.

The following steps are used to secure the symmetric encryption keys using Symmetric Encryption:

In order for anyone to decrypt the data being encrypted in the database, they would need access to ALL of the following:

A major feature of symmetric encryption is that it makes the encryption and decryption automatically available when the Rails application is started. This includes all rake tasks and the Rails console. In this way data can be encrypted or decrypted as part of any rake task.

From a security perspective it is important then to properly secure the system so that no hacker can switch to and run as the rails user and thereby gain access to the encryption and decryption capabilities

It is not necessary to encrypt the initialization vector (IV), and it can be placed directly in the configuration file. The encryption key must be kept secure and must never be placed in the configuration file or other Rails source file in production. The IV should be generated using the rails generator described below to ensure it is a truly random key from the entire key space. Using a human readable text string is not considered secure.

Limitations

By default symmetric encryption uses the same initialization vector (IV) and encryption key to encrypt data using the SymmetricEncryption.encrypt call. This technique is required in cases where the encrypted data is used as a key to lookup for example a Social Security Number, since for the same input data it must always return the same encrypted result. The drawback is that this technique is not considered secure when encypting large amounts of data.

For non-key fields, such as storing encrypted raw responses, use the random_iv: true option where possible so that a randomly generated IV is used and included in every encrypted string.

The Symmetric Encryption streaming interface SymmetricEncryption::Writer avoids this problem by automatically generating a randomized key and IV for every file or stream. The random IV and key are stored in the header of the output stream so that it is available when reading back the encrypted file/stream. The key is placed in the file header in encrypted form using the current global key.

The ActiveRecord attr_encrypted method supports the random_iv: true option. Similarly for Mongoid the random_iv: true option is available.

Note that encrypting the same input string with the same key and random_iv: true option will result in different encrypted output every time it is encrypted.

Recommendations

Disclaimer

Although this library has assisted in meeting PCI Compliance and has passed previous PCI audits, it in no way guarantees that PCI Compliance will be achieved by anyone using this library.

Next => Supported Frameworks