55 lines
1.1 KiB
Ruby
55 lines
1.1 KiB
Ruby
# frozen_string_literal: true
|
|
require 'openssl'
|
|
require 'base64'
|
|
|
|
class CryptSerializer
|
|
attr_reader :cipher
|
|
|
|
class << self
|
|
# pulling from DB - return plain value
|
|
def load value
|
|
new.decrypt value
|
|
end
|
|
|
|
# saving to DB - return encrypted value
|
|
def dump value
|
|
new.encrypt value
|
|
end
|
|
end
|
|
|
|
def initialize
|
|
@cipher = OpenSSL::Cipher::AES.new(256, :CBC)
|
|
end
|
|
|
|
def encrypt(value)
|
|
return value if value.nil?
|
|
unless value.is_a?(String)
|
|
raise "Attribute was supposed to be a `String`, but was instead a `#{value.class}`"
|
|
end
|
|
|
|
build_cipher value
|
|
end
|
|
|
|
def decrypt(value)
|
|
return value if value.nil?
|
|
|
|
parts = Marshal.load Base64.urlsafe_decode64(value)
|
|
decode_cipher parts
|
|
end
|
|
|
|
private
|
|
|
|
def build_cipher value
|
|
cipher.encrypt
|
|
parts = [cipher.random_key, cipher.random_iv, cipher.update(value) + cipher.final]
|
|
Base64.urlsafe_encode64 Marshal.dump(parts)
|
|
end
|
|
|
|
def decode_cipher parts
|
|
cipher.decrypt
|
|
cipher.key = parts[0]
|
|
cipher.iv = parts[1]
|
|
cipher.update(parts[2]) + cipher.final
|
|
end
|
|
end
|