Dwolla permits an app to solicit and store a user's PIN as a form of pre-authorization, but requires that it be encrypted. From the TOS:
PIN(s) must be encrypted in transit and at rest (this includes any and all backup mediums) using FIPS 140-2 standards (at a minimum)
Normally, I'd use Bcrypt to encrypt (actually, make a secure hash. Neil Slater, thanks for the correction) something (using bcrypt-ruby gem), such as a password. But if I encrypt with Bcrypt, then I'd have to transmit the hash, and of course that won't match what Dwolla is expecting and the PIN will be rejected.
How do you encrypt the PIN and unencrypt it for secure transmittal?
UPDATE:
One of the answers in the question that Andrew links to below referenced OpenSSL:Cipher, and using that I can encrypt the PIN with the below code. But remaining questions then are:
- How should I store the key, iv (initialization vector), and cipher? Is it secure to save as environment variables, or would it be better to put in a database table in a secure hash?
- Does the below code make sense as a way to encrypt the PIN?
- Since I don't have a public key from Dwolla, what's the best way to transmit it?
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