Strongly Encrypting Data

Problem

You want to encrypt some data: to keep it private, or to keep it safe when sent through an insecure medium like email.

Solution

There are at least two good symmetric-key cryptography libraries for Ruby: Pelle Braendgaards EzCrypto (available as the ezcrypto gem)and Richard Kernahans Crypt (a third-party download).

EzCrypto is a user-friendly Ruby wrapper around the OpenSSL library, which you may need to install separately. Heres how to encrypt and decrypt a string with EzCrypto:

require ubygems require ezcrypto plaintext = 24.9195N 17.821E ezcrypto_key = EzCrypto::Key.with_password My secret key, salt string ezcrypto_ciphertext = ezcrypto_key.encrypt(plaintext) # => "F262260273217 R351362-21-a336324Qc…" ezcrypto_key.decrypt(ezcrypto_ciphertext) # => "24.9195N 17.821E"

The Crypt library gives each encryption algorithm its own class, so you need to decide which you want to use. Ill use the AES/Rijndael algorithm: all the other algorithms have the same interface.[2]

[2] The Crypt::IDEA class works a little differently, but that algorithm is patented, so you shouldn use it anyway.

require crypt/rijndael aes_key = Crypt::Rijndael.new(My secret key) aes_cyphertext = aes_key.encrypt_string(plaintext) # => "e0320330]203 346…" aes_key.decrypt_string(aes_cyphertext) # => "24.9195N 17.821E"

Discussion

EzCrypto is available as a gem (ezcrypto), and its fast because the actual encryption and decryption happens in the C OpenSSL libraries. Crypt is a pure Ruby implementation, so its slower, but you don have to worry about OpenSSL being installed.

EzCrypto and Crypt both implement several symmetric key algorithms. With EzCrypto, you can also specify the algorithm to use when you create an EzCrypto key. With Crypt, you need to instantiate the appropriate algorithms class:

# EzCrypto example blowfish_key = EzCrypto::Key.with_password(My secret password, salt string, :algorithm=>lowfish) # Crypt example require crypt/blowfish blowfish_key = Crypt::Blowfish.new(My secret password)

The Crypt classes provide some convenience methods for encrypting and decrypting files and streams. The encrypt_file method takes two filenames: it reads from one file, encrypts the data, and writes ciphertext to the other. The encrypt_stream method is a little more general: it reads plaintext from one I0 object and writes ciphertext to the other.

All the algorithms supported by Crypt and EzCrypto are symmetric-key algorithms: you must use the same key to encrypt and decrypt the data. This is simple when you e only encrypting data so that you can decrypt it later, but its not so simple when you e sending encrypted data to someone else. You need to securely share the key with the other person ahead of time, or you need to use public-key algorithms like the ones provided by the Ruby PKCS implementation.

There was some controversy about whether this recipe should even be included in this Cookbook. A little knowledge is a dangerous thing, and a little is all we can impart in the space we have for a recipe. Simply using an encryption algorithm won automatically make your data secure. It won be secure if you use a lousy password (like, say, "My secret password", as in the examples above).

Further, your data won be secure if you store your keys on disk the wrong way. It won be secure if your computer doesn have a reliable enough source of random numbers. When you prompt the user for their password, the operating system might pick that moment to swap to disk the chunk of memory that contains the password, where an attacker could find it. Even experts frequently make mistakes when they e writing cryptography code.

That said, a strong encryption algorithm is better than a weak one, and trying to write your own algorithm is just about the worst mistake you can make. All we ask that you be careful. Instead of worrying about writing an algorithm to encrypt your data, get a book on security and focus your efforts on making sure you use the existing algorithms correctly.

See Also

Категории