如何加密必须传输的 PIN



>Dwolla允许应用程序请求和存储用户的PIN作为预授权的形式,但要求对其进行加密。从服务条款:

PIN 必须在传输中和静态时加密(这包括任何和所有备份介质)使用 FIPS 140-2 标准(至少)

通常,我会使用 Bcrypt 来加密(实际上,制作一个安全的哈希。尼尔·斯莱特,感谢您的更正)某些东西(使用 bcrypt-ruby gem),例如密码。但是如果我使用Bcrypt加密,那么我将不得不传输哈希,当然这与Dwolla的期望不符,PIN将被拒绝。

如何加密 PIN 并解密它以实现安全传输?

更新:

Andrew链接到下面的问题中的一个答案引用了OpenSSL:Cipher,使用它,我可以用下面的代码加密PIN。但剩下的问题是:

  1. 我应该如何存储密钥、iv(初始化向量)和密码?另存为环境变量是安全的,还是在安全哈希中放入数据库表更好?
  2. 以下代码作为加密 PIN 的一种方式是否有意义?
  3. 由于我没有来自 Dwolla 的公钥,传输它的最佳方式是什么?

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

这就是我发现的。在 Rails 中,只需生成一次密钥并存储为环境变量(并在部署时对其进行加密)。为每个引脚生成一个新的 iv(初始化向量)。将 iv 和加密引脚存储在数据库中。

您可能希望将加密的 PIN 和 IV 转换为 UTF8,以便在不更改数据库设置方式的情况下成功保存。(默认情况下,它们将生成为 ASCII 8 位)。

以下是在用户模型中执行此操作的一种方法,但您可能需要重构,因为这些是大型方法:

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 端点购买。

有人有什么要补充的吗?

在这种情况下

,我会使用公钥/私钥加密。 不是 Ruby 专家,但此链接可能会有所帮助:

Ruby:使用私钥/公钥进行文件加密/解密

如果您的 PIN 是从外部发送的,则需要最终用户公钥进行加密。 如果这是不可能的,那么你可以使用异步(公共/私有)和对称算法的混合 - 基本上是SSH所做的。

http://en.wikipedia.org/wiki/Secure_Shell

相关内容

  • 没有找到相关文章

最新更新