random32_unbiased 函数如何在 Monero 的 Schnorr 签名算法中工作

问题描述

Zero to Monero book 中,我正在阅读 Schnorr signatures。第 2.3.4 节引用了 src/crypto/crypto.cppcodebase 中的 random32_unbiased() 函数。我的理解是这个函数生成一个介于 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,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(爱德华兹数字签名),以在 Monero 区块链上创建交易。

edwards25519 是复合阶曲线,也就是说,它不是像比特币使用的secp256k1那样的素阶曲线。

由于这个事实,在加密上下文中,我们必须在曲线的素数阶子群中工作,因此出于安全原因,我们的群是素数。

门罗币的那个子群比实际曲线的阶数小约 8 倍!因此子组大小为l,即2^252 + 27742317777372353535851937790883648493

因此,门罗币只能有 2^252 + 27742317777372353535851937790883648493 个有效的公钥,或者其他任何使用 edwards25519 的公钥

正如 James K. Polk 指出的那样,我们希望确保我们留在循环子群中,但不会在关键材料中引入偏差。

有趣的是,我将 l 放入 sagemath 中,将其乘以 15,结果确实适合 256 位。

255.906890595609 准确地说,16 次需要 256.000000000000000000000000000000000000005 位。数学哟。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...