How to encrypt the PIN code to be transmitted?

Dwolla allows the application to request and store the user's PIN as a pre-authorization form, but requires it to be encrypted. From TOS :

The PIN code must be encrypted during transit and at rest (this includes any and all backup media) using FIPS 140-2 standards (at least)

Typically, I use Bcrypt to encrypt (actually, make a secure hash. Neil Slater, thanks for fixing) something (using the bcrypt-ruby bug), like a password. But if I encrypt using Bcrypt, then I will have to transfer the hash, and of course, this will not match the expected Dwolla, and the PIN will be rejected.

How do you encrypt your PIN and decrypt it for secure receipt?

UPDATE:

One of the answers in the question Andrew refers to below refers to OpenSSL: Cipher , and using this, I can encrypt the PIN code below the code. But the remaining questions:

  • How to store a key, iv (initialization vector) and encrypt? Is it safe to save as environment variables, or would it be better to put the database table in a safe hash?
  • Is the code below clear for PIN encryption?
  • Since I do not have a public key for Dwolla, what is the best way to transfer 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
+4
source share
2 answers

. Rails ( ). iv ( ) . iv .

, - 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 ssl Heroku.

- ?

+3
0

All Articles