Skip to content

Instantly share code, notes, and snippets.

@jkgraham
Created November 20, 2014 21:28
Show Gist options
  • Save jkgraham/b8bf5621979a95ae4c9a to your computer and use it in GitHub Desktop.
Save jkgraham/b8bf5621979a95ae4c9a to your computer and use it in GitHub Desktop.
# 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 <tasos.laskos@arachni-scanner.com>
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