> For the complete documentation index, see [llms.txt](https://docs.railgun.org/developer-guide/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.railgun.org/developer-guide/wallet/private-wallets/encryption-keys-new.md).

# Encryption Keys (new)

hash & encryption blocks from ORG

The Database Encryption Key `encryptionKey` is a 32-byte hexadecimal string (length 64).

```typescript
const encryptionKey: string = '0101010101010101010101010101010101010101010101010101010101010101';
```

This key is used to safeguard the user’s mnemonic and wallet keys from attackers. We recommend an encryption key that is generated with entropy or `pbkdf2` hash from a strong user-provided password or PIN.

Keep the encryption key extremely safe, as it grants access to the user's wallets and mnemonics. On Mobile iOS, consider storing the Encryption Key in [Secure Enclave](https://support.apple.com/guide/security/secure-enclave-sec59b0b31ff/web).

#### Example: Create and store encryption key to local storage

```typescript
// hash-service.ts
import { pbkdf2 } from "@railgun-community/wallet";
import { Pbkdf2Response } from "@railgun-community/shared-models";

/**
 * Type definition for hashed password data.
 *
 * @property {string} secret - The hashed password or secret.
 * @property {string} salt - The salt used in the password hashing process.
 * @property {number} iterations - The number of iterations used in the hashing algorithm.
 */
type HashPasswordString = {
  secret: string;
  salt: string;
  iterations: number;
};

/**
 * Generates a salted hash from a secret string using PBKDF2 algorithm.
 *
 * @param {object} params - The parameters for hashing
 * @param {string} params.secret - The secret string to be hashed
 * @param {string} params.salt - The salt used in the hashing process
 * @param {number} params.iterations - Number of iterations for the PBKDF2 algorithm
 * @returns {Promise<Pbkdf2Response>} A promise that resolves to the hashing result
 */
export const hashPasswordString = async ({
  secret,
  salt,
  iterations,
}: HashPasswordString): Promise<Pbkdf2Response> => {
  return pbkdf2(secret, salt, iterations);
};
```

#### Example: Get encryption key from local storage

````typescript
// encryption.ts
import { getRandomBytes } from "@railgun-community/wallet";
import { hashPasswordString } from "./hash-service";
import fs from "fs";

/**
 * Asynchronously stores data in a JSON file.
 *
 * This function takes an object and persists it to the filesystem
 * as a JSON file with the provided filename with a `.json` extension.
 * The data is wrapped in an object with a `data` property before being stored.
 *
 * @param filename - The name of the file where the data will be stored (without extension)
 * @param data - The data to be stored, typically an object like {hashPasswordStored, salt}
 * @returns A Promise that resolves when the data has been written to the file
 *
 * @example
 * ```typescript
 * await storeData('credentials', { hashPasswordStored: '123abc', salt: 'xyz789' });
 * // Creates credentials.json with the content: {"data":{"hashPasswordStored":"123abc","salt":"xyz789"}}
 * ```
 */
export const storeData = async (filename: string, data: any): Promise<void> => {
  // incoming object will be
  // {hashPasswordStored, salt}
  fs.writeFileSync(`${filename}.json`, JSON.stringify({ data }));
};

/**
 * Asynchronously reads and parses JSON data from a file.
 *
 * @param filename - The name of the file to read (without the .json extension)
 * @returns A Promise that resolves to the parsed data property from the JSON file
 * @throws Will throw an error if the file cannot be read or if the JSON is invalid
 *
 * @example
 * ```typescript
 * const data = await getData('config');
 * console.log(data); // Outputs the 'data' property from config.json
 * ```
 */
export const getData = async (filename: string): Promise<any> => {
  return JSON.parse(fs.readFileSync(`${filename}.json`, "utf8")).data;
};

/**
 * Generates and stores encryption keys based on user-provided password.
 *
 * This function creates a secure encryption key from the user's password by:
 * 1. Generating a random salt
 * 2. Deriving an encryption key from the password and salt using 100,000 iterations
 * 3. Generating a separate password hash for storage using 1,000,000 iterations for extra security
 * 4. Storing the salt and the hashed password in local storage
 *
 * @param password - The user-provided password to generate encryption keys from
 * @returns A Promise that resolves with the derived encryption key
 *
 * @example
 * const encryptionKey = await setEncryptionKeyFromPassword("userPassword123");
 */
export const setEncryptionKeyFromPassword = async (
  password: string
): Promise<string> => {
  // Desired `password` comes from user input

  const salt = getRandomBytes(16); // Generate salt
  const [encryptionKey, hashPasswordStored] = await Promise.all([
    hashPasswordString({ secret: password, salt, iterations: 100000 }), // Generate hash from password and salt
    hashPasswordString({ secret: password, salt, iterations: 1000000 }), // Generate hash for stored password. Use more iterations for the stored value.
  ]);

  await Promise.all([
    await storeData("hashPasswordStored", hashPasswordStored), // Save `hashPasswordStored` to local storage
    await storeData("salt", salt), // Save `salt` to local storage
  ]);

  return encryptionKey;
};

/**
 * Validates the user's password and returns an encryption key if valid.
 *
 * This function performs two primary operations:
 * 1. Validates the provided password against a previously stored hash
 * 2. Generates an encryption key based on the password if validation succeeds
 *
 * @param {string} password - The user-provided password to validate
 * @returns {Promise<string>} A promise that resolves to the encryption key if the password is correct
 * @throws {Error} Throws an error if the password is incorrect
 *
 * @remarks
 * The function uses different iteration counts for generating the encryption key (100,000)
 * versus validating the password (1,000,000), which provides a balance between
 * security and performance.
 */
export const getEncryptionKeyFromPassword = async (
  password: string
): Promise<string> => {
  //   `password` comes from user input
  const [storedPasswordHash, storedSalt] = await Promise.all([
    getData("hashPasswordStored"), // Fetch the previously stored password hash from local storage
    getData("salt"), //   ..., // Fetch the previously stored `salt` from local storage
  ]);
  console.log("STORED DATA", storedPasswordHash, storedSalt);
  const [encryptionKey, hashPassword] = await Promise.all([
    hashPasswordString({
      secret: password,
      salt: storedSalt,
      iterations: 100000,
    }), // Same iterations as when generated, i.e. 100000
    hashPasswordString({
      secret: password,
      salt: storedSalt,
      iterations: 1000000,
    }), // Same iterations as when generated, i.e. 1000000
  ]);
  if (storedPasswordHash !== hashPassword) {
    throw new Error("Incorrect password.");
  }
  return encryptionKey;
};
````
