首页 > 解决方案 > 有没有办法使用 [u8; 64]数组?

问题描述

原始问题:

我目前正在尝试用 rust 编写一个库 - 将其编译为 WASM - 用于将 bip39 助记密码短语转换为 Arweave JWK。我目前正在使用tiny-bip39RSA

根据RSA上给出的示例使用 RSA 生成私钥时,我想根据我传递给函数的助记密码来播种 rng。我尝试通过简单地从tiny-bip39生成的助记符对象中获取种子来实现这一点,但这似乎生成了&[u8]一个长度为64. 但是,Seed 被定义为[u8; 32],并且无需编写自己的 rng,我无法弄清楚如何使用 len64种子。

#[wasm_bindgen]
pub fn get_key_from_mnemonic(phrase: &str) {
    let mnemonic = Mnemonic::from_phrase(phrase, Language::English).unwrap();

    assert_eq!(phrase, mnemonic.phrase());

    let seed = Seed::new(&mnemonic, "");
    let seed_bytes = seed.as_bytes();

    let mut rng = ChaCha12Rng::from_seed(seed_bytes);

    [...]
}

是否有允许 len64种子的加密安全 rng?

我试着简单地尝试,但这似乎不起作用,这是有道理的。

let seed_bytes: <ChaCha12Rng as SeedableRng>::Seed = seed.as_bytes().try_into().unwrap();

编辑:

我想出了一个解决方案,除了随机数生成之外,它似乎在各个方面都有效。

    let mnemonic = Mnemonic::from_phrase(phrase, Language::English).unwrap();

    assert_eq!(phrase, mnemonic.phrase());

    let seed = Seed::new(&mnemonic, "");
    let seed_bytes = seed.as_bytes();
    let mut seed_buf: [u8; 32] = Default::default();

    let mut hmac_drgb = HmacDRBG::<Sha256>::new(&seed_bytes, &[], &[]);
    hmac_drgb.generate_to_slice(&mut seed_buf, None);

    let mut chacha = ChaCha20Rng::from_seed(seed_buf);

    let modulus_length = 4098;
    let rsa_private_key = RsaPrivateKey::new(&mut chacha, modulus_length).unwrap();

    let der = rsa_private_key.to_pkcs1_der().unwrap();

    let jwk = JWK {
        modulus: der.private_key().modulus.as_bytes().to_vec(),
        public_exponent: der.private_key().public_exponent.as_bytes().to_vec(),
        private_exponent: der.private_key().private_exponent.as_bytes().to_vec(),
        prime1: der.private_key().prime1.as_bytes().to_vec(),
        prime2: der.private_key().prime2.as_bytes().to_vec(),
        exponent1: der.private_key().exponent1.as_bytes().to_vec(),
        exponent2: der.private_key().exponent2.as_bytes().to_vec(),
        coefficient: der.private_key().coefficient.as_bytes().to_vec(),
    };

当我试图重写arweave-mnemonic-keys提供的一些功能时,我试图通过所有依赖项,找出我需要哪些 rust 模块,并认为我已经设法弄清楚除了如何生成之外的所有内容RSA算法的随机数。

我试过浏览 node-forge/lib/rsa.js 文件,发现了这个片段:

function generateRandom(bits, rng) {
      var num = new BigInteger(bits, rng);
      // force MSB set
      var bits1 = bits - 1;
      if(!num.testBit(bits1)) {
        num.bitwiseTo(BigInteger.ONE.shiftLeft(bits1), op_or, num);
      }
      // align number on 30k+1 boundary
      num.dAddOffset(31 - num.mod(THIRTY).byteValue(), 0);
      return num;
}

但是,我不确定如何在 rust 中重现它。到目前为止,我已经尝试使用ChaCha8RngChaCha12RngChaCha20RngPcg64,它们都没有产生想要的结果。

标签: randomrustcryptographyrsawebassembly

解决方案


这取决于 CSPRNG。如果您使用 HMAC-SHA-512 播种 HMAC DRBG,那么这将是一个完全正常的输入量。但是,在您的情况下,CSPRNG 是 ChaCha,它被配置为具有 256 位密钥。

如果这个助记词是从 CSPRNG 生成的并且具有足够的熵,那么您所需要的只是一个简单、直接的密钥派生函数,如 HKDF。您可以将HKDF与 SHA-256 或 SHA-512 一起使用,种子作为输入密钥材料,无盐,输出密钥材料大小为 32 字节。然后,您可以使用它来播种您的 CSPRNG。

您还需要一个信息字符串,通常是一些用于此目的的文本字符串。我喜欢使用版本号来保证未来的发展,因此您可以使用“v1 PRNG 种子”之类的东西。

我在这里的建议是,由于您有一个 64 字节的输入种子,因此使用 SHA-512 的 HKDF 是最好的,因为如果您最终需要为其他数据播种,它可以避免丢失熵。此外,虽然 ChaCha12Rng 是默认设置,但 ChaCha20Rng 更保守,可能适合生成长期密钥。


推荐阅读