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。我的理解是这个函数生成一个介于 1l-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 位。数学哟.