1.2.1 • Published 6 months ago

mnemonic-backup v1.2.1

Weekly downloads
-
License
MIT
Repository
gitlab
Last release
6 months ago

Mnemonic Backup

NPM Version NPM License NPM Unpacked Size

A mnemonic solution for backup/recovery codes.

Mnemonic Backup is an implementation of 14-word Mnemonic Backup Phrases. These backup phrases are intended for use as a more user-friendly/memorable alternative to traditional backup/recovery codes. The primary functionality of this library concerns the encryption of mnemonics, using keys derived from the same mnemonics via deterministic functions. In an implementation such as part of a user account system, backup phrases can be used to verify account ownership by using a backup phrase to decrypt a matching phrase from cyphertext associated with the account.

To get started, install the library:

npm install mnemonic-backup

This library consists of five functions: generateMnemonic, generateKey, prepareKey, encryptMnemonic, and decryptMnemonic. These functions are used in the creation of mnemonic phrases, cryptographic keys, and for the encryption and decryption of Mnemonic Backup Phrases.

Mnemonic Phrase Generation

The Mnemonic Phrase is generated using the generateMnemonic function, where 11-bit segments of provided or internally generated entropy are used to create a mnemonic, using words from the BIP39 English wordlist, provided by @iacobus/bip39.

generateMnemonic(entropy);

This function expects a single optional entropy parameter, expecting 154 bits of entropy directly as bits when provided. This function acts as a proxy to the mnemonic(); function of the mnemonic-key library. If no entropy is provided, the library will internally generate entropy.

Example use with "entropy" provided:

const { generateMnemonic } = require('mnemonic-backup');

// 176 Bits of entropy in Hex
const entropy = "596F75206A757374206C6F7374205468652047616D65";

const mnemonic = generateMnemonic(entropy);
console.log("Mnemonic Phrase:", mnemonic);

// Sample Output:
// Mnemonic Phrase: floor knife elite stay fire ring like mistake inflict patient bench speak faith carbon

The function returns a 14-word Mnemonic Phrase derived from the generated or provided entropy in the output.

Obtaining a Cryptographic Key

Generating a Key

A Cryptographic Key is derived from the Mnemonic Phrase using the getKey(); function of the mnemonic-key library, which the generateKey(); function acts as a proxy to. Keys are obtained from mnemonics using the PBKDF2 (Password-Based Key Derivation Function 2) synchronous key derivation function.

Using the generateKey function.

To generate the Cryptographic Key, the generateKey function is used.

generateKey(mnemonic, iterations);

This function expects a mnemonic parameter, which should be the Mnemonic Phrase. An optional iterations parameter may also be provided, allowing the number of iterations to be specified. If no number is provided, a default of 210,000 will be used, based on the OWASP recommendations for PBKDF2-HMAC-SHA512.

Example use without "iterations" provided:

const { generateKey } = require('mnemonic-backup');

// 14 Word Mnemonic Phrase
const mnemonic = "floor knife elite stay fire ring like mistake inflict patient bench speak faith carbon";

generateKey(mnemonic)
    .then((key) => {
        console.log("Cryptographic Key:", key);
    });

// Sample Output:
// Cryptographic Key: 5581d8bf77f333b1ec6c6b1ba28abbdd7a9d3c7d3857c99ae1cac47ee1734bc0

The function returns a Cryptographic Key derived from the provided Mnemonic Phrase in the output.

Preparing a Key

The Cryptographic Key is prepared with salting and peppering, using the PBKDF2 synchronous key derivation function.

crypto.pbkdf2Sync(password, salt, iterations, keylen, digest);

Here, the Cryptographic Key is peppered and supplied as the password. A Buffer of a salt is provided as salt, a number of iterations is provided, the requested byte length of the key (keylen) is set to 32, and the digest is set to SHA256.

Using the prepareKey function

To prepare a Cryptographic Key, the prepareKey function is used.

prepareKey(key, pepper, salt, iterations);

This function expects a key parameter, which should be the Cryptographic Key. A pepper and a salt parameter are expected, provided for peppering and salting the key. An optional iterations parameter may also be provided, allowing the number of iterations to be specified. If no number is provided, a default of 600,000 will be used, based on the OWASP recommendations for PBKDF2-HMAC-SHA256.

Example use with "iterations" provided:

const { prepareKey } = require('mnemonic-backup');

// Cryptographic Key
const key = "5581d8bf77f333b1ec6c6b1ba28abbdd7a9d3c7d3857c99ae1cac47ee1734bc0"

// Pepper and Salt
const pepper = "57686174206973207468652074727574683F20"
const salt = "4E6F7468696E67204D617474657273203A29";

// Iterations set to 750,000
const iterations = 750000;

const preparedKey = prepareKey(key, pepper, salt, iterations);
console.log("Prepared Key:", preparedKey);

