首页 > 解决方案 > 使用 KDF 在 Go 中使用 bcrypt 获取特定的输出密钥长度

问题描述

看起来 Go 生态系统只有一个基本的 bcrypt 实现(golang.org/x/crypto/bcrypt),开发人员可以练习从编码的输出字符串中提取密钥,然后进一步扩展它以满足特定的需求如果您要将其用作加密密钥,而不是将其作为密码存储在某处的数据库中,则密钥长度。让我感到困惑的是,对于 Go 或一般来说,似乎没有在线上对这个概念进行任何快速处理。

冒着引入错误的风险,我怀疑我将被迫使用scrypt,至少在 Go 中,它确实需要一个输出长度参数。

我错过了什么吗?在 Go 中的某处是否有bcrypt的实现,它采用密钥长度参数并直接管理生成可接受长度的密钥?

标签: gobcryptscryptkdf

解决方案


Bcrypt 不是密钥派生算法;它是一种密码哈希算法。

  • PBKDF2 可以接受密码并输出n所需的位
  • scrypt 可以输入密码并输出n所需的位

这些是密​​钥派生函数。他们获取密码并生成n位,然后您可以将其用作加密密钥。

BCrypt 无法做到这一点。BCrypt 不是密钥派生函数。它是一个密码哈希函数。它总是输出相同数量的位。

奖励: bcrypt 总是准确地输出 24 字节(192 位),因为 bcrypt 的输出是加密的结果OrpheanBeholderScryDoubt

注意:这不是散列 OrpheanBeholderScryDoubt的结果- bcrypt 算法实际上是使用河豚密码进行加密 OrpheanBeholderScryDoubt(并重复加密 64 次)。

bcrypt 的优势来自“昂贵的密钥设置”

奖励:bcrypt 的优势在于它价格昂贵。而“贵”就是记忆。算法需要的内存越多,它对抗暴力攻击的能力就越强。

  • SHA-2:可以在 128 字节的 RAM 中运行
  • bcrypt:不断接触 4 KB 的 RAM
  • scrypt:不断触及 16 MB 的 RAM(在 Android 和 LiteCoin 的默认配置中)
  • Argon2:通常建议您将其配置为触摸 1 GB 的 RAM

防御暴力攻击意味着防御并行化。需要 128 字节的算法可以在 1 GB 视频卡上进行 700 万次并行操作。

Scrypt 需要 16 MB 的 RAM,只能并行运行 62 个。

Argon2 使用 1 GB 的 RAM,只能在显卡上运行 1 个。无论如何,它在 CPU 上运行得更快。

将 bcrypt 组合成密钥派生函数 (KDF)

您可以将 bcrypt 组合成一个密钥派生函数。您可以使用标准功能PBKDF2为您完成。

通常 PBKDF2 被称为:

String password = "hunter2";
String salt     = "sea salt 69 nice";

Byte[] key = PBKDF2(password, salt, 32, 10000); //32-bytes is 256 bits

但是,您可以使用 bcrypt 字符串结果作为盐:

String password = "hunter2";
String salt     = bcrypt.HashPassword(password, 12);

Byte[] key = PBKDF2(password, salt, 32, 1); //32-bytes is 256-bits

现在您已经“使用 bcrypt”生成了一个 256 位密钥。这是一个巧妙的技巧。

事实上,这个 hack 非常简洁,它实际上就是scrypt所做的:

String password = "hunter2";
String salt     = ScryptExpensiveKeyHash(password, userSalt, ...);

Byte[] key = PBKDF2(password, salt, 32, 1); //32-bytes is 256-bits

结论

Bcrypt 不是密钥派生函数。这是 PBKDF2、scrypt(使用 PBKDF2)和 argon2 等函数的目标。

仅允许 NIST 批准的算法时使用 bcrytp

将这个 pbkdf2 构造与 bcrypt 一起使用还有另一个很好的理由。

有时,不知道他们在说什么的“安全专家”会坚持要求您使用 PBDKF2 进行密钥派生。(是的,它确实发生了)。你会一遍又一遍地告诉他们 PBDKF2 是非常弱的密钥派生系统(它基于 SHA2 的运行速度太快了,10,000 或 100,000 次迭代远远不足以保护你免受暴力攻击 -这就是 bcrypt、scrypt 和 argon2 的发明目的)。

但是这个人不会放过它,会要求使用PBKDF2。有了这种结构,您仍然可以使用 bcrypt 来保证安全性,而 PBKDF2 则可以用于需要它的无知者。

您只是碰巧使用了强“盐”


推荐阅读