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,成本)
并上传
- 加密私钥
- 密码哈希
我正在构建一个应用程序,其中在客户端使用密码来加密椭圆曲线密钥对的私钥。然后将密码加密并发送到服务器(连同加密的私钥)和 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,成本)
并上传
- 加密私钥
- 密码哈希