Argon2

Argon2 是一种现代、安全且抗 ASIC抗 GPU 的密钥派生函数。在 CPU 和 RAM 用量配置参数相近的情况下,正确配置的 Argon2 比 PBKDF2BcryptScrypt 更能抵抗密码破解。

Argon2 的变体

Argon2 函数有多个变体:

  • Argon2d——具有很强的 GPU 抗性,但可能受到侧信道攻击(只在非常特殊的情况下可能发生)。
  • Argon2i——GPU 抗性较弱,但不存在侧信道攻击。
  • Argon2id——推荐使用(结合了 Argon2d 和 Argon2i)。

Argon2 的配置参数

Argon2 具有以下配置参数,与 Scrypt 非常相似:

  • password P:要进行哈希的密码(或消息)
  • salt S:随机生成的盐(密码哈希建议使用 16 字节)
  • iterations t:要执行的迭代次数
  • memorySizeKB m:要使用的内存量(以 KB 为单位)
  • parallelism p:并行度(即线程数)
  • outputKeyLength T:期望返回的字节数

Argon2——示例

可以在这里在线试用 Argon2 基于密码的密钥派生函数:http://antelle.net/argon2-browser

在 Python 中计算 Argon2——示例

现在编写一些 Python 代码,使用 Argon2 算法从密码派生密钥。

首先,使用以下命令安装 Python 包 argon2_cffi

pip install argon2_cffi

现在编写用于计算 Argon2 的 Python 代码:

import argon2, binascii

hash = argon2.hash_password_raw(
    time_cost=16, memory_cost=2**15, parallelism=2, hash_len=32,
    password=b'password', salt=b'some salt', type=argon2.low_level.Type.ID)
print("Argon2 raw hash:", binascii.hexlify(hash))

argon2Hasher = argon2.PasswordHasher(
    time_cost=16, memory_cost=2**15, parallelism=2, hash_len=32, salt_len=16)
hash = argon2Hasher.hash("password")
print("Argon2 hash (random salt):", hash)

verifyValid = argon2Hasher.verify(hash, "password")
print("Argon2 verify (correct password):", verifyValid)

try:
    argon2Hasher.verify(hash, "wrong123")
except:
    print("Argon2 verify (incorrect password):", False)

运行上面的代码示例:https://repl.it/@nakov/Argon2-in-Python

上述代码首先派生一个“原始哈希”(256 位密钥),这是基于 argon2 的密钥派生,与 scrypt 类似。它还会派生一个“argon2 哈希”,其中包含算法参数、随机盐和派生密钥。后者用于密码存储和验证。最后,使用正确密码和错误密码测试计算出的哈希。

Argon2 计算接受多个输入配置项time_cost(迭代次数)、memory_cost(以 KB 计的内存用量)、parallelism(要使用的并行线程数)、hash_len(派生密钥大小)、salt_len(随机生成的盐大小,通常为 128 位/16 字节)。

上述代码执行的输出示例:

Argon2 raw hash: b'157f21dd3fdf7bafb76d2923ccaffa0b7be7cbae394709474d2bc66ee7b09d3e'
Argon2 hash (random salt): $argon2id$v=19$m=32768,t=16,p=2$Rfy6J41W9idBU+n/8sZc6Q$i3QYYPtoogIAw78I2qqlUQ8vjzUXGG1V6QsBOq2NIp4
Argon2 verify (correct password): True
Argon2 verify (incorrect password): False

请注意,上述输出中的 argon2 哈希采用标准化格式,其中包含 Argon2 算法配置参数 + 派生密钥 + 随机。按照设计,每次执行代码时,盐和派生密钥都应不同

尝试多次执行上述代码,确认派生密钥保持相同(因为盐固定),而派生出的 argon2 哈希每次执行都不同(因为算法内部会生成随机盐)。

尝试修改 time_costmemory_cost 设置,观察它们如何影响密钥派生的执行时间

将算法设置 + 盐 + 哈希一同存储

在许多应用、框架和工具中,Argon2 密码哈希会与算法设置和盐一同存储在一个具有特定格式(如上所示)的字符串中。该字符串由多个部分组成,以 $ 字符分隔。例如,密码 p@ss~123 可以按如下 Argon2 标准格式存储(这里给出多个示例,以便看清其模式):

$argon2d$v=19$m=1024,t=16,p=4$c2FsdDEyM3NhbHQxMjM$2dVtFVPCezhvjtyu2PaeXOeBR+RUZ6SqhtD/+QF4F1o
$argon2d$v=19$m=1024,t=16,p=4$YW5vdGhlcnNhbHRhbm90aGVyc2FsdA$KB7Nj7kK21YdGeEBQy7R3vKkYCz1cdR/I3QcArMhl/Q
$argon2i$v=19$m=8192,t=32,p=1$c21hbGxzYWx0$lmO1aPPy3x0CcvrKpFLi1TL/uSVJ/eO5hPHiWZFaWvY

上述所有哈希都对应同一个密码,但算法设置和盐各不相同。

何时使用 Argon2?

正确配置时,Argon2 被认为是一种高度安全的 KDF 函数,也是业界可用的最佳选择之一。因此,可以把它用作通用的基于密码的密钥派生算法,例如用于加密钱包、文档、文件或应用密码。一般情况下,推荐使用 Argon2,而非 ScryptBcryptPBKDF2

results matching ""

    No results matching ""