原题:
我目前正在尝试用rust编写一个库-要编译为WASM -用于将bip39助记符密码短语转换为Arweave JWK。我目前使用的是tiny-bip39和RSA。
当根据RSA给出的示例使用RSA生成私钥时,我想根据我传递给函数的助记密码短语来播种rng。我试图通过简单地从由tiny-bip39生成的助记符对象中获取种子来实现这一点,但是这似乎生成了一个64
长度的&[u8]
。但是,Seed被定义为[u8; 32]
,如果不编写自己的rng,我就不知道如何使用len64
Seed。
#[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
种子的加密安全环?
我试着简单地尝试进入,但似乎没有工作,这是有道理的。
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-助记键提供的一些功能时,我已经尝试过了所有的依赖关系,找出我需要的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
,没有一个产生想要的结果。
这取决于CSPRNG。如果您使用HMAC- sha -512播种HMAC DRBG,那么这将是一个完全正常的输入量。但是,在您的示例中,CSPRNG是ChaCha,它被配置为具有256位密钥。
如果这个助记符是由CSPRNG生成的,并且有足够的熵,那么你所需要的就是一个简单、直接的密钥派生函数,比如HKDF。您可以将HKDF与SHA-256或SHA-512一起使用,以种子作为输入键控材料,无盐,输出键控材料大小为32字节。然后,您可以使用它来播种您的CSPRNG。
您还需要一个info字符串,通常是用于此目的的一些文本字符串。我喜欢使用版本号来保证将来不会出错,所以你可以使用"v1 PRNG种子"之类的东西。
我的建议是,既然你有一个64字节的输入种子,那么使用SHA-512的HKDF是最好的,因为如果你最终需要播种其他数据,它可以避免失去熵。此外,虽然ChaCha12Rng是默认值,但ChaCha20Rng更为保守,可能更适合生成长期密钥。