Armazenar senhas descriptografáveis ​​em instâncias ActiveModel

Isso é ótimo quando você precisa de criptografia bidirecional para armazenar senhas de serviço externo.

gem 'gibberish'

module HasDecryptablePassword
SALT_LENGTH
= 64
KEY_LENGTH
= 64

# TODO move (and change) AES_KEY to secrets.yml
# AES_KEY will need to be known by all apps, i.e background jobs, etc.
AES_KEY
= 'your-secret-key'
AES_SIZE
= 256 # TODO 512 is not supported by gibberish gem, investigate

module ActiveModel
extend
ActiveSupport::Concern

included
do
include
HasDecryptablePassword
validates
:encrypted_password, presence: true
validates
:salt, presence: true, length: {is: SALT_LENGTH}
before_validation
:encrypt_password
end
end

def encrypt_password
self.encrypted_password = aes_cipher.enc(password)
true
end

def decrypted_password
aes_cipher
.dec(encrypted_password)
end

private

def aes_cipher
Gibberish::AES.new(key, AES_SIZE)
end

def key
generate_salt

fail
unless AES_KEY.length == KEY_LENGTH
fail
unless salt.length == SALT_LENGTH
AES_KEY
+ salt
end

def generate_salt
self.salt ||= SecureRandom.hex(SALT_LENGTH >> 1)
end

end