Symfony 5 如何为 argon2 存储盐?

Posted

技术标签:

【中文标题】Symfony 5 如何为 argon2 存储盐?【英文标题】:How Symfony 5 stores salt for argon2? 【发布时间】:2020-09-11 00:02:18 【问题描述】:

symfony 如何为 argon2 存储盐字符串?在对密码进行编码时,氩中的盐是强制性的,但用户实体中没有存储盐字符串。密码编码器中的函数支持盐作为参数,但为空且从未使用过

/vendor/symfony/security-core/Encoder/SodiumPasswordEncoder.php

public function encodePassword(string $raw, ?string $salt): string

    if (\strlen($raw) > self::MAX_PASSWORD_LENGTH) 
        throw new BadCredentialsException('Invalid password.');
    

    if (\function_exists('sodium_crypto_pwhash_str')) 
        return sodium_crypto_pwhash_str($raw, $this->opsLimit, $this->memLimit);
    

    if (\extension_loaded('libsodium')) 
        return \Sodium\crypto_pwhash_str($raw, $this->opsLimit, $this->memLimit);
    

    throw new LogicException('Libsodium is not available. You should either install the sodium extension, upgrade to php 7.2+ or use a different encoder.');

【问题讨论】:

最终 Symfony 使用password_hash 来生成哈希。除了实际的哈希和盐之外,算法及其选项(强度等)也存储在返回值中。 php 文档详细讨论了它。还有一个 password_get_info 可以解压数据。如果您想知道,UserInterface 仍然具有盐属性,只是为了向后兼容。我预计它会在 6.x 中消失。 【参考方案1】:

盐直接存储在哈希密码上,不需要使用单独的字段来存储盐。

不使用$salt 参数,因为每次调用sodium_crypto_pwhash_str 都会生成随机盐,如the docs 中所述:

使用 CPU 和内存硬散列算法以及随机生成的盐,以及内存和 CPU 限制来生成适合密码存储的 ASCII 编码散列。

返回值将包含散列密码、使用的算法、盐、内存成本、时间成本等。重新散列和验证用户提供的密码所需的一切,这就是存储在 UserInterface::$password 上的内容。

例如,调用:

sodium_crypto_pwhash_str('secret_string',
    SODIUM_CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE,
    SODIUM_CRYPTO_PWHASH_MEMLIMIT_INTERACTIVE
);

会返回如下内容:

$argon2i$v=19$m=32768,t=4,p=1$smna9HfWD+caJJakZiekyQ$qbflsyuP3txLRgsGIt1alcv7HmYjfiMPanYtDU0LtCA

different parts of the response由$字符分隔,如下:

    argon2i: 使用的算法 v=19:版本 m=32768,t=4,p=1:算法选项(内存成本、时间成本和要使用的线程) smna9HfWD+caJJakZiekyQ这是自动生成的盐。 qbflsyuP3txLRgsGIt1alcv7HmYjfiMPanYtDU0LtCA。实际的哈希值。

这是存储在UserInterface::$password 上的内容,如您所见,其中包含验证哈希所需的所有信息,包括盐。不推荐将盐存储在单独的字段中,并且仅保留该字段以实现向后兼容性。

任何使用上述方法或推荐的password_hash 的人都可以在没有专门的盐场的情况下满足他们的所有需求。

【讨论】:

好的,谢谢你的澄清。那么,请告诉我,这个字符串盐的哪一部分是? $2y$13$GplmMPH1MeZFkFJ48jjTcuLaP1TC7eTIy903KnZehhEWjQcvLaxqO 我已经测试了 argon2 (github.com/p-h-c/phc-winner-argon2) 手动提供盐,并且 argon2 在编码字符串中不包含盐。我使用“密码”作为密码,使用“XXXXXX”作为盐字符串。 Argon2 创建:$argon2i$v=19$m=65536,t=2,p=2$WFhYWFhYAHA$P2871ERltPKz+IKGGbLI6RwnLxoFIvW9+tYyBgo3pDU 所以不存储盐 我发现,WFhYWFhYAHA 这是 base64 编码的盐字符串 :)

以上是关于Symfony 5 如何为 argon2 存储盐?的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法使用 Argon2i 加密来解密密码?

Symfony 2. 如何为实体的嵌入表单设置默认值?

如何为 Symfony2 站点正确设置 Varnish?

Symfony2:如何为整个应用程序强制使用 HTTPS?

Symfony:如何为与 Voryx REST Bundle 的一对多关系创建 POST 请求

如何为 Symfony3 上的 AJAX 调用添加 CSRF 保护?