bcrypt vs pbkdf2 用于加密私钥

bcrypt vs pbkdf2 for encrypting private keys

我正在构建一个应用程序,其中在客户端使用密码来加密椭圆曲线密钥对的私钥。然后将密码加密并发送到服务器(连同加密的私钥)和 public 密钥。

最初,我在加密私钥之前使用 pbkdf2 对密码进行哈希处理,但由于我也在对密码进行 bcrypted,我可以改用 bcrypted 吗?

根据 https://medium.com/@mpreziuso/password-hashing-pbkdf2-scrypt-bcrypt-1ef4bb9c19b3#.sj4jcbynx,答案不仅是肯定的,而且 bcrypt 更好,因为它具有更强的 GPU-ASIC 弹性。有什么我想念的吗?

您不应该使用 bcrypt 散列输出作为加密密钥;它不是关键 material:

  • BCrypt 不是密钥派生 函数
  • BCrypt 是一个密码存储功能

您有一个要使用用户密码加密的椭圆曲线私钥。当然,您不想直接 使用密码 - 您希望使用密码 导出 加密密钥。为此,您可以使用:

  • PBKDF2
  • scrypt

这些都是密钥派生函数(例如基于密码的密钥派生函数)。他们的目的是在给定密码的情况下生成加密密钥。它们被设计为 "hard".

您为这两种算法提供数据:

  • 密码
  • 成本参数
  • 所需的字节数(例如 32 ==> 32 字节 ==> 256 位)

它 returns 是一个 256 位密钥,可以用作 AES-256 的加密密钥。

然后您想要备份用户的密钥

我猜你想:

  • 将加密的椭圆曲线私钥存储在您的服务器上
  • 在您的服务器上存储他们密码的散列

你的问题是:既然你已经通过 "a hashing funtion" 运行 他们的密码,你不能只使用该哈希值作为他们存储的密码吗?

没有!该散列也是保护其私钥的加密密钥。您不希望私钥 t运行 发送到任何地方。你不希望它存在于任何地方。那个 32 字节的加密密钥应该在您用完后立即从内存中删除。

如果您还希望存储用户密码的 散列 ,您应该使用通常用于密码存储的算法:

  • pbkdf2(滥用密码存储的密钥派生函数)
  • bcrypt(优于 pbkdf2)
  • scrypt(滥用密码存储的密钥派生函数;比 bcrypt 更好)
  • argon2(优于 scrypt)

您应该通过这些密码存储算法之一单独 运行 用户密码。如果您有权访问 bcrypt;在 pbkdf2 上使用它。如果您有 scrypt,请同时使用它:

  • 加密密钥的推导
  • 密码散列

您系统的安全性来自(除了密码的保密性),用户密码与保护其私钥的加密密钥之间的计算距离:

"hunter2"  --PBKDF2--> Key material
"hunter2"  ---------bcrypt-------> Key material
"hunter2"  ----------------scrypt----------> Key material

您希望密码和密钥之间的距离尽可能远。

不推荐作弊

如果您真的非常想节省 CPU 个周期(并避免计算两次 scrypt),从技术上讲,您可以采取:

Key Material ---SHA2---> "hashed password"

并将加密密钥的散列称为 "hashed password" 并存储它。单个 SHA2 的计算可以忽略不计。这是可以接受的,因为攻击者使用它的唯一方法是尝试猜测每个可能的 256 位加密密钥——这是他们首先无法解决的问题。无法暴力破解 256 位密钥。如果他们试图暴力破解它,额外的散列版本对他们没有帮助,因为他们只能通过尝试解密私钥来测试他们的尝试。

但它不太令人满意,因为您正在存储(t运行sformed)版本的加密密钥。您希望尽可能少地存储该密钥(以及它的任何 t运行 变形版本)。

总结

  • 生成 EC 密钥对
  • encryptionKey = scryptDeriveBytes(密码、盐、成本、32)
  • encryptedPrivateKey = AES256(privateKey, encryptionKey)
  • passwordHash = scryptHashPassword(密码,salt,成本)

并上传

  • 加密私钥
  • 密码哈希