lib/symmetric_encryption/symmetric_encryption.rb in symmetric-encryption-1.1.1 vs lib/symmetric_encryption/symmetric_encryption.rb in symmetric-encryption-2.0.0

- old
+ new

@@ -83,15 +83,44 @@ # 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 - def self.encrypt(str) + # + # Parameters + # str [String] + # String to be encrypted. If str is not a string, #to_s will be called on it + # to convert it to a string + # + # random_iv [true|false] + # Whether the encypted value should use a random IV every time the + # field is encrypted. + # It is recommended to set this to true where feasible. If the encrypted + # value could be used as part of a SQL where clause, or as part + # of any lookup, then it must be false. + # Setting random_iv to true will result in a different encrypted output for + # the same input string. + # Note: Only set to true if the field will never be used as part of + # the where clause in an SQL query. + # Note: When random_iv is true it will add a 8 byte header, plus the bytes + # to store the random IV in every returned encrypted string, prior to the + # encoding if any. + # Default: false + # Highly Recommended where feasible: true + # + # compress [true|false] + # Whether to compress str before encryption + # Should only be used for large strings since compression overhead and + # the overhead of adding the 'magic' header may exceed any benefits of + # compression + # Note: Adds a 6 byte header prior to encoding, only if :random_iv is false + # Default: false + def self.encrypt(str, random_iv=false, compress=false) raise "Call SymmetricEncryption.load! or SymmetricEncryption.cipher= prior to encrypting or decrypting data" unless @@cipher # Encrypt and then encode the supplied string - @@cipher.encrypt(str) + @@cipher.encrypt(str, random_iv, compress) end # Invokes decrypt # Returns decrypted String # Return nil if it fails to decrypt a String @@ -157,17 +186,17 @@ def self.generate_symmetric_key_files(filename=nil, environment=nil) config = read_config(filename, environment) cipher_cfg = config[:ciphers].first key_filename = cipher_cfg[:key_filename] iv_filename = cipher_cfg[:iv_filename] - cipher = cipher_cfg[:cipher] + cipher_name = cipher_cfg[:cipher_name] || cipher_cfg[:cipher] raise "The configuration file must contain a 'private_rsa_key' parameter to generate symmetric keys" unless config[:private_rsa_key] rsa_key = OpenSSL::PKey::RSA.new(config[:private_rsa_key]) # Generate a new Symmetric Key pair - key_pair = SymmetricEncryption::Cipher.random_key_pair(cipher || 'aes-256-cbc', !iv_filename.nil?) + key_pair = SymmetricEncryption::Cipher.random_key_pair(cipher_name || 'aes-256-cbc', !iv_filename.nil?) # Save symmetric key after encrypting it with the private RSA key, backing up existing files if present File.rename(key_filename, "#{key_filename}.#{Time.now.to_i}") if File.exist?(key_filename) File.open(key_filename, 'wb') {|file| file.write( rsa_key.public_encrypt(key_pair[:key]) ) } @@ -205,29 +234,29 @@ # Which environments config to load. Usually: production, development, etc. def self.read_config(filename=nil, environment=nil) config = YAML.load_file(filename || File.join(Rails.root, "config", "symmetric-encryption.yml"))[environment || Rails.env] # Default cipher - default_cipher = config['cipher'] || 'aes-256-cbc' + default_cipher = config['cipher_name'] || config['cipher'] || 'aes-256-cbc' cfg = {} # Hard coded symmetric_key? - Dev / Testing use only! if symmetric_key = (config['key'] || config['symmetric_key']) raise "SymmetricEncryption Cannot hard code Production encryption keys in #{filename}" if (environment || Rails.env) == 'production' - cfg[:key] = symmetric_key - cfg[:iv] = config['iv'] || config['symmetric_iv'] - cfg[:cipher] = default_cipher + cfg[:key] = symmetric_key + cfg[:iv] = config['iv'] || config['symmetric_iv'] + cfg[:cipher_name] = default_cipher elsif ciphers = config['ciphers'] raise "Missing mandatory config parameter 'private_rsa_key'" unless cfg[:private_rsa_key] = config['private_rsa_key'] cfg[:ciphers] = ciphers.collect do |cipher_cfg| key_filename = cipher_cfg['key_filename'] || cipher_cfg['symmetric_key_filename'] raise "Missing mandatory 'key_filename' for environment:#{environment} in #{filename}" unless key_filename iv_filename = cipher_cfg['iv_filename'] || cipher_cfg['symmetric_iv_filename'] { - :cipher => cipher_cfg['cipher'] || default_cipher, + :cipher_name => cipher_cfg['cipher_name'] || cipher_cfg['cipher'] || default_cipher, :key_filename => key_filename, :iv_filename => iv_filename, :encoding => cipher_cfg['encoding'], :version => cipher_cfg['version'] } @@ -235,11 +264,11 @@ else # Migrate old format config raise "Missing mandatory config parameter 'private_rsa_key'" unless cfg[:private_rsa_key] = config['private_rsa_key'] cfg[:ciphers] = [ { - :cipher => default_cipher, + :cipher_name => default_cipher, :key_filename => config['symmetric_key_filename'], :iv_filename => config['symmetric_iv_filename'], } ] end @@ -250,20 +279,21 @@ # stored in files # # Raises an Exception on failure # # Parameters: - # cipher - # Encryption cipher for the symmetric encryption key - # private_key + # private_rsa_key # Key used to unlock file containing the actual symmetric key - # key_filename - # Name of file containing symmetric key encrypted using the public - # key matching the supplied private_key - # iv_filename - # Optional. Name of file containing symmetric key initialization vector - # encrypted using the public key matching the supplied private_key + # cipher_conf Hash: + # cipher_name + # Encryption cipher name for the symmetric encryption key + # key_filename + # Name of file containing symmetric key encrypted using the public + # key matching the supplied private_key + # iv_filename + # Optional. Name of file containing symmetric key initialization vector + # encrypted using the public key matching the supplied private_key def self.cipher_from_encrypted_files(private_rsa_key, cipher_conf) # Load Encrypted Symmetric keys key_filename = cipher_conf[:key_filename] encrypted_key = begin File.read(key_filename) @@ -284,14 +314,14 @@ # Decrypt Symmetric Keys rsa = OpenSSL::PKey::RSA.new(private_rsa_key) iv = rsa.private_decrypt(encrypted_iv) if iv_filename Cipher.new( - :key => rsa.private_decrypt(encrypted_key), - :iv => iv, - :cipher => cipher_conf[:cipher], - :encoding => cipher_conf[:encoding], - :version => cipher_conf[:version] + :key => rsa.private_decrypt(encrypted_key), + :iv => iv, + :cipher_name => cipher_conf[:cipher_name], + :encoding => cipher_conf[:encoding], + :version => cipher_conf[:version] ) end # With Ruby 1.9 strings have encodings if defined?(Encoding) \ No newline at end of file