Dwolla允许应用程序作为预授权形式征求和存储用户的PIN,但要求加密。来自TOS:
PIN码必须在传输和静止时加密(包括任何和 所有备份媒体)使用FIPS 140-2标准(至少)
通常情况下,我会使用Bcrypt加密(实际上是一个安全的哈希。尼尔斯莱特,谢谢你的修正)(使用bcrypt-ruby gem),比如密码。但是如果我使用Bcrypt进行加密,那么我必须传输哈希值,当然这与Dwolla所期望的不相符,并且PIN将被拒绝。
如何加密PIN并对其进行解密以进行安全传输?
安德鲁链接到下面引用OpenSSL:Cipher的问题中的答案之一,并使用它我可以使用以下代码加密PIN。但剩下的问题是:
pin = "1111" # this is what needs to be encrypted
#encryption:
cipher = OpenSSL::Cipher.new('AES-128-CBC') #=> #<OpenSSL::Cipher:0x00000100ef09d8>
cipher.encrypt
key = cipher.random_key #=> odd characters...
iv = cipher.random_iv #=> odd characters...
encrypted = cipher.update(pin) + cipher.final #=> odd characters...
#dcryption:
decipher = OpenSSL::Cipher::AES.new(128, :CBC)
decipher.decrypt
decipher.key = key
decipher.iv = iv
plain = decipher.update(encrypted) + decipher.final
puts plain == pin #=> true
答案 0 :(得分:3)
所以这就是我发现的。在Rails中,只生成一次密钥并存储为环境变量(当您部署加密时)。为每个引脚生成新的iv(初始化向量)。将iv和加密的引脚存储在数据库中。
您可能希望将加密的PIN和IV转换为UTF8,以便成功保存,而无需更改设置数据库的方式。 (默认情况下,它们将生成为ASCII 8位)。
这是在User模型中执行此操作的一种方法,但您可能需要重构,因为这些是大型方法:
def dwolla_pin # => this is to decrypt the PIN in order to use it
unless encrypted_dwolla_pin.nil?
decipher = OpenSSL::Cipher::AES.new(128, :CBC)
decipher.decrypt
decipher.key = ENV["ENCRYPT_KEY"]
# Convert IV from UTF8 (as stored) back to ASCII-8bit (for OpenSSL)
utf8_iv = self.iv_for_pin
decipher.iv = Base64.decode64(utf8_iv.encode('ascii-8bit'))
# Convert PIN from UTF8 (as stored) back to ASCII-8bit (for OpenSSL)
utf8_pin = self.encrypted_dwolla_pin
ascii_pin = Base64.decode64(utf8_pin.encode('ascii-8bit'))
dwolla_pin ||= decipher.update(ascii_pin) + decipher.final
end
end
def dwolla_pin=(new_pin) # => this is to encrypt the PIN in order to store it
return false unless valid_pin?(new_pin)
cipher = OpenSSL::Cipher.new('AES-128-CBC')
cipher.encrypt
cipher.key = ENV["ENCRYPT_KEY"]
# Create IV and convert to UTF-8 for storage in database
iv = cipher.random_iv
utf8_iv = Base64.encode64(iv).encode('utf-8')
self.update_attribute(:iv_for_pin, utf8_iv)
# Encrypt PIN and convert to UTF-8 for storage in database
encrypted_pin = cipher.update(new_pin) + cipher.final
utf8_pin = Base64.encode64(encrypted_pin).encode('utf-8')
self.update_attribute(:encrypted_dwolla_pin, utf8_pin)
end
def valid_pin?(pin) # => Here I'm just checking to make sure the PIN is basically in the right format
pin.match(/^\d{4}/) && pin.length == 4
end
“安全传输”表示使用SSL和部署SSH。如果部署到Heroku然后已经使用SSH,但对于SSL,您需要从您的DNS主机通配符证书和Heroku上的ssl端点购买。
有没有人可以添加任何内容?
答案 1 :(得分:0)
我会在这种情况下使用公钥/私钥加密。不是Ruby专家,但这个链接可能会有所帮助:
Ruby: file encryption/decryption with private/public keys
如果您的引脚是从外部发送的,那么您需要最终用户公钥进行加密。如果这是不可能的,那么你可以使用异步(公共/私有)和对称算法的混合 - 基本上是SSH所做的。