Created
November 20, 2014 21:28
-
-
Save jkgraham/b8bf5621979a95ae4c9a to your computer and use it in GitHub Desktop.
This file contains 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
# 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]> | |
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 | |
plaintext | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment