bcrypt vs pbkdf2用于加密私钥

时间:2016-11-12 19:49:25

标签: encryption cryptography bcrypt pbkdf2

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

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

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

1 个答案:

答案 0 :(得分:9)

您不应将 bcrypt 哈希输出用作加密密钥;它并不是关键材料:

  • BCrypt不是密钥派生功能
  • BCrypt是密码存储功能

您要使用用户密码加密椭圆曲线私钥。当然,您不想直接使用密码 - 您希望使用密码派生加密密钥。为此你可以使用:

  • PBKDF2
  • scrypt

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

您提供这两种算法:

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

它会返回一个256位密钥,您可以将其用作AES-256的加密密钥。

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

我认为你想要:

  • 将加密的椭圆曲线私钥存储在您的服务器上
  • 在您的服务器上存储其密码的哈希

您的问题是:因为您已经通过"哈希函数" 运行了密码,您是否只能将该哈希用作其存储的密码?

没有!该哈希也是保护其私钥的加密密钥。您不希望在任何地方传输私钥。你不希望它存在于任何地方。一旦你完成了它,就应该从内存中擦除这个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"

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

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

总结

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

并上传

  • encryptedPrivateKey
  • passwordhash