yescrypt 中的 j9T 是什么意思(来自 /etc/shadow)?

kel*_*aka 4 encryption shadow

考虑这个阴影字符串

$y$j9T$PaFEMV0mbpeadmHDv0Lp31$G/LliR3MqgdjEBcFC1E.s/3vlRofsZ0Wn5JyZHXAol5
Run Code Online (Sandbox Code Playgroud)

有4部分

  • id : y (yescrypt)
  • 参数:j9T
  • 盐:PaFEMV0mbpeadmHDv0Lp31
  • 哈希:G/LliR3MqgdjEBcFC1E.s/3vlRofsZ0Wn5JyZHXAol5

问:

  1. j9Tparam 字段中的含义是什么?
  2. 该领域还有其他选择吗?
  3. 我们在哪里可以找到官方文档?

我见过这个问题;然而,加密密码的格式/etc/shadow,那里没有解释。

NUL*_*LLx 10

免责声明

以下是我自己的发现以及我在没有对密码学和所涉及的概念有专业了解的情况下解释它们的方式。

签名

值得注意的是,正如OpenWall GitHub 上的yescrypt CHANGES文件所述,关于0.8.1 (2015/10/25) 和 1.0.0 (2018/03/09) 之间所做的更改yescrypt有两个签名

  • $7$- 经典scrypt哈希,不是很紧凑的定长编码
  • $y$- 原生yescrypt和经典scrypt哈希,新的极其紧凑的可变长度编码

这种极其紧凑的可变长度编码引入了UNIX StackExchange 答案中倒数第二段末尾所讨论的大部分复杂性,但不是全部复杂性。

参数

对于参数的简单描述,BitcoinWiki Yescrypt 参数部分可能会有所帮助:

范围 描述
password 密码哈希
salt 使用盐
flags 切换功能的标志
N 增加 N 会增加运行时间和内存使用
r 增加 R 会增加算法操作的块的大小(从而增加内存使用)
p 并行系数
t 增加 T 会增加运行时间而不增加内存使用
g 哈希值“升级”的次数,用于加强存储的密码哈希值,而不需要知道原始密码
NROM 结果密钥将依赖的只读存储器
DKLen 导出密钥的长度(输出)

格式

其中,$7$哈希仅使用以下内容:

  • N- 用1个字节(字符)编码
  • r- 用5个字节(字符)编码
  • p- 用5个字节(字符)编码

由于$7$也意味着固定长度编码,每个参数都有预先指定的字节数对其进行编码,并且每个参数都按顺序排列:$7$Nrrrrrppppp$...。$

让我们将每个字节括在[]方括号中:$7$[N][r1][r2][r3][r4][r5][p1][p2][p3][p4][p5]$... $。此外,这意味着 11 是指定序列中的参数所需的确切字节数(因此它不紧凑)。

另一方面,$y$哈希值需要三个参数:

  • flags- 至少使用 1 个字节(字符)进行编码
  • N- 至少使用 1 个字节(字符)进行编码
  • r- 至少使用 1 个字节(字符)进行编码

尽管如此,哈希仍然可以通过使用可变长度$y$编码来使用所有参数。实际上,这意味着每个参数都以自己的大小为前缀#编码在第一个字节中,并以#个字节继续:

$y$[flags_len=#][flags1]…………[flags#][N_len=#][N1][N#][r_len=#][r1]$$

为了使事情变得更加复杂,强制参数后面跟着一个可选have参数。根据 的值haveyescrypt决定、 、和中的哪些p(如果有的话)也是所提供数据的一部分。tgNROM

有关参数以及在什么情况下使用哪些参数的综合指南,最好查阅OpenWall GitHub 上的yescrypt PARAMETERS文件。

编码

参数字段的解码是通过 完成的decode64_uint32(),它使用一个数组,该数组以当前字节的 ASCII 值与句点字符 (46) 之间的差值为索引,该值是基数:atoi64().

atoi64_partial[77] = {
  0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
  64, 64, 64, 64, 64, 64, 64,
  12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
  25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
  64, 64, 64, 64, 64, 64,
  38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
  51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63
};
Run Code Online (Sandbox Code Playgroud)

对于每个字段,从第一个字段字节开始yescrypt执行以下操作:

  1. 如上所述,使用第一个字段字节来索引数组。
  2. 使用数组项执行计算以获得字段的部分值
  3. 对数组项执行计算,以获得对字段值的其余部分进行编码的后续字节数。
  4. 对于每个下一个字节,算法使用它再次索引数组添加数据以达到最终的字段值。

BitcoinWiki Yescrypt 函数部分中有一些其他进程的伪代码。

演示参数编码

让我们从PARAMETERS上面的文件中举一个例子:

  • flags = YESCRYPT_DEFAULTS
  • N = 4096
  • r = 32
  • p = 1
  • t = 0
  • g = 0
  • NROM = 0

上述值集被描述为密码散列的标准且慢(内存使用量 16 MiB,性能如 bcrypt 成本 2^8 - 延迟 10-30 毫秒,吞吐量在 16 核服务器上每秒 1000+用户认证,无ROM

$y$是签名。

flags = YESCRYPT_DEFAULT = 182 = 0xB6 = jyescrypt可变长度编码中。

这里,flags应该解码为YESCRYPT_DEFAULT,这相当于YESCRYPT_RW_DEFAULTS,定义为(YESCRYPT_RW | YESCRYPT_ROUNDS_6 | YESCRYPT_GATHER_4 | YESCRYPT_SIMPLE_2 | YESCRYPT_SBOX_12K)

  • YESCRYPT_RW = 0x002
  • YESCRYPT_ROUNDS_6 = 0x004
  • YESCRYPT_GATHER_4 = 0x010
  • YESCRYPT_SIMPLE_2 = 0x020
  • YESCRYPT_SBOX_12K = 0x080

执行逻辑OR运算,yescrypt得出最终数字并对其进行编码。

N = 4096 = 0x1000 = 9yescrypt可变长度编码中。事实上,N = 2解码_N_字段

r = 32 = 0x20 = Tyescrypt可变长度编码中。

$此时表明yescript没有指定可选参数。

最后,加入盐。理论上它是任意长度的。但是,盐的长度必须是 4 的幂

$y$j9T$SALT$

例子

以下是一些有效但不安全的示例,在完成上述描述后可能会在视觉上有所帮助:

  • $7$9/..../..../$SALTS$
  • $y$./.$SALT$
  • $y$8/.$SALT$