有没有办法使用 [u8; 64]阵列?
Is there a way to seed a cryptographically secure RNG engine in rust using a [u8; 64] array?
原始问题:
我目前正在尝试用 Rust 编写一个库 - 将被编译为 WASM - 用于将 bip39 助记密码短语转换为 Arweave JWK。我目前正在使用 tiny-bip39 and RSA.
根据 RSA I want to seed the rng based on the mnemonic passphrase I have passed into the function. I tried achieving this by simply getting the seed from the mnemonic object generated by tiny-bip39 中给出的示例使用 RSA 生成私钥时,这似乎生成了长度为 64
的 &[u8]
。但是,Seed 被定义为 [u8; 32]
,而不必编写自己的 rng,我无法弄清楚如何使用 len 64
种子。
#[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);
[...]
}
是否有允许 len 64
种子的加密安全 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 中重现它。到目前为止,我已经尝试使用 ChaCha8Rng
、ChaCha12Rng
、ChaCha20Rng
和 Pcg64
、none,它们产生了想要的结果。
这取决于 CSPRNG。如果您使用 HMAC-SHA-512 为 HMAC DRBG 播种,那么这将是一个完全正常的输入量。但是,在您的情况下,CSPRNG 是 ChaCha,它被配置为具有 256 位密钥。
如果这个助记词是由CSPRNG生成的,并且有足够的熵,那么你只需要一个像HKDF这样简单明了的密钥推导函数。您可以将 HKDF 与 SHA-256 或 SHA-512 一起使用,种子作为输入键控 material,无盐,输出键控 material 大小为 32 字节。然后,您可以使用它来播种您的 CSPRNG。
您还需要一个信息字符串,通常是一些文本字符串。我喜欢使用版本号来证明未来,因此您可以使用“v1 PRNG seed”之类的东西。
我的建议是,由于您有一个 64 字节的输入种子,因此使用 SHA-512 的 HKDF 是最好的,因为它可以避免在您最终需要为其他数据播种时丢失熵。此外,虽然 ChaCha12Rng 是默认值,但 ChaCha20Rng 更为保守,可能适合生成长期密钥。
原始问题:
我目前正在尝试用 Rust 编写一个库 - 将被编译为 WASM - 用于将 bip39 助记密码短语转换为 Arweave JWK。我目前正在使用 tiny-bip39 and RSA.
根据 RSA I want to seed the rng based on the mnemonic passphrase I have passed into the function. I tried achieving this by simply getting the seed from the mnemonic object generated by tiny-bip39 中给出的示例使用 RSA 生成私钥时,这似乎生成了长度为 64
的 &[u8]
。但是,Seed 被定义为 [u8; 32]
,而不必编写自己的 rng,我无法弄清楚如何使用 len 64
种子。
#[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);
[...]
}
是否有允许 len 64
种子的加密安全 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 中重现它。到目前为止,我已经尝试使用 ChaCha8Rng
、ChaCha12Rng
、ChaCha20Rng
和 Pcg64
、none,它们产生了想要的结果。
这取决于 CSPRNG。如果您使用 HMAC-SHA-512 为 HMAC DRBG 播种,那么这将是一个完全正常的输入量。但是,在您的情况下,CSPRNG 是 ChaCha,它被配置为具有 256 位密钥。
如果这个助记词是由CSPRNG生成的,并且有足够的熵,那么你只需要一个像HKDF这样简单明了的密钥推导函数。您可以将 HKDF 与 SHA-256 或 SHA-512 一起使用,种子作为输入键控 material,无盐,输出键控 material 大小为 32 字节。然后,您可以使用它来播种您的 CSPRNG。
您还需要一个信息字符串,通常是一些文本字符串。我喜欢使用版本号来证明未来,因此您可以使用“v1 PRNG seed”之类的东西。
我的建议是,由于您有一个 64 字节的输入种子,因此使用 SHA-512 的 HKDF 是最好的,因为它可以避免在您最终需要为其他数据播种时丢失熵。此外,虽然 ChaCha12Rng 是默认值,但 ChaCha20Rng 更为保守,可能适合生成长期密钥。