React Native Quick Crypto
API Reference

Post-Quantum Cryptography

Quantum-resistant algorithms (ML-DSA, ML-KEM)

Post-Quantum Cryptography (PQC) provides cryptographic algorithms that are secure against both classical and quantum computers. RNQC implements the NIST standardized lattice-based algorithms via OpenSSL 3.6+.

Why Post-Quantum?

Quantum computers threaten RSA, ECDSA, and ECDH. The PQC algorithms below are NIST-standardized replacements designed to resist quantum attacks while running efficiently on classical hardware.

Table of Contents

Algorithms

ML-DSA (FIPS 204)

Module Lattice Digital Signature Algorithm. Replacement for RSA and ECDSA signatures.

Parameter SetSecurity LevelPublic KeySignatureUse Case
ML-DSA-44NIST Level 21,312 B2,420 BGeneral purpose
ML-DSA-65NIST Level 31,952 B3,309 BRecommended
ML-DSA-87NIST Level 52,592 B4,627 BMaximum security

ML-KEM (FIPS 203)

Module Lattice Key Encapsulation Mechanism. Replacement for ECDH key exchange.

Parameter SetSecurity LevelPublic KeyCiphertextShared Secret
ML-KEM-512NIST Level 1800 B768 B32 B
ML-KEM-768NIST Level 31,184 B1,088 B32 B
ML-KEM-1024NIST Level 51,568 B1,568 B32 B

ML-DSA (Digital Signatures)

Node.js API

Generate ML-DSA key pairs and sign/verify using the standard crypto API:

import {
  generateKeyPairSync,
  sign,
  verify
} from 'react-native-quick-crypto';

// Generate ML-DSA-65 key pair
const { publicKey, privateKey } = generateKeyPairSync('ml-dsa-65');

// Sign
const message = Buffer.from('quantum-safe message');
const signature = sign(null, message, privateKey);

// Verify
const isValid = verify(null, message, publicKey, signature);
console.log('Valid:', isValid); // true

Key Export/Import

ML-DSA keys support multiple export formats:

// Export as PEM
const pubPem = publicKey.export({ type: 'spki', format: 'pem' });
const privPem = privateKey.export({ type: 'pkcs8', format: 'pem' });

// Export as DER
const pubDer = publicKey.export({ type: 'spki', format: 'der' });

// Re-import
import { createPublicKey, createPrivateKey } from 'react-native-quick-crypto';

const imported = createPublicKey({
  key: pubDer,
  format: 'der',
  type: 'spki'
});

ML-KEM (Key Encapsulation)

ML-KEM uses encapsulation rather than key exchange. One party encapsulates a shared secret using the other's public key, producing a ciphertext. The other party decapsulates the ciphertext with their private key to recover the same shared secret.

Node.js API

import {
  generateKeyPairSync,
  encapsulate,
  decapsulate
} from 'react-native-quick-crypto';

// Generate ML-KEM-768 key pair
const { publicKey, privateKey } = generateKeyPairSync('ml-kem-768');

// Encapsulate: produces shared secret + ciphertext
const { sharedSecret, ciphertext } = encapsulate(publicKey);

// Decapsulate: recovers the same shared secret
const recovered = decapsulate(privateKey, ciphertext);

console.log(sharedSecret.equals(recovered)); // true

WebCrypto API

PQC algorithms are fully supported through the SubtleCrypto interface.

ML-DSA via SubtleCrypto

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

// Generate key pair
const keyPair = await subtle.generateKey(
  { name: 'ML-DSA-65' },
  true,
  ['sign', 'verify']
);

// Sign
const data = new TextEncoder().encode('quantum-safe data');
const signature = await subtle.sign(
  { name: 'ML-DSA-65' },
  keyPair.privateKey,
  data
);

// Verify
const isValid = await subtle.verify(
  { name: 'ML-DSA-65' },
  keyPair.publicKey,
  signature,
  data
);

ML-KEM via SubtleCrypto

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

// Generate encapsulation key pair
const keyPair = await subtle.generateKey(
  { name: 'ML-KEM-768' },
  true,
  ['deriveBits', 'deriveKey']
);

// Encapsulate: get shared secret bits + ciphertext
const { sharedSecret, ciphertext } = await subtle.encapsulateBits(
  { name: 'ML-KEM-768' },
  keyPair.publicKey
);

// Decapsulate: recover shared secret
const recovered = await subtle.decapsulateBits(
  { name: 'ML-KEM-768' },
  keyPair.privateKey,
  ciphertext
);

// Or derive a key directly from encapsulation
const { key: aesKey, ciphertext: ct } = await subtle.encapsulateKey(
  { name: 'ML-KEM-768' },
  keyPair.publicKey,
  { name: 'AES-GCM', length: 256 },
  true,
  ['encrypt', 'decrypt']
);

// Decapsulate to get the same AES key
const recoveredKey = await subtle.decapsulateKey(
  { name: 'ML-KEM-768' },
  keyPair.privateKey,
  ct,
  { name: 'AES-GCM', length: 256 },
  true,
  ['encrypt', 'decrypt']
);

Key Export Formats

Algorithmspkipkcs8jwkraw-publicraw-seed
ML-DSA-44/65/87
ML-KEM-512/768/1024
// Export ML-DSA public key as JWK
const jwk = await subtle.exportKey('jwk', keyPair.publicKey);

// Export raw public key bytes
const rawPub = await subtle.exportKey('raw-public', keyPair.publicKey);

// Export seed (deterministic private key material)
const seed = await subtle.exportKey('raw-seed', keyPair.privateKey);

// Import from raw-public
const imported = await subtle.importKey(
  'raw-public',
  rawPub,
  { name: 'ML-DSA-65' },
  true,
  ['verify']
);

Real-World Examples

Hybrid Signature (Classical + PQC)

Combine Ed25519 with ML-DSA for defense-in-depth during the quantum transition:

import {
  generateKeyPairSync,
  sign,
  verify
} from 'react-native-quick-crypto';

function hybridSign(message: Buffer) {
  const ed = generateKeyPairSync('ed25519');
  const pqc = generateKeyPairSync('ml-dsa-65');

  const edSig = sign(null, message, ed.privateKey);
  const pqcSig = sign(null, message, pqc.privateKey);

  return {
    message,
    signatures: { ed25519: edSig, mlDsa65: pqcSig },
    publicKeys: { ed25519: ed.publicKey, mlDsa65: pqc.publicKey }
  };
}

function hybridVerify(signed: ReturnType<typeof hybridSign>): boolean {
  const edValid = verify(
    null, signed.message,
    signed.publicKeys.ed25519, signed.signatures.ed25519
  );
  const pqcValid = verify(
    null, signed.message,
    signed.publicKeys.mlDsa65, signed.signatures.mlDsa65
  );

  // Both must pass
  return edValid && pqcValid;
}

Quantum-Safe Key Exchange

Use ML-KEM to establish a shared secret for symmetric encryption:

import {
  generateKeyPairSync,
  encapsulate,
  decapsulate,
  createCipheriv,
  createDecipheriv,
  createHash,
  randomBytes
} from 'react-native-quick-crypto';

// Server publishes its ML-KEM public key
const server = generateKeyPairSync('ml-kem-768');

// Client encapsulates a shared secret
const { sharedSecret, ciphertext } = encapsulate(server.publicKey);

// Derive AES key from shared secret
const aesKey = createHash('sha256').update(sharedSecret).digest();
const iv = randomBytes(12);

// Encrypt with AES-GCM
const cipher = createCipheriv('aes-256-gcm', aesKey, iv);
let encrypted = cipher.update('secret message', 'utf8', 'base64');
encrypted += cipher.final('base64');
const tag = cipher.getAuthTag();

// Server decapsulates to get the same shared secret
const serverSecret = decapsulate(server.privateKey, ciphertext);
const serverKey = createHash('sha256').update(serverSecret).digest();

// Server decrypts
const decipher = createDecipheriv('aes-256-gcm', serverKey, iv);
decipher.setAuthTag(tag);
let decrypted = decipher.update(encrypted, 'base64', 'utf8');
decrypted += decipher.final('utf8');
console.log(decrypted); // "secret message"

On this page