考虑这个阴影字符串
$y$j9T$PaFEMV0mbpeadmHDv0Lp31$G/LliR3MqgdjEBcFC1E.s/3vlRofsZ0Wn5JyZHXAol5
有4部分
- id : y (yescrypt)
- 参数:j9T
- 盐:PaFEMV0mbpeadmHDv0Lp31
- 哈希:G/LliR3MqgdjEBcFC1E.s/3vlRofsZ0Wn5JyZHXAol5
问:
j9T
param 字段中的含义是什么?- 该领域还有其他选择吗?
- 我们在哪里可以找到官方文档?
我见过这个问题;加密密码的格式为/etc/shadow
但是,那里没有任何解释。
答案1
免责声明
以下是我自己的发现以及我在没有对密码学和所涉及的概念有专业了解的情况下解释它们的方式。
签名
值得注意的是,作为yescrypt
CHANGES
文件在 OpenWall GitHub 上有关于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
范围。根据 的值have
,是的密码决定其中,如果有的话、p
、t
和g
也是NROM
所提供数据的一部分。
有关参数以及在什么情况下使用哪些参数的综合指南,最好咨询yescrypt
PARAMETERS
文件在 OpenWall GitHub 上。
编码
解码参数字段是通过decode64_uint32()
,它使用大批,索引经过atoi64()
.
当前字节的 ASCII 值与作为基数的句点字符 (46)之间的差值:
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
};
对于每个字段,从第一个字段字节开始yescrypt
执行以下操作:
- 使用第一个字段字节索引数组如上所述。
- 对数组项进行计算,得到字段的部分值。
- 对数组项进行计算,得到后续字节数对字段值的其余部分进行编码。
- 对于每个下一个字节,该算法使用它来再次索引数组和添加数据达到最终的字段值。
有一些其他进程的伪代码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 = j
在yescrypt
变长编码。
这里,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 = 9
在yescrypt
变长编码。实际上,N = 2解码_N_字段。
r = 32 = 0x20 = T
在yescrypt
变长编码。
$
此时表明yescript
没有指定可选参数。
最后,盐被添加。理论上它是任意长度的。然而,盐的长度必须是 4 的幂。
$y$j9T$SALT$
例子
以下是一些有效但不安全的示例,在完成上述描述后可能会在视觉上有所帮助:
$7$9/..../..../$SALTS$
$y$./.$SALT$
$y$8/.$SALT$