💻
Developer Guide
  • Wallet SDK
    • Wallet Overview
    • Getting Started
      • 1. Start the RAILGUN Privacy Engine
      • 2. Build a persistent store for artifact downloads
      • 3. Load a Groth16 prover for each platform
      • 4. Add networks and RPC providers
      • 5. Set up a debug logger
    • Private Wallets
      • RAILGUN Wallets
      • View-Only Wallets
      • Encryption Keys
    • Private Balances
      • Balance and Sync Callbacks
      • Updating Balances
      • QuickSync
    • Transactions
      • Shielding
        • Shield ERC-20 tokens
        • Shield base token
        • Shield NFTs
      • Private Transfers
        • Private ERC-20 Transfers
        • Private NFT Transfers
      • Cross-Contract Calls
      • Unshielding
        • Unshield ERC-20 tokens
        • Unshield base token
        • Unshield NFTs
      • UX: Private Transactions
    • Broadcasters
  • Cookbook SDK
    • Cookbook Overview
    • Recipe Guide: Write a zkApp
      • "Step" — A smart contract call
      • "Recipe" — Steps in series
      • "Combo Meal" — 2+ Recipes
    • Use your zkApp privately
  • Engine SDK
    • Engine Overview
  • ZK Account Abstraction
    • Account Abstraction Overview
    • Getting started with the contracts
    • Wallets
    • State Structure
    • Example Primitives
Powered by GitBook
On this page
  1. Wallet SDK
  2. Private Wallets

Encryption Keys

PreviousView-Only WalletsNextPrivate Balances

Last updated 1 year ago

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

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 .

Example: Create and store encryption key to local storage

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

export const hashPasswordString = async ({ secret, salt, iterations }): Promise<Pbkdf2Response> => {
  return pbkdf2(secret, salt, iterations);
},
import { getRandomBytes } from '@railgun-community/wallet';
import { hashPasswordString } from './hash-service';

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(password, salt, 100000), // Generate hash from password and salt
    hashPasswordString(password, salt, 1000000), // Generate hash for stored password. Use more iterations for the stored value.
  ]);

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

  return encryptionKey;
};

Example: Get encryption key from local storage

import { hashPasswordString } from './hash-service';

export const getEncryptionKeyFromPassword = async (password: string): Promise<string> => {
  // `password` comes from user input
  
  const [storedPasswordHash, storedSalt] = await Promise.all([
    ..., // Fetch the previously stored password hash from local storage
    ..., // Fetch the previously stored `salt` from local storage
  ]);
  
  const [encryptionKey, hashPassword] = await Promise.all([
    hashPasswordString(password, storedSalt, 100000), // Same iterations as when generated, i.e. 100000
    hashPasswordString(password, storedSalt, 1000000), // Same iterations as when generated, i.e. 1000000
  ]);

  if (hashPasswordStored !== hashPassword) {
    throw new Error('Incorrect password.');
  }

  return encryptionKey;
}
Secure Enclave