Method: SymmetricEncryption.decrypt

Defined in:
lib/symmetric_encryption/symmetric_encryption.rb

.decrypt(encrypted_and_encoded_string, version: nil, type: :string) ⇒ Object

Decrypt supplied string.

Returns [String] the decrypted string.
Returns [nil] if the supplied value is nil.
Returns [''] if it is a string and it is empty.

Parameters
  string [String]
    Encrypted string to decrypt.
  version [Integer]
    Specify which cipher version to use if no header is present on the
    encrypted string.
  type [:string|:integer|:float|:decimal|:datetime|:time|:date|:boolean]
    If value is set to something other than :string, then the coercible gem
    will be use to coerce the unencrypted string value into the specified
    type. This assumes that the value was stored using the same type.
    Note: If type is set to something other than :string, it's expected
      that the coercible gem is available in the path.
    Default: :string

If the supplied string has an encryption header then the cipher matching
the version number in the header will be used to decrypt the string

When no header is present in the encrypted data, a custom Block/Proc can
be supplied to determine which cipher to use to decrypt the data.
see #cipher_selector=

Raises: OpenSSL::Cipher::CipherError when ‘str’ was not encrypted using the primary key and iv

NOTE: #decrypt will not attempt to use a secondary cipher if it fails

to decrypt the current string. This is because in a very small
yet significant number of cases it is possible to decrypt data using
the incorrect key. Clearly the data returned is garbage, but it still
successfully returns a string of data


127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# File 'lib/symmetric_encryption/symmetric_encryption.rb', line 127

def self.decrypt(encrypted_and_encoded_string, version: nil, type: :string)
  return encrypted_and_encoded_string if encrypted_and_encoded_string.nil? || (encrypted_and_encoded_string == "")

  str = encrypted_and_encoded_string.to_s

  # Decode before decrypting supplied string
  decoded = cipher.decode(str)
  return unless decoded
  return decoded if decoded.empty?

  header    = Header.new
  decrypted =
    if header.parse!(decoded)
      header.cipher.binary_decrypt(decoded, header: header)
    else
      c =
        if version
          # Supplied version takes preference
          cipher(version)
        elsif @select_cipher
          # Use cipher_selector if present to decide which cipher to use
          @select_cipher.call(str, decoded)
        else
          # Global cipher
          cipher
        end
      c.binary_decrypt(decoded)
    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
  Coerce.coerce_from_string(decrypted, type)
end