random32_unbiased 函数如何在 Monero 的 Schnorr 签名算法中工作
How random32_unbiased function works in Monero's Schnorr signiture algorithm
在Zero to Monero book, I am reading about Schnorr signatures. Section 2.3.4 references the random32_unbiased()
function from src/crypto/crypto.cpp
of the codebase。我的理解是这个函数生成一个介于 1
和 l-1
之间的随机整数(包括两者),其中 l
是一个大整数。
那个函数是:
void random32_unbiased(unsigned char *bytes)
{
// l = 2^252 + 27742317777372353535851937790883648493.
// l fits 15 times in 32 bytes (iow, 15 l is the highest multiple of l that fits in 32 bytes)
static const unsigned char limit[32] = { 0xe3, 0x6a, 0x67, 0x72, 0x8b, 0xce, 0x13, 0x29, 0x8f, 0x30, 0x82, 0x8c, 0x0b, 0xa4, 0x10, 0x39, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0 };
while(1)
{
generate_random_bytes_thread_safe(32, bytes);
if (!less32(bytes, limit))
continue;
sc_reduce32(bytes);
if (sc_isnonzero(bytes))
break;
}
}
带static const unsigned char limit[32]
的那一行有什么用?
我的主要问题是上面那个,但总的来说,我对函数的工作原理不是很了解,所以也希望能解释一下。
Monero 使用 edwards25519
作为基础椭圆曲线,用于生成 EdDSA
(Edwards 数字签名),在 Monero 区块链上创建交易。
edwards25519
是复合阶曲线,即不是比特币使用的secp256k1
那样的素数阶曲线。
由于这个事实,在加密上下文中,我们必须以曲线的素数顺序 子组 工作,因此出于安全原因,我们的组是素数。
Monero 的子组比实际曲线的阶数小 ~8 倍!因此,子组大小为 l
,即 2^252 + 27742317777372353535851937790883648493
因此,Monero 或任何其他使用 edwards25519
的密钥只能有 2^252 + 27742317777372353535851937790883648493
个有效的 public 密钥
正如 James K. Polk 指出的那样,我们希望确保我们留在循环子群中,但不会在密钥中引入偏差 material。
有趣的是,我将 l
卡在 sagemath 中,将其乘以 15,确实它适合 256 位。
255.906890595609
准确地说,16 次需要 256.000000000000000000000000000000000000005
位。数学哟.
在Zero to Monero book, I am reading about Schnorr signatures. Section 2.3.4 references the random32_unbiased()
function from src/crypto/crypto.cpp
of the codebase。我的理解是这个函数生成一个介于 1
和 l-1
之间的随机整数(包括两者),其中 l
是一个大整数。
那个函数是:
void random32_unbiased(unsigned char *bytes)
{
// l = 2^252 + 27742317777372353535851937790883648493.
// l fits 15 times in 32 bytes (iow, 15 l is the highest multiple of l that fits in 32 bytes)
static const unsigned char limit[32] = { 0xe3, 0x6a, 0x67, 0x72, 0x8b, 0xce, 0x13, 0x29, 0x8f, 0x30, 0x82, 0x8c, 0x0b, 0xa4, 0x10, 0x39, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0 };
while(1)
{
generate_random_bytes_thread_safe(32, bytes);
if (!less32(bytes, limit))
continue;
sc_reduce32(bytes);
if (sc_isnonzero(bytes))
break;
}
}
带static const unsigned char limit[32]
的那一行有什么用?
我的主要问题是上面那个,但总的来说,我对函数的工作原理不是很了解,所以也希望能解释一下。
Monero 使用 edwards25519
作为基础椭圆曲线,用于生成 EdDSA
(Edwards 数字签名),在 Monero 区块链上创建交易。
edwards25519
是复合阶曲线,即不是比特币使用的secp256k1
那样的素数阶曲线。
由于这个事实,在加密上下文中,我们必须以曲线的素数顺序 子组 工作,因此出于安全原因,我们的组是素数。
Monero 的子组比实际曲线的阶数小 ~8 倍!因此,子组大小为 l
,即 2^252 + 27742317777372353535851937790883648493
因此,Monero 或任何其他使用 edwards25519
2^252 + 27742317777372353535851937790883648493
个有效的 public 密钥
正如 James K. Polk 指出的那样,我们希望确保我们留在循环子群中,但不会在密钥中引入偏差 material。
有趣的是,我将 l
卡在 sagemath 中,将其乘以 15,确实它适合 256 位。
255.906890595609
准确地说,16 次需要 256.000000000000000000000000000000000000005
位。数学哟.