React Native Quick Crypto
API Reference

Argon2

Memory-hard password hashing (PHC winner)

Argon2 is the winner of the Password Hashing Competition (PHC) and the recommended algorithm for password hashing and key derivation. It is designed to resist GPU, ASIC, and side-channel attacks.

When to use Argon2 vs PBKDF2/Scrypt

Argon2 is the modern choice for password hashing. Use PBKDF2 only for FIPS compliance, and scrypt when Argon2 is unavailable. Argon2 offers the best resistance to hardware-accelerated attacks.

Table of Contents

Theory

Argon2 fills a large block of memory with pseudorandom data derived from the password and salt, then performs multiple passes over it. This makes brute-force attacks expensive on both time and memory dimensions.

Key parameters:

ParameterDescriptionTypical Value
memoryCostMemory in KiB65536 (64 MB)
timeCostNumber of passes3
parallelismParallel threads4

Variants

VariantBest ForProperties
argon2dCryptocurrency miningFastest, data-dependent memory access (vulnerable to side-channel)
argon2iPassword hashingData-independent memory access (side-channel resistant)
argon2idRecommended defaultHybrid of argon2d and argon2i

Module Methods

argon2(algorithm, parameters, callback)

Asynchronous Argon2 hashing.

Parameters:

Prop

Type

Example:

import { argon2, randomBytes } from 'react-native-quick-crypto';

const password = 'user-password';
const salt = randomBytes(16);

argon2('argon2id', {
  pass: password,
  salt,
  memoryCost: 65536,  // 64 MB
  timeCost: 3,
  parallelism: 4,
  hashLength: 32
}, (err, hash) => {
  if (err) throw err;
  console.log(hash.toString('hex'));
});

argon2Sync(algorithm, parameters)

Synchronous version. Returns Buffer.

The synchronous version blocks the JS thread. Use the async version for UI-facing operations.

import { argon2Sync, randomBytes } from 'react-native-quick-crypto';

const hash = argon2Sync('argon2id', {
  pass: 'password',
  salt: randomBytes(16),
  memoryCost: 65536,
  timeCost: 3,
  parallelism: 4,
  hashLength: 32
});

WebCrypto API

Argon2 is available through subtle.deriveBits() and subtle.deriveKey().

Import a Password Key

import { subtle } from 'react-native-quick-crypto';

const passwordKey = await subtle.importKey(
  'raw-secret',
  new TextEncoder().encode('user-password'),
  { name: 'Argon2id' },
  false,
  ['deriveBits', 'deriveKey']
);

deriveBits

const salt = crypto.getRandomValues(new Uint8Array(16));

const bits = await subtle.deriveBits(
  {
    name: 'Argon2id',
    salt,
    memoryCost: 65536,
    timeCost: 3,
    parallelism: 4
  },
  passwordKey,
  256 // bits
);

deriveKey

Derive an AES key directly from a password:

const aesKey = await subtle.deriveKey(
  {
    name: 'Argon2id',
    salt: crypto.getRandomValues(new Uint8Array(16)),
    memoryCost: 65536,
    timeCost: 3,
    parallelism: 4
  },
  passwordKey,
  { name: 'AES-GCM', length: 256 },
  true,
  ['encrypt', 'decrypt']
);

Real-World Examples

Secure Password Storage

import { argon2, randomBytes, timingSafeEqual } from 'react-native-quick-crypto';

interface StoredPassword {
  hash: string;
  salt: string;
  algorithm: string;
  memoryCost: number;
  timeCost: number;
  parallelism: number;
}

function hashPassword(password: string): Promise<StoredPassword> {
  return new Promise((resolve, reject) => {
    const salt = randomBytes(16);
    const params = {
      pass: password,
      salt,
      memoryCost: 65536,
      timeCost: 3,
      parallelism: 4,
      hashLength: 32
    };

    argon2('argon2id', params, (err, hash) => {
      if (err) return reject(err);
      resolve({
        hash: hash.toString('hex'),
        salt: salt.toString('hex'),
        algorithm: 'argon2id',
        memoryCost: 65536,
        timeCost: 3,
        parallelism: 4
      });
    });
  });
}

function verifyPassword(password: string, stored: StoredPassword): Promise<boolean> {
  return new Promise((resolve, reject) => {
    argon2(stored.algorithm, {
      pass: password,
      salt: Buffer.from(stored.salt, 'hex'),
      memoryCost: stored.memoryCost,
      timeCost: stored.timeCost,
      parallelism: stored.parallelism,
      hashLength: 32
    }, (err, hash) => {
      if (err) return reject(err);
      const expected = Buffer.from(stored.hash, 'hex');
      resolve(timingSafeEqual(hash, expected));
    });
  });
}

Deriving an Encryption Key from a Password

import {
  argon2Sync,
  randomBytes,
  createCipheriv,
  createDecipheriv
} from 'react-native-quick-crypto';

function encryptWithPassword(plaintext: string, password: string) {
  const salt = randomBytes(16);
  const iv = randomBytes(12);

  const key = argon2Sync('argon2id', {
    pass: password,
    salt,
    memoryCost: 65536,
    timeCost: 3,
    parallelism: 4,
    hashLength: 32
  });

  const cipher = createCipheriv('aes-256-gcm', key, iv);
  let encrypted = cipher.update(plaintext, 'utf8', 'base64');
  encrypted += cipher.final('base64');
  const tag = cipher.getAuthTag();

  return {
    encrypted,
    salt: salt.toString('base64'),
    iv: iv.toString('base64'),
    tag: tag.toString('base64')
  };
}

On this page