lib/symmetric_encryption/cipher.rb in symmetric-encryption-3.9.1 vs lib/symmetric_encryption/cipher.rb in symmetric-encryption-4.0.0.beta3

- old
+ new

@@ -1,190 +1,52 @@ require 'openssl' module SymmetricEncryption # Hold all information related to encryption keys - # as well as encrypt and decrypt data using those 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 + # threads at the same time without needing an instance of Cipher per thread. class Cipher # Cipher to use for encryption and decryption attr_accessor :cipher_name, :version, :iv, :always_add_header - attr_reader :encoder, :encoding + attr_reader :encoding attr_writer :key - # Backward compatibility - alias_method :cipher, :cipher_name + # Returns [Cipher] from a cipher config instance. + def self.from_config(cipher_name: 'aes-256-cbc', + version: 0, + always_add_header: true, + encoding: :base64strict, + **config) - # Defines the Header Structure returned when parsing the header - HeaderStruct = Struct.new( - # [true|false] Whether the data is compressed, if supplied in the header - :compressed, - # [String] IV used to encrypt the data, if supplied in the header - :iv, - # [String] Key used to encrypt the data, if supplied in the header - :key, - # [String] Name of the cipher used, if supplied in the header - :cipher_name, - # [Integer] Version of the cipher used, if supplied in the header - :version, - # [SymmetricEncryption::Cipher] Cipher matching the header, or SymmetricEncryption.cipher(default_version) - :decryption_cipher - ) + Key.migrate_config!(config) + key = Key.from_config(cipher_name: cipher_name, **config) - # Generate a new Symmetric Key pair - # - # Returns a hash containing a new random symmetric_key pair - # consisting of a :key and :iv. - # The cipher_name is also included for compatibility with the Cipher initializer - # - # Notes: - # * The key _must_ be properly secured - # * The iv can be stored in the clear and it is not necessary to encrypt it - def self.random_key_pair(cipher_name = 'aes-256-cbc') - openssl_cipher = ::OpenSSL::Cipher.new(cipher_name) - openssl_cipher.encrypt - - { - key: openssl_cipher.random_key, - iv: openssl_cipher.random_iv, - cipher_name: cipher_name - } + Cipher.new( + key: key.key, + iv: key.iv, + cipher_name: cipher_name, + version: version, + always_add_header: always_add_header, + encoding: encoding + ) end - # Generate new randomized keys and generate key and iv files if supplied. - # Overwrites key files for the current environment. + # Returns [SymmetricEncryption::Cipher] for encryption and decryption purposes. # - # Parameters - # :key_filename - # Name of file that will contain the symmetric key encrypted using the public - # key from the private_rsa_key. - # Or, - # :encrypted_key - # Symmetric key encrypted using the public key from the private_rsa_key - # and then Base64 encoded - # - # Note: - # If :key_filename and :encrypted_key are not supplied then a new :key will be returned. - # :key is the Symmetric Key to use for encryption and decryption. - # - # - # :iv_filename - # Name of file containing symmetric key initialization vector - # encrypted using the public key from the private_rsa_key - # Deprecated: It is _not_ necessary to encrypt the initialization vector (IV) - # Or, - # :encrypted_iv - # Initialization vector encrypted using the public key from the private_rsa_key - # and then Base64 encoded - # Deprecated: It is _not_ necessary to encrypt the initialization vector (IV) - # - # Note: - # If :iv_filename and :encrypted_iv are not supplied then a new :iv will be returned. - # :key is the Initialization Vector to use with Symmetric Key. - # - # - # private_rsa_key [String] - # Key encryption key. - # To generate a new one: SymmetricEncryption::KeyEncryptionKey.generate - # Required if :key_filename, :encrypted_key, :iv_filename, or :encrypted_iv is supplied - # - # :cipher_name [String] - # Encryption Cipher to use. - # Default: aes-256-cbc - # - # :encoding [Symbol] - # :base64strict - # Return as a base64 encoded string that does not include additional newlines - # This is the recommended format since newlines in the values to - # SQL queries are cumbersome. Also the newline reformatting is unnecessary - # It is not the default for backward compatibility - # :base64 - # Return as a base64 encoded string - # :base16 - # Return as a Hex encoded string - # :none - # Return as raw binary data string. Note: String can contain embedded nulls - # Default: :base64strict - def self.generate_random_keys(params = {}) - params = params.dup - private_rsa_key = params.delete(:private_rsa_key) - cipher_name = params.delete(:cipher_name) || 'aes-256-cbc' - encoding = params.delete(:encoding) || :base64strict - unless private_rsa_key - [:key_filename, :encrypted_key, :iv_filename, :encrypted_iv].each do |key| - raise(SymmetricEncryption::ConfigError, "When :#{key} is supplied, :private_rsa_key is required.") if params.include?(key) - end - end - - key_encryption_key = KeyEncryptionKey.new(private_rsa_key) if private_rsa_key - cipher_conf = {cipher_name: cipher_name, encoding: encoding} - - key_pair = SymmetricEncryption::Cipher.random_key_pair(cipher_name) - key = key_pair[:key] - iv = key_pair[:iv] - - if file_name = params.delete(:key_filename) - cipher_conf[:key_filename] = file_name - encrypted_key = key_encryption_key.encrypt(key) - write_to_file(file_name, encrypted_key) - elsif params.delete(:encrypted_key) - encrypted_key = key_encryption_key.encrypt(key) - cipher_conf[:encrypted_key] = SymmetricEncryption::Encoder[encoding].encode(encrypted_key) - else - params.delete(:key) - cipher_conf[:key] = SymmetricEncryption::Encoder[encoding].encode(key.to_s) - end - - if file_name = params.delete(:iv_filename) - cipher_conf[:iv_filename] = file_name - encrypted_iv = key_encryption_key.encrypt(iv) - write_to_file(file_name, encrypted_iv) - elsif params.delete(:encrypted_iv) - encrypted_iv = key_encryption_key.encrypt(iv) - cipher_conf[:encrypted_iv] = SymmetricEncryption::Encoder[encoding].encode(encrypted_iv) - else - params.delete(:iv) - cipher_conf[:iv] = SymmetricEncryption::Encoder[encoding].encode(iv.to_s) - end - - raise(ArgumentError, "SymmetricEncryption::Cipher Invalid options #{params.inspect}") if params.size > 0 - cipher_conf - end - - # Create a Symmetric::Key for encryption and decryption purposes - # # Parameters: - # :key [String] - # The Symmetric Key to use for encryption and decryption - # Or, - # :key_filename - # Name of file containing symmetric key encrypted using the public - # key from the private_rsa_key - # Or, - # :encrypted_key - # Symmetric key encrypted using the public key from the private_rsa_key - # and then Base64 encoded + # key [String] + # The Symmetric Key to use for encryption and decryption. # - # :iv [String] - # Optional. The Initialization Vector to use with Symmetric Key - # Highly Recommended as it is the input into the CBC algorithm - # Or, - # :iv_filename - # Name of file containing symmetric key initialization vector - # encrypted using the public key from the private_rsa_key - # Deprecated: It is _not_ necessary to encrypt the initialization vector (IV) - # Or, - # :encrypted_iv - # Initialization vector encrypted using the public key from the private_rsa_key - # and then Base64 encoded - # Deprecated: It is _not_ necessary to encrypt the initialization vector (IV) + # iv [String] + # The Initialization Vector to use. # - # :cipher_name [String] + # cipher_name [String] # Optional. Encryption Cipher to use # Default: aes-256-cbc # - # :encoding [Symbol] + # encoding [Symbol] # :base64strict # Return as a base64 encoded string that does not include additional newlines # This is the recommended format since newlines in the values to # SQL queries are cumbersome. Also the newline reformatting is unnecessary # It is not the default for backward compatibility @@ -192,78 +54,52 @@ # Return as a base64 encoded string # :base16 # Return as a Hex encoded string # :none # Return as raw binary data string. Note: String can contain embedded nulls - # Default: :base64 - # Recommended: :base64strict + # Default: :base64strict # - # :version [Fixnum] + # version [Fixnum] # Optional. The version number of this encryption key # Used by SymmetricEncryption to select the correct key when decrypting data - # Maximum value: 255 + # Valid Range: 0..255 + # Default: 1 # - # :always_add_header [true|false] + # always_add_header [true|false] # Whether to always include the header when encrypting data. # ** Highly recommended to set this value to true ** # Increases the length of the encrypted data by a few bytes, but makes # migration to a new key trivial - # Default: false - # Recommended: true - # - # private_rsa_key [String] - # Key encryption key. - # To generate a new one: SymmetricEncryption::KeyEncryptionKey.generate - # Required if :key_filename, :encrypted_key, :iv_filename, or :encrypted_iv is supplied - def initialize(params={}) - params = params.dup - @cipher_name = params.delete(:cipher_name) || params.delete(:cipher) || 'aes-256-cbc' - @version = params.delete(:version) || 0 - @always_add_header = params.delete(:always_add_header) || false - self.encoding = (params.delete(:encoding) || :base64).to_sym - private_rsa_key = params.delete(:private_rsa_key) - unless private_rsa_key - [:key_filename, :encrypted_key, :iv_filename, :encrypted_iv].each do |key| - raise(SymmetricEncryption::ConfigError, "When :#{key} is supplied, :private_rsa_key is required.") if params.include?(key) - end - end + # Default: true + def initialize(key:, + iv: nil, + cipher_name: 'aes-256-cbc', + version: 0, + always_add_header: true, + encoding: :base64strict) - key_encryption_key = KeyEncryptionKey.new(private_rsa_key) if private_rsa_key - @key = - if key = params.delete(:key) - key - elsif file_name = params.delete(:key_filename) - encrypted_key = self.class.read_from_file(file_name) - key_encryption_key.decrypt(encrypted_key) - elsif encrypted_key = params.delete(:encrypted_key) - binary = self.encoder.decode(encrypted_key) - key_encryption_key.decrypt(binary) - else - raise(ArgumentError, 'Missing mandatory parameter :key, :key_filename, or :encrypted_key') - end + @key = key + @iv = iv + @cipher_name = cipher_name + self.encoding = encoding.to_sym + @version = version.to_i + @always_add_header = always_add_header - @iv = - if iv = params.delete(:iv) - iv - elsif file_name = params.delete(:iv_filename) - encrypted_iv = self.class.read_from_file(file_name) - key_encryption_key.decrypt(encrypted_iv) - elsif encrypted_iv = params.delete(:encrypted_iv) - binary = self.encoder.decode(encrypted_iv) - key_encryption_key.decrypt(binary) - end - - raise(ArgumentError, "Cipher version has a valid range of 0 to 255. #{@version} is too high, or negative") if (@version.to_i > 255) || (@version.to_i < 0) - raise(ArgumentError, "SymmetricEncryption::Cipher Invalid options #{params.inspect}") if params.size > 0 + raise(ArgumentError, "Cipher version has a valid range of 0 to 255. #{@version} is too high, or negative") if (@version > 255) || (@version < 0) end # Change the encoding def encoding=(encoding) - @encoder = SymmetricEncryption::Encoder[encoding] + @encoder = nil @encoding = encoding end + # Returns [SymmetricEncryption::Encoder] the encoder to use for the current encoding. + def encoder + @encoder ||= SymmetricEncryption::Encoder[encoding] + end + # Encrypt and then encode a string # # Returns data encrypted and then encoded according to the encoding setting # of this cipher # Returns nil if str is nil @@ -276,35 +112,32 @@ # 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. + # Notes: + # * Setting random_iv to true will result in a different encrypted output for + # the same input string. + # * It is recommended to set this to true, except if it will be used as a lookup key. + # * Only set to true if the field will never be used as a lookup key, since + # the encrypted value needs to be same every time in this case. + # * When random_iv is true it adds the random IV string to the header. # 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 encryption header may exceed any benefits of - # compression - # Note: Adds a 6 byte header prior to encoding, only if :random_iv is false + # Whether to compress str before encryption. # Default: false - def encrypt(str, random_iv=false, compress=false) + # Notes: + # * Should only be used for large strings since compression overhead and + # the overhead of adding the encryption header may exceed any benefits of + # compression + def encrypt(str, random_iv: false, compress: false, header: always_add_header) return if str.nil? str = str.to_s return str if str.empty? - encrypted = binary_encrypt(str, random_iv, compress) + encrypted = binary_encrypt(str, random_iv: random_iv, compress: compress, header: header) self.encode(encrypted) end # Decode and Decrypt string # Returns a decrypted string after decoding it first according to the @@ -327,16 +160,16 @@ decoded = self.decode(str) return unless decoded return decoded if decoded.empty? decrypted = binary_decrypt(decoded) - if defined?(Encoding) - # Try to force result to UTF-8 encoding, but if it is not valid, force it back to Binary - unless decrypted.force_encoding(SymmetricEncryption::UTF8_ENCODING).valid_encoding? - decrypted.force_encoding(SymmetricEncryption::BINARY_ENCODING) - end + + # Try to force result to UTF-8 encoding, but if it is not valid, force it back to Binary + unless decrypted.force_encoding(SymmetricEncryption::UTF8_ENCODING).valid_encoding? + decrypted.force_encoding(SymmetricEncryption::BINARY_ENCODING) end + decrypted end # Returns UTF8 encoded string after encoding the supplied Binary string # @@ -360,170 +193,81 @@ end # Return a new random key using the configured cipher_name # Useful for generating new symmetric keys def random_key - ::OpenSSL::Cipher::Cipher.new(@cipher_name).random_key + ::OpenSSL::Cipher.new(cipher_name).random_key end + # Return a new random IV using the configured cipher_name + # Useful for generating new symmetric keys + def random_iv + ::OpenSSL::Cipher.new(cipher_name).random_iv + end + # Returns the block size for the configured cipher_name def block_size - ::OpenSSL::Cipher::Cipher.new(@cipher_name).block_size + ::OpenSSL::Cipher.new(cipher_name).block_size end - # Returns whether the supplied buffer starts with a symmetric_encryption header - # Note: The encoding of the supplied buffer is forced to binary if not already binary - def self.has_header?(buffer) - return false if buffer.nil? || (buffer == '') - buffer.force_encoding(SymmetricEncryption::BINARY_ENCODING) if buffer.respond_to?(:force_encoding) - buffer.start_with?(MAGIC_HEADER) - end - - # Returns HeaderStruct of the header parsed from the supplied string - # Returns nil if no header is present + # Advanced use only # - # The supplied buffer will be updated directly and its header will be - # stripped if present + # Returns a Binary encrypted string without applying Base64, or any other encoding. # - # Parameters - # buffer - # String to extract the header from + # 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 # - def self.parse_header!(buffer) - return unless has_header?(buffer) - - # Header includes magic header and version byte - # - # The encryption header consists of: - # 4 Byte Magic Header Prefix: @Enc - # Followed by 2 Bytes (16 bits) - # Bit 0 through 7: The version of the cipher used to encrypt the header - # Bit 8 though 10: Reserved - # Bit 11: Whether the encrypted data is Binary (otherwise UTF8 text) - # Bit 12: Whether the Cipher Name is included - # Bit 13: Whether the Key is included - # Bit 14: Whether the IV is included - # Bit 15: Whether the data is compressed - # 2 Byte IV Length if included - # IV in binary form - # 2 Byte Key Length if included - # Key in binary form - # 2 Byte Cipher Name Length if included - # Cipher name it UTF8 text - - # Remove header and extract flags - _, flags = buffer.slice!(0..MAGIC_HEADER_SIZE+1).unpack(MAGIC_HEADER_UNPACK) - compressed = (flags & 0b1000_0000_0000_0000) != 0 - include_iv = (flags & 0b0100_0000_0000_0000) != 0 - include_key = (flags & 0b0010_0000_0000_0000) != 0 - include_cipher = (flags & 0b0001_0000_0000_0000) != 0 - # Version of the key to use to decrypt the key if present, - # otherwise to decrypt the data following the header - version = flags & 0b0000_0000_1111_1111 - decryption_cipher = SymmetricEncryption.cipher(version) - raise(SymmetricEncryption::CipherError, "Cipher with version:#{version.inspect} not found in any of the configured SymmetricEncryption ciphers") unless decryption_cipher - iv, key, cipher_name = nil - - if include_iv - len = buffer.slice!(0..1).unpack('v').first - iv = buffer.slice!(0..len-1) - end - if include_key - len = buffer.slice!(0..1).unpack('v').first - key = decryption_cipher.binary_decrypt(buffer.slice!(0..len-1), false) - end - if include_cipher - len = buffer.slice!(0..1).unpack('v').first - cipher_name = buffer.slice!(0..len-1) - end - - HeaderStruct.new(compressed, iv, key, cipher_name, version, decryption_cipher) - end - - # Returns a magic header for this cipher instance that can be placed at - # the beginning of a file or stream to indicate how the data was encrypted + # random_iv [true|false] + # Whether the encypted value should use a random IV every time the + # field is encrypted. + # Notes: + # * Setting random_iv to true will result in a different encrypted output for + # the same input string. + # * It is recommended to set this to true, except if it will be used as a lookup key. + # * Only set to true if the field will never be used as a lookup key, since + # the encrypted value needs to be same every time in this case. + # * When random_iv is true it adds the random IV string to the header. + # Default: false + # Highly Recommended where feasible: true # - # Parameters - # compressed - # Sets the compressed indicator in the header + # compress [true|false] + # Whether to compress str before encryption. # Default: false + # Notes: + # * Should only be used for large strings since compression overhead and + # the overhead of adding the encryption header may exceed any benefits of + # compression # - # iv - # The iv to to put in the header - # Default: nil : Exclude from header + # header [true|false] + # Whether to add a header to the encrypted string. + # Default: `always_add_header` # - # key - # The key to to put in the header - # The key is encrypted using the global encryption key - # Default: nil : Exclude key from header - # - # cipher_name - # Includes the cipher_name used. For example 'aes-256-cbc' - # The cipher_name string to to put in the header - # Default: nil : Exclude cipher_name name from header - def self.build_header(version, compressed=false, iv=nil, key=nil, cipher_name=nil) - version ||= SymmetricEncryption.cipher.version - - flags = version # Same as 0b0000_0000_0000_0000 - - # If the data is to be compressed before being encrypted, set the - # compressed bit in the flags word - flags |= 0b1000_0000_0000_0000 if compressed - flags |= 0b0100_0000_0000_0000 if iv - flags |= 0b0010_0000_0000_0000 if key - flags |= 0b0001_0000_0000_0000 if cipher_name - header = "#{MAGIC_HEADER}#{[flags].pack('v')}".force_encoding(SymmetricEncryption::BINARY_ENCODING) - if iv - header << [iv.length].pack('v') - header << iv - end - if key - encrypted = SymmetricEncryption.cipher(version).binary_encrypt(key, false, false, false) - header << [encrypted.length].pack('v').force_encoding(SymmetricEncryption::BINARY_ENCODING) - header << encrypted - end - if cipher_name - header << [cipher_name.length].pack('v') - header << cipher_name - end - header - end - - # Advanced use only - # - # Returns a Binary encrypted string without applying any Base64, or other encoding - # - # add_header [nil|true|false] - # Whether to add a header to the encrypted string - # If not supplied it defaults to true if always_add_header || random_iv || compress - # Default: nil - # - # Creates a new OpenSSL::Cipher with every call so that this call - # is thread-safe - # - # See #encrypt to encrypt and encode the result as a string - def binary_encrypt(str, random_iv=false, compress=false, add_header=nil) + # See #encrypt to encrypt and encode the result as a string. + def binary_encrypt(str, random_iv: false, compress: false, header: always_add_header) return if str.nil? string = str.to_s return string if string.empty? - # Creates a new OpenSSL::Cipher with every call so that this call - # is thread-safe - openssl_cipher = ::OpenSSL::Cipher.new(self.cipher_name) + # Header required when adding a random_iv or compressing + header = Header.new(version: version, compress: compress) if (header == true) || random_iv || compress + + # Creates a new OpenSSL::Cipher with every call so that this call is thread-safe. + openssl_cipher = ::OpenSSL::Cipher.new(cipher_name) openssl_cipher.encrypt openssl_cipher.key = @key - add_header = always_add_header || random_iv || compress if add_header.nil? - result = - if add_header - # Random iv and compress both add the magic header - iv = random_iv ? openssl_cipher.random_iv : @iv - openssl_cipher.iv = iv if iv - # Set the binary indicator on the header if string is Binary Encoded - self.class.build_header(version, compress, random_iv ? iv : nil, nil, nil) + - openssl_cipher.update(compress ? Zlib::Deflate.deflate(string) : string) + + result = + if header + if random_iv + openssl_cipher.iv = header.iv = openssl_cipher.random_iv + elsif self.iv + openssl_cipher.iv = self.iv + end + header.to_s + openssl_cipher.update(compress ? Zlib::Deflate.deflate(string) : string) else - openssl_cipher.iv = @iv if defined?(@iv) && @iv + openssl_cipher.iv = iv if iv openssl_cipher.update(string) end result << openssl_cipher.final end @@ -540,11 +284,11 @@ # # Parameters # encrypted_string [String] # Binary encrypted string to decrypt # - # header [HeaderStruct] + # header [SymmetricEncryption::Header] # Optional header for the supplied encrypted_string # # Reads the 'magic' header if present for key, iv, cipher_name and compression # # encrypted_string must be in raw binary form when calling this method @@ -554,59 +298,58 @@ # the same instance of Cipher # # Note: # When a string is encrypted and the header is used, its decrypted form # is automatically set to the same UTF-8 or Binary encoding - def binary_decrypt(encrypted_string, header=nil) + def binary_decrypt(encrypted_string, header: Header.new) return if encrypted_string.nil? str = encrypted_string.to_s - str.force_encoding(SymmetricEncryption::BINARY_ENCODING) if str.respond_to?(:force_encoding) + str.force_encoding(SymmetricEncryption::BINARY_ENCODING) return str if str.empty? - if header || self.class.has_header?(str) - str = str.dup - header ||= self.class.parse_header!(str) + offset = header.parse(str) + data = offset > 0 ? str[offset..-1] : str - openssl_cipher = ::OpenSSL::Cipher.new(header.cipher_name || self.cipher_name) - openssl_cipher.decrypt - openssl_cipher.key = header.key || @key - iv = header.iv || @iv - openssl_cipher.iv = iv if iv - result = openssl_cipher.update(str) - result << openssl_cipher.final - header.compressed ? Zlib::Inflate.inflate(result) : result - else - openssl_cipher = ::OpenSSL::Cipher.new(self.cipher_name) - openssl_cipher.decrypt - openssl_cipher.key = @key - openssl_cipher.iv = @iv if @iv - result = openssl_cipher.update(str) - result << openssl_cipher.final + openssl_cipher = ::OpenSSL::Cipher.new(header.cipher_name || cipher_name) + openssl_cipher.decrypt + openssl_cipher.key = header.key || @key + if iv = (header.iv || @iv) + openssl_cipher.iv = iv end + result = openssl_cipher.update(data) + result << openssl_cipher.final + header.compressed? ? Zlib::Inflate.inflate(result) : result end + # Returns the magic header after applying the encoding in this cipher + def encoded_magic_header + @encoded_magic_header ||= encoder.encode(SymmetricEncryption::Header::MAGIC_HEADER).gsub('=', '').strip + end + # Returns [String] object represented as a string, filtering out the key def inspect - "#<#{self.class}:0x#{self.__id__.to_s(16)} @key=\"[FILTERED]\" @iv=#{iv.inspect} @cipher_name=#{cipher_name.inspect}, @version=#{version.inspect}, @encoding=#{encoding.inspect}, @always_add_header=#{always_add_header.inspect}" + "#<#{self.class}:0x#{self.__id__.to_s(16)} @key=\"[FILTERED]\" @iv=#{iv.inspect} @cipher_name=#{cipher_name.inspect}, @version=#{version.inspect}, @encoding=#{encoding.inspect}, @always_add_header=#{always_add_header.inspect}>" end - private + # DEPRECATED + def self.has_header?(buffer) + SymmetricEncryption::Header.present?(buffer) + end - attr_reader :key - - # Read from the file, raising an exception if it is not found - def self.read_from_file(file_name) - File.open(file_name, 'rb') { |f| f.read } - rescue Errno::ENOENT => exc - puts "\nSymmetric Encryption key file: '#{file_name}' not found or readable." - puts "To generate the keys for the first time run: bin/rails generate symmetric_encryption:new_keys production\n\n" - raise(exc) + # DEPRECATED + def self.parse_header!(buffer) + header = SymmetricEncryption::Header.new + header.parse!(buffer) ? header : nil end - # Write to the supplied filename, backing up the existing file if present - def self.write_to_file(file_name, data) - File.rename(file_name, "#{file_name}.#{Time.now.to_i}") if File.exist?(file_name) - File.open(file_name, 'wb') { |file| file.write(data) } + # DEPRECATED + def self.build_header(version, compress = false, iv = nil, key = nil, cipher_name = nil) + h = Header.new(version: version, compress: compress, iv: iv, key: key, cipher_name: cipher_name) + h.to_s end + + private + + attr_reader :key end end