Created
May 19, 2011 22:33
-
-
Save Zapotek/981959 to your computer and use it in GitHub Desktop.
RSA_AES_CBC
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'openssl' | |
require "yaml" | |
require "base64" | |
# | |
# Simple hybrid crypto class using RSA for public key encryption and AES with CBC | |
# for bulk data encryption/decryption. | |
# | |
# RSA is used to encrypt the AES primitives which are used to encrypt the plaintext. | |
# | |
# @author: Tasos "Zapotek" Laskos | |
# <[email protected]> | |
# <[email protected]> | |
# @version: 0.1 | |
class RSA_AES_CBC | |
# | |
# If only encryption is required the private key parameter can be omitted. | |
# | |
# @param [String] public_pem location of the Public key in PEM format | |
# @param [String] private_pem location of the Private key in PEM format | |
# | |
def initialize( public_pem, private_pem = nil ) | |
@public_pem = public_pem | |
@private_pem = private_pem | |
end | |
# | |
# Encrypts data and returns a Base64 representation of the ciphertext | |
# and AES CBC primitives encrypted using the public key. | |
# | |
# @param [String] data | |
# | |
# @return [String] Base64 representation of the ciphertext | |
# and AES CBC primitives encrypted using the public key. | |
# | |
def encrypt( data ) | |
rsa = OpenSSL::PKey::RSA.new( File.read( @public_pem ) ) | |
# encrypt with 256 bit AES with CBC | |
aes = OpenSSL::Cipher::Cipher.new( 'aes-256-cbc' ) | |
aes.encrypt | |
# use random key and IV | |
aes.key = key = aes.random_key | |
aes.iv = iv = aes.random_iv | |
# this will hold all primitives and ciphertext | |
primitives = {} | |
primitives['ciphertext'] = aes.update( data ) | |
primitives['ciphertext'] << aes.final | |
primitives['key'] = rsa.public_encrypt( key ) | |
primitives['iv'] = rsa.public_encrypt( iv ) | |
# serialize everything and base64 encode it | |
Base64.encode64( primitives.to_yaml ) | |
end | |
# | |
# Decrypts data. | |
# | |
# @param [String] data | |
# | |
# @return [String] plaintext | |
# | |
def decrypt( data ) | |
rsa = OpenSSL::PKey::RSA.new( File.read( @private_pem ) ) | |
# decrypt with 256 bit AES with CBC | |
aes = OpenSSL::Cipher::Cipher.new( 'aes-256-cbc' ) | |
aes.decrypt | |
# unencode and unserialize to get the primitives and ciphertext | |
primitives = YAML::load( Base64.decode64( data ) ) | |
aes.key = rsa.private_decrypt( primitives['key'] ) | |
aes.iv = rsa.private_decrypt( primitives['iv'] ) | |
plaintext = aes.update( primitives['ciphertext'] ) | |
plaintext << aes.final | |
return plaintext | |
end | |
end | |
# crypto = RSA_AES_CBC.new( 'public.pem', 'private.pem' ) | |
# ciphered = crypto.encrypt( 'Foo' ) | |
# puts crypto.decrypt( ciphered ) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment