如何将 Argon2 密码存储在我的数据库中?

How do I store Argon2 passwords in my database?

我正在尝试使用 Argon2 算法将用户密码存储在我的数据库中。

这是我使用它得到的:

<span class="math-container">$echo -n "password" | argon2 "smallsalt" -id -t 4 -m 18 -p 4
Type:           Argon2id
Iterations:     4
Memory:         262144 KiB
Parallelism:    4
Hash:           cb4447d91dd62b085a555e13ebcc6f04f4c666388606b2c401ddf803055f54ac
Encoded:        $</span>argon2id<span class="math-container">$v=19$</span>m=262144,t=4,p=4<span class="math-container">$c21hbGxzYWx0$</span>y0RH2R3WKwhaVV4T68xvBPTGZjiGBrLEAd34AwVfVKw
1.486 seconds
Verification ok

在这种情况下,我应该在数据库中存储什么

拜托,你能帮帮我吗?我是这方面的新手,有点迷路了。

我会把typeiterationsmemoryparallelismhashsalt和相应的用户id放入分开列并留下编码位,因为它只是所有属性连接在一起。如果它们位于不同的列中,那么您可以更轻松地引用属性,而不必拆分和索引编码字符串。

另一种选择是仅将编码后的字符串存储在 1 列中,但正如我所说,查看某些属性更加乏味,因为您必须拆分编码后的字符串然后对其进行索引。

都没有。将以下内容保存为单个值:

  • 算法 ID(例如 argon2id)
  • 迭代次数 (4)
  • 内存使用系数 (18)
  • 并行度 (4)

字段 "encoded" 的输出具有误导性,因为您不能 按原样使用它 进行密码检查(即哈希生成),例如m=262144 其中密码检查需要原始因子 m=18.

是否要在每次检查密码时启动一个 OS 进程?我会阻止你这样做。我建议您使用库(C++、Java、...)。他们生成一个字符串,其中包含所有这些用“$”连接和分隔的数据。

我来晚了一点,但我不同意前面的答案。
您应该存储字段:Encoded
$argon2id$.... 值。

(至少如果您使用的是具有 verify() 函数的普通 Argon2 库。 然而,man-page for argon2 命令看起来不像是这样做的。

只有当您受困于命令行时,才应考虑单独存储每个字段。)

$argon2id$ 编码哈希
argon2 编码的散列与它的表亲 bcrypt's syntax.

相同

编码的哈希值包括您在用户登录时验证哈希值所需的一切。

这很可能是未来的证明。当更新更好的 argon2 出现时:您可以升级单列散列密码。就像您可以检测到 bcrypt 的 $2a$-hashes,并将它们重新散列为 $argon2id$-hashes,下次用户登录时。(如果您从 bcrypt 转移到 agron2。)

TL;DR
将 $ 编码值 encoded_hash 存储在您的数据库中。
使用argon2.verify(password, encoded_hash)验证密码是否正确。

不必为散列中的所有值操心。让图书馆为您做这件事。 :)

我有同样的问题并在收集一些信息时阅读了此 post。现在,经过几天的思考,我个人会采取与接受的答案不同的路线,因此略微不同意。我想我会分享我的观点,这样它也可能对其他人有所帮助。

我想这将取决于每个人的情况。我认为这里没有适合所有人的答案。我确定在某些情况下它是完全有效的,甚至 better/simpler 存储编码字符串 ($argon2...)。

但是,我认为根据上下文,存储编码字符串似乎不是正确的方法。

首先,它使散列方法非常明显。它可能不是那么重要,但出于某些原因,它让我没有它更舒服 ^^。但是,更重要的是,这意味着实现细节存储在您的持久层(数据库或其他)中。在撰写本文时,argon2id 是 OWASP 推荐的哈希机制,但这些东西可能会改变(最终会改变......)。有一天,它可能会被认为是不安全的,或者另一个功能会被认为更安全。

因此,我建议这个更多功能“不可知论”的起点:

  • 散列(对于 argon2 -> 十六进制字符串)
  • last_modified日期
  • 带有散列参数的字符串(对于argon2,您可以将参数以您选择的形式放在这里)

last_modified 允许知道散列是否需要更新,参数允许支持“旧”散列的验证和更新。

当然,这意味着您必须在代码中多做一些工作,不能简单地直接使用每个库的快捷方式。但是,我会说这种增加的复杂性在其他情况下提供了更大的灵活性(比如摆脱给定的哈希函数)。天下没有免费的午餐。

这就是为什么我认为这取决于您的上下文以及为什么我个人不会在我的情况下接受公认的答案。

PS:我不是密码学专家,也不是开发安全专家。因此,请随意反驳、丰富、同意或不同意。我只是想保留我的实施细节 ;)