// Sample Output:
// Prepared Key: 773b371566d8ebbc57d9d9ce581e6fcd13d3d57f617d366fcfebd2937f8a05da

The function returns the prepared cryptographic key in the output.

Encrypting the Mnemonic Phrase

A cypher is created by encrypting the Mnemonic Phrase with AES (Advanced Encryption Standard) at a length of 256 bits using GCM (Galois/Counter Mode).

crypto.createCipheriv(algorithm, key, iv[, options]);

In this setup, the algorithm is aes-256-gcm, with the key being a Buffer of a provided cryptographic key. A Buffer of an Initialization Vector (iv) is also provided. The Mnemonic Phrase is then encrypted using .update(mnemonic, 'utf8', 'hex');, and an Authentication Tag is returned with .getAuthTag().toString('hex'); as a hexadecimal string.

Using the encryptMnemonic function

To encrypt the Mnemonic Phrase/create a cypher, the encryptMnemonic function is used.

encryptMnemonic(mnemonic, key, iv);

This function expects a mnemonic parameter, which should be a Mnemonic Phrase, and a key parameter, which should be a cryptographic key (using a prepared key is recommended). An optional Initialization Vector (iv) parameter is accepted, which is expected to be provided as a hexadecimal string (24 characters). If no Initialization Vector is provided, a Buffer of 12 random bytes (crypto.randomBytes(12);) is used.

Example use with "iv" provided:

const { encryptMnemonic } = require('mnemonic-backup');

// 14 Word Mnemonic Phrase
const mnemonic = "floor knife elite stay fire ring like mistake inflict patient bench speak faith carbon";

// Cryptographic Key (prepared key)
const key = "773b371566d8ebbc57d9d9ce581e6fcd13d3d57f617d366fcfebd2937f8a05da";

// Initialization Vector provided in Hex
const iv = "44494e4f5341555253212121";

const result = encryptMnemonic(mnemonic, key, iv);
    console.log("Cyphertext:", result.cyphertext);
    console.log("IV:", result.iv);
    console.log("Auth Tag:", result.authTag);

// Sample Output:
// Cyphertext: 4955bb6686bd53bb792298bcc039cba5e7e5dfe7e14150a8e5d0ade51d129d0874b251b76450293db1d67a6dfe5a8236bfe303568e8aaedd5566f02f0032874c512693ff58ce33a8d5c4d7f75481ff7158f72eefa081
// IV: 44494e4f5341555253212121
// Auth Tag: 8c7708ed8f31c292c89aae9ceb175102

The function returns the Cyphertext, Initialization Vector, and Authentication Tag from the encryption of the Mnemonic Phrase in the output.

Decryption

A cypher/encrypted Mnemonic Phrase is decrypted using the cyphertext and authTag from the encryption output, along with the same key and Initialization Vector used for encryption.

crypto.createDecipheriv(algorithm, key, iv[, options]);

The algorithm used for decryption is the same used for encryption, aes-256-gcm, with the key being a Buffer of a provided cryptographic key. A Buffer of an Initialization Vector (iv) is also provided. The Authentication Tag (authTag) is set using .setAuthTag(authTagBuffer); with a Buffer of the Authentication Tag.

Using the decryptMnemonic function

To decrypt the cyphertext of a Mnemonic Phrase, the decryptMnemonic function is used.

decryptMnemonic(cyphertext, key, iv, authTag);

This function expects a cyphertext parameter, containing the cyphertext of the encrypted Mnemonic Phrase, along with a key, an iv, and an authTag parameter, expecting the same cryptographic key, initilization vector, and authentication tag used during encryption.

Example use:

const { decryptMnemonic } = require('mnemonic-backup');

// Cryptographic Key
const key = "773b371566d8ebbc57d9d9ce581e6fcd13d3d57f617d366fcfebd2937f8a05da";

// cyphertext, iv, and authTag from Encryption
const cyphertext = "4955bb6686bd53bb792298bcc039cba5e7e5dfe7e14150a8e5d0ade51d129d0874b251b76450293db1d67a6dfe5a8236bfe303568e8aaedd5566f02f0032874c512693ff58ce33a8d5c4d7f75481ff7158f72eefa081";
const iv = "44494e4f5341555253212121";
const authTag = "8c7708ed8f31c292c89aae9ceb175102";

const decryptedMnemonic = decryptMnemonic(cyphertext, key, iv, authTag);
console.log("Decrypted Mnemonic:", decryptedMnemonic);

// Sample Output:
// Decrypted Mnemonic: floor knife elite stay fire ring like mistake inflict patient bench speak faith carbon

The function returns the decrypted Mnemonic Phrase in the output.

1.2.1

6 months ago

1.2.0

10 months ago

1.1.0

10 months ago

1.0.0

10 months ago