module Encryptable
  extend ActiveSupport::Concern

  private
    def encrypt(attribute)
      crypt.encrypt_and_sign(attribute)
    end

    def decrypt(attribute)
      crypt.decrypt_and_verify(attribute)
    end

    def crypt
      key_base = Rails.application.secrets.secret_key_base[0..31]
      ActiveSupport::MessageEncryptor.new(key_base, key_base)
    end

    # methods below are used to decrypt legacy fields using Defuse/php-encryption library

    def legacy_decrypt(attribute)
      cipher_text = hex_to_bin(attribute)
      encrypted = cipher_text.byteslice(52, cipher_text.bytesize - 84)
      cipher = OpenSSL::Cipher.new('aes-256-ctr')
      cipher.decrypt
      cipher.key = key(cipher_text)
      cipher.iv = cipher_text.byteslice(36, 16)
      cipher.update(encrypted) + cipher.final
    end

    def hex_to_bin(password)
      password.scan(/../).map(&:hex).pack('c*')
    end

    def load_from_ascii
      key_base = Rails.application.secrets.legacy_key_base
      bytes = hex_to_bin(key_base)
      bytes.byteslice(4, bytes.bytesize - 36)
    end

    def key(text)
      HKDF.new(
        load_from_ascii,
        salt: text.byteslice(4, 32),
        algorithm: 'SHA256', info: 'DefusePHP|V2|KeyForEncryption'
      ).read(32)
    end
end
