Libsodium 在BLAKE2b之上构建他们的KDF:
BLAKE2B-subkeylen(key=key, message={}, salt=subkey_id || {0}, personal=ctx || {0})除了键外,函数还有两个附加参数:子键ID (一个8字节值,它是0填充的,成为salt)和个性化上下文。他们将这两个值记录如下:
subkey_id可以是最多(2^64)-1的任何值。
和:
类似于一种类型,上下文ctx是一个描述键将用于什么的8个字符字符串。它的目的是通过分离域来减少意外的错误。使用相同键的相同函数,但在两个不同的上下文中,可能会生成两个不同的输出。上下文不一定是秘密的,可以有一个低熵。
如果我正确理解了这一点,8字节子键ID (它变成16字节盐)和8字节ctx (成为16字节个性化)都被用于“命名空间”,不必是秘密的,而且可能是低熵的。
在BLAKE2b中,salt和个性化上下文之间有什么区别?个性化语境是否可以被认为是“盐的第二部分”,仅为语义目的而引入?如果是的话,使用一个32字节的盐不是更容易理解,更容易实现错误吗?
发布于 2020-01-24 09:24:34
对于一个“keystore”,上下文应该是常量:这是KDF的属性,用于名称空间的盐空间,并确保两个不同的应用程序(或keystore)不会重用相同的盐分。
但是,对于给定密钥存储区中的每个密钥,Subkey_id需要不同,而且它不用于命名空间。但是,对于给定的子键ID,它可以是常量(即使未散列数据发生了更改)。
如果要确保不同的应用程序可以安全地生成唯一的salt值,而不必执行完整的扫描,则需要的目的是:如果每个应用程序都有自己的上下文,那么它们就可以使用一个简单的计数器来处理子键ID。
发布于 2023-03-28 18:21:38
我知道这是个老问题,但我也有同样的问题,经过一番探索,我想找到了答案,所以我想分享一下:
salt和个性化contex之间的区别确实可以被认为是纯语义的。
看一下利伯钠的实现,我们简单地将所有参数xor到初始化向量中,这就构成了散列轮的基础。
blake2b_init_param(blake2b_state *S, const blake2b_param *P)
{
size_t i;
const uint8_t *p;
blake2b_init0(S);
p = (const uint8_t *) (P);
/* IV XOR ParamBlock */
for (i = 0; i < 8; i++) {
S->h[i] ^= LOAD64_LE(p + sizeof(S->h[i]) * i); // <- here
}
return 0;
}还可以看看我们拥有的blake2b_param 定义:
typedef struct blake2b_param_ {
uint8_t digest_length; /* 1 */
uint8_t key_length; /* 2 */
...
uint8_t salt[BLAKE2B_SALTBYTES]; /* 48 */
uint8_t personal[BLAKE2B_PERSONALBYTES]; /* 64 */
} blake2b_param;因为这是一种加密哈希算法,如果它的初始化参数发生了单比特的变化,那么整个输出就会发生根本无法追溯的变化。
因此,在实践中,盐、个性化、甚至(我认为?)没有区别。传递到算法中的初始键。所有的东西都被消化成一个精细的、不可追踪的二进制粘贴:)
希望这能有所帮助!
https://crypto.stackexchange.com/questions/77193
复制相似问题