如何使用种子确定性地生成安全的 RSA 密钥?

Lui*_*ñez 5 javascript rsa deterministic encryption-asymmetric typescript

我们如何使用助记词列表作为种子(就像我们已经习惯使用加密货币钱包一样),以便能够在私钥丢失、意外删除或卡在损坏的设备上时恢复私钥?

这对于客户端之间的 e2e 加密很有用:密钥应该在客户端上生成,只有公钥会与服务器共享。

用户可以在需要时离线重新生成密钥,只要他们能够再次提供助记词,显然可以安全地离线存储。

助记词种子应该足够长,以提供安全量的熵。

一些问答似乎非常过时:我们如何在 Javascript/Typescript 中实现这一点,可能使用维护的库?

Lui*_*ñez 11

解决方案:bip39node-forge

\n

引用这个答案我实现这个解决方案的答案:

\n
\n

在这种情况下,生成的公钥本质上是公开的,因此可以用于离线字典攻击。攻击者只需尝试可能的密码,直到找到相同的公钥。这就是您想要实现的目标的本质。

\n
\n

我们可以假设128 位的熵应该足够了防止此类攻击,但幸运的是,我们可以决定助记词的强度。

\n

1.生成助记词

\n

首先,我们可以使用以下命令生成助记词bip-39JS实现生成助记词。

\n
import { generateMnemonic } from "bip39";\n\nconst mnemonic = generateMnemonic(256) // 256 to be on the _really safe_ side. Default is 128 bit.\n\nconsole.log(mnemonic) // prints 24 words\n
Run Code Online (Sandbox Code Playgroud)\n

2. 创建确定性 PRNG 函数

\n

现在我们可以使用node-forge它来生成密钥。\n该pki.rsa.generateKeyPair函数在输入中接受伪随机数生成器函数。目标是让这个函数不计算伪随机数(这不再是确定性的),而是返回根据助记符计算的值计算的值。

\n
import { mnemonicToSeed } from "bip39";\nimport { pki, random } from "node-forge";\n\nconst seed = (await mnemonicToSeed(mnemonic)).toString(\'hex\')\n\nconst prng = random.createInstance();\nprng.seedFileSync = () => seed\n
Run Code Online (Sandbox Code Playgroud)\n

3. 生成密钥对

\n

我们现在可以喂generateKeyPair使用我们的“操纵”prng 来提供该函数:

\n
const { privateKey, publicKey } = pki.rsa.generateKeyPair({ bits: 4096, prng, workers: 2 })\n
Run Code Online (Sandbox Code Playgroud)\n

等瞧\xc3\xa0!

\n

我们现在拥有安全且确定性的 RSA 密钥,直接在客户端生成,并且可以使用与输入相同的助记符进行恢复。\n请考虑使用确定性密钥所涉及的风险,并确保您的用户不会或客户端上的其他任何地方存储助记词(一般情况下,建议将其写在纸上并存放在安全的地方)。

\n