Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

118 lines (103 sloc) 3.774 kB
module SymmetricEncryption
# Hold all information related to encryption keys
# as well as encrypt and decrypt data using those keys
#
# Cipher is thread safe so that the same instance can be called by multiple
# threads at the same time without needing an instance of Cipher per thread
class Cipher
# Cipher to use for encryption and decryption
attr_reader :cipher, :version, :version
attr_accessor :encoding
# Available encodings
ENCODINGS = [:none, :base64, :base64strict]
# Generate a new Symmetric Key pair
#
# Returns a hash containing a new random symmetric_key pair
# consisting of a :key and :iv.
# The cipher is also included for compatibility with the Cipher initializer
def self.random_key_pair(cipher = 'aes-256-cbc', generate_iv = true)
openssl_cipher = OpenSSL::Cipher.new(cipher)
openssl_cipher.encrypt
{
:key => openssl_cipher.random_key,
:iv => generate_iv ? openssl_cipher.random_iv : nil,
:cipher => cipher
}
end
# Create a Symmetric::Key for encryption and decryption purposes
#
# Parameters:
# :key
# The Symmetric Key to use for encryption and decryption
# :iv
# Optional. The Initialization Vector to use with Symmetric Key
# :cipher
# Optional. Encryption Cipher to use
# Default: aes-256-cbc
def initialize(parms={})
raise "Missing mandatory parameter :key" unless @key = parms[:key]
@iv = parms[:iv]
@cipher = parms[:cipher] || 'aes-256-cbc'
@version = parms[:version]
@encoding = (parms[:encoding] || :base64).to_sym
raise("Invalid Encoding: #{@encoding}") unless ENCODINGS.include?(@encoding)
end
# AES Symmetric Encryption of supplied string
# Returns result as a Base64 encoded string
# Returns nil if the supplied str is nil
# Returns "" if it is a string and it is empty
#
# options:
# :encoding
# :base64 Return as a base64 encoded string
# :binary Return as raw binary data string. Note: String can contain embedded nulls
# Default: :base64
# :compress
# [true|false] Whether or not to compress the data _before_ encrypting
# Default: false
def encrypt(str)
return if str.nil?
buf = str.to_s
return str if buf.empty?
crypt(:encrypt, buf)
end
# AES Symmetric Decryption of supplied string
# Returns decrypted string
# Returns nil if the supplied str is nil
# Returns "" if it is a string and it is empty
def decrypt(str)
return if str.nil?
buf = str.to_s
return str if buf.empty?
crypt(:decrypt, buf)
end
# Return a new random key using the configured cipher
# Useful for generating new symmetric keys
def random_key
::OpenSSL::Cipher::Cipher.new(@cipher).random_key
end
# Returns the block size for the configured cipher
def block_size
::OpenSSL::Cipher::Cipher.new(@cipher).block_size
end
protected
# Only for use by Symmetric::EncryptedStream
def openssl_cipher(cipher_method)
openssl_cipher = ::OpenSSL::Cipher.new(self.cipher)
openssl_cipher.send(cipher_method)
openssl_cipher.key = @key
openssl_cipher.iv = @iv if @iv
openssl_cipher
end
# Creates a new OpenSSL::Cipher with every call so that this call
# is thread-safe
def crypt(cipher_method, string) #:nodoc:
openssl_cipher = ::OpenSSL::Cipher.new(self.cipher)
openssl_cipher.send(cipher_method)
openssl_cipher.key = @key
openssl_cipher.iv = @iv if @iv
result = openssl_cipher.update(string)
result << openssl_cipher.final
end
end
end
Jump to Line
Something went wrong with that request. Please try again.