Solution: bip39
and node-forge
As stated in this insightful answer, the key to achieving this solution lies in understanding the nature of public keys and their vulnerability to offline attacks through dictionary search.
The resulting public key is inherently public, making it susceptible to offline dictionary attacks where possible passwords are attempted until a match is found. This risk is inherent to the desired outcome.
It is recommended that we aim for at least 128 bits of entropy to fend off such attacks in the future, but ultimately, the strength of our mnemonic passphrase is within our control.
1. Generating Mnemonic Passphrase
To begin, we can create a secure mnemonic using the JavaScript implementation of bip-39
.
import { generateMnemonic } from "bip39";
const mnemonic = generateMnemonic(256) // Opting for 256 bits for maximum security. Default is 128 bits.
console.log(mnemonic) // Outputs 24 unique words
2. Developing Deterministic PRNG Function
Next, utilize node-forge
to generate our encryption keys.
The pki.rsa.generateKeyPair
function requires a pseudo-random number generator. Our aim is to make this function produce values derived deterministically from the mnemonic, rather than pure randomness.
import { mnemonicToSeed } from "bip39";
import { pki, random } from "node-forge";
const seed = (await mnemonicToSeed(mnemonic)).toString('hex')
const prng = random.createInstance();
prng.seedFileSync = () => seed
3. Key Pair Generation
We can now use the generateKeyPair
function with our modified pseudo-random number generator:
const { privateKey, publicKey } = pki.rsa.generateKeyPair({ bits: 4096, prng, workers: 2 })
And there you have it!
With these steps, we have successfully created secure and deterministic RSA keys directly on the client side, all restorable using the same mnemonic passphrase as input.
However, be cautious of the risks associated with deterministic keys, ensuring that users do not store their mnemonic online or anywhere easily accessible. It is generally advised to keep a written copy stored in a secure location.