我希望使用AES算法加密并解密 模型的一个属性字符串值。
我想知道 Rails ,最简单的方法是什么?是否有可以直接使用的 AES gem
库?以及如何使用它?
基本上我需要一些关于如何在Rails应用中应用 AES 加密/解密的指南。
-------更新-------
我注意到AES gem。如果我将这个gem添加到我的GemFile中,我如何在我的加密应用程序中使用它?解密?
答案 0 :(得分:7)
AFAIK,aes
gem包装了openssl
Ruby标准库,以提供更加简化的界面。它仅支持aes-256-cbc
,这是具有密码块链接的256位AES。您可能会在Rails中为模型添加加密/解密方法。
加密的基本操作顺序是:
aes-256-cbc
的初始化向量(aes
gem实际上可以为您执行此操作,因此您可以跳过此步骤):format
(默认为Base64,否则为纯Ruby字节串)和/或初始化向量:iv
那将是:
key = AES.key
=> "6476b3f5ec6dcaddb637e9c9654aa687" # key ends up as a 32-char long hex string
iv = AES.iv(:base_64)
=> "PPDRCMsZhumCdEO1Zm05uw=="
enc64 = AES.encrypt("hello, secret world", key, {:iv => iv})
=> "PPDRCMsZhumCdEO1Zm05uw==$b3CCy/1dAMJ2JG5T50igEMGtvo9Ppkla1c9vrKbo+zQ="
# note that the encrypted result is the :iv
# and Base64-transformed encrypted message
# concatenated with $
然后,您可以通过传入整个enc64
+ :iv
+加密的消息字符串以及AES 256位$
来解密key
。
AES.decrypt(enc64, key)
=> "hello, secret world"
在Ruby中使用openssl
标准库有一些经验,我可以告诉你,英文文档很少,而日文文档非常好。无论如何,使用openssl
API最多会让人感到困惑,所以如果你不介意将自己限制在aes-256-cbc
,那么这个aes
gem看起来非常有用。
请注意,作者确实对速度有一个警告。如果您发现需要更快的解决方案,则应该查看FastAES
。但是,FastAES
是一个C扩展,并且需要为您的目标平台编译。
答案 1 :(得分:5)
我建议在您的应用中制作一个模块,并将其包含在您想要使用的位置,并使用模块方法:
模块
require 'openssl'
require 'base64'
module Preventurl
def self.included(base)
base.extend self
end
def cipher
OpenSSL::Cipher::Cipher.new('aes-256-cbc') # ('aes-256-cbc')
end
def cipher_key
'jabcderfghfhfddd!'
end
def decrypt(value)
c = cipher.decrypt
c.key = Digest::SHA256.digest(cipher_key)
c.update(Base64.decode64(value.to_s)) + c.final
end
def encrypt(value)
c = cipher.encrypt
c.key = Digest::SHA256.digest(cipher_key)
Base64.encode64(c.update(value.to_s) + c.final)
end
end
在应用程序控制器include MyModule
现在来自任何控制器:
encrypt("This is a text")
==> "h0RGuW5m3Wk9AAspik9ZXVysOcy2IeQrhQDn85mdo5I=%0A"
decrypt("h0RGuW5m3Wk9AAspik9ZXVysOcy2IeQrhQDn85mdo5I=%0A")
==> "This is a text"
答案 2 :(得分:2)
您可以使用OpenSSL库。创建以下功能,然后您可以使用加密和解密方法。
def aes(m,k,t)
(aes = OpenSSL::Cipher::Cipher.new('aes-256-cbc').send(m)).key = Digest::SHA256.digest(k)
aes.update(t) << aes.final
end
def encrypt(key, text)
aes(:encrypt, key, text)
end
def decrypt(key, text)
aes(:decrypt, key, text)
end
答案 3 :(得分:2)
https://github.com/shuber/attr_encrypted
http://ezcrypto.rubyforge.org/
attr_encrypted对我很有用 - 虽然我也使用过Ezcrypto。它充当OpenSSL库的包装器。
答案 4 :(得分:2)
我偶然发现了同样的问题并为此创建了一个简单的模型问题(rails 5):
require 'openssl'
require 'base64'
module EncryptableModelConcern
extend ActiveSupport::Concern
included do
before_save :encrypt_encryptable_attributes
after_save :decrypt_encryptable_attributes
after_find :decrypt_encryptable_attributes
end
module ClassMethods
# Sets the model `@encryptable_attributes` class instance variable.
# Encryptable attributes are encrypted before saving using `before_save` hook and decrypted using `after_save` and `after_find` hooks.
# Example:
# ```
# class Board < BaseModel
# encryptable_attributes :name, :title, :content
# end
# ```
def encryptable_attributes(*attrs)
@encryptable_attributes = attrs
end
end
# Returns the model's `@encryptable_attributes` class instance variable.
#
def encryptable_attributes
self.class.instance_variable_get(:@encryptable_attributes) || []
end
# Encryptes the model's encryptable attributes before saving using Rails' `before_save` hook.
#
# **Note: Be careful in calling this method manually as it can corrupt the data.**
def encrypt_encryptable_attributes
encryptable_attributes.each do |k|
self[k] = encrypt(self[k])
end
end
# Decrypts the model's encryptable attributes using Rails' `after_save` and `after_find` hooks.
#
# **Note: Be careful in calling this method manually as it can corrupt the data.**
def decrypt_encryptable_attributes
encryptable_attributes.each do |k|
self[k] = decrypt(self[k])
end
end
private
def cipher
OpenSSL::Cipher::Cipher.new('aes-256-cbc')
end
def cipher_key
Rails.configuration.crypto['key'] # <-- your own key generator here
end
def encrypt(value)
c = cipher.encrypt
c.key = Digest::SHA256.digest(cipher_key)
c.iv = iv = c.random_iv
Base64.encode64(iv) + Base64.encode64(c.update(value.to_s) + c.final)
end
def decrypt(value)
c = cipher.decrypt
c.key = Digest::SHA256.digest(cipher_key)
c.iv = Base64.decode64 value.slice!(0,25)
c.update(Base64.decode64(value.to_s)) + c.final
end
end
将其包含在您希望拥有加密属性的模型中
class Post < ApplicationRecord
include EncryptableModelConcern
encryptable_attributes :title, :content
end
现在,您的模型属性将在before_save
上加密,并将在after_save
和after_find
挂钩上解密。