bcrypt vs pbkdf2用于加密私钥

pup*_*eno 6 encryption cryptography bcrypt pbkdf2

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

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

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

Ian*_*oyd 10

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

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

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

  • PBKDF2
  • scrypt

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

你喂这两种算法:

  • 密码
  • 成本参数
  • 所需的字节数(例如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
Run Code Online (Sandbox Code Playgroud)

您需要密码和密钥之间的距离.

不推荐作弊

如果你真的急于节省CPU周期(并避免计算两次scrypt),你在技术上可以采取:

Key Material ---SHA2---> "hashed password"
Run Code Online (Sandbox Code Playgroud)

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

但它更不可取,因为你正在存储(转换的)加密密钥版本.您希望尽可能少地存储该密钥(及其任何转换版本).

总结一下

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

并上传

  • encryptedPrivateKey
  • passwordhash