Skip to content

Instantly share code, notes, and snippets.

@ronny
Last active August 29, 2015 14:05
Show Gist options
  • Save ronny/147dfaf878c8d0e58c26 to your computer and use it in GitHub Desktop.
Save ronny/147dfaf878c8d0e58c26 to your computer and use it in GitHub Desktop.
AES symmetric-key encryption/decryption in Ruby with the built-in OpenSSL lib
require 'openssl'
require 'digest/sha2'
module AESCrypt
CIPHER_TYPE = "AES-256-CBC".freeze
class << self
def decrypt(armored_iv_and_ciphertext, key)
ciphertext = [armored_iv_and_ciphertext].pack("H*")
aes = OpenSSL::Cipher::Cipher.new(CIPHER_TYPE)
aes.decrypt
aes.key = Digest::SHA512.hexdigest(key)
aes.iv = ciphertext.slice!(0, 16)
aes.update(ciphertext) + aes.final
end
def encrypt(data, key)
aes = OpenSSL::Cipher::Cipher.new(CIPHER_TYPE)
aes.encrypt
aes.iv = iv = aes.random_iv
aes.key = Digest::SHA512.hexdigest(key)
iv_and_ciphertext = iv + aes.update(data) + aes.final
armored_iv_and_ciphertext = iv_and_ciphertext.unpack("H*")[0]
end
end
end
RSpec.describe AESCrypt do
describe 'encrypt' do
let(:key) { "woohoosecret" }
let(:plaintext) { "its private" }
it 'returns a non-nil string other than plaintext or the key' do
result = AESCrypt.encrypt(plaintext, key)
expect(result).not_to be_nil
expect(result).to be_a String
expect(result).not_to match plaintext
expect(result).not_to match key
end
end
describe 'decrypt' do
let(:key) { "woohoosecret" }
let(:plaintext) { "its private" }
it 'works' do
result = AESCrypt.decrypt(AESCrypt.encrypt(plaintext, key), key)
expect(result).to eq plaintext
end
end
end
@fullofcaffeine
Copy link

Interesting! Could you elaborate on the additional armored_iv_and_ciphertext? I'm wondering if iv_and_ciphertext would be enough for my purposes. Why did you add this step? How much more security does it add in terms of hacking effort? And lastly, why didn't you use a PKCS5 (OpenSSL::PKCS5.pbkdf2_hmac_sha1) to generate the key?

@ronny
Copy link
Author

ronny commented Jun 9, 2015

@fullofcaffeine The armored_iv_and_ciphertext is not about security, it's making the encryption output more easily transportable (e.g. over the wire, serialised to a file, database,etc.), it'd simply be an ASCII string of hex characters, no binary bytes to worry about.

I'm by no means an expert in cryptography, so I'm not going to pretend to be one :) It does sound like using OpenSSL::PKCS5.pbkdf2_hmac_sha1 instead of Digest::SHA512.hexdigest may be better, but I'm not sure.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment