# vault-crypto

Post-quantum cryptographic primitives for the ZK-Vault protocol, compiled to WebAssembly.

## Features

- **AEAD Encryption**: AES-256-GCM and XChaCha20-Poly1305
- **Post-Quantum KEM**: ML-KEM-768 (Kyber-768) key encapsulation
- **Key Derivation**: HKDF-SHA256 and HKDF-join for all-of policies
- **Secret Sharing**: Shamir (t, n)-threshold secret splitting
- **Utilities**: Key commitment, random generation, hashing

## Installation

```bash
npm install @ajna-inc/vault-crypto
```

## Usage

### Generate and Encrypt with CEK

```typescript
import * as vault from '@ajna-inc/vault-crypto';

// Initialize WASM
await vault.init();

// Generate a random CEK
const cek = vault.generateCek();

// Generate nonce
const nonce = vault.generateNonceAesGcm();

// Encrypt data
const plaintext = new TextEncoder().encode('Secret document');
const aad = new TextEncoder().encode('{"docId":"abc","epoch":0}');

const result = vault.aesGcmEncrypt(cek, nonce, plaintext, aad);
const ciphertext = result.ciphertext();

// Decrypt
const decrypted = vault.aesGcmDecrypt(cek, nonce, ciphertext, aad);
console.log(new TextDecoder().decode(decrypted)); // "Secret document"
```

### KEM: Wrap CEK for Recipient

```typescript
// Recipient generates keypair
const keypair = vault.kemGenerateKeypair();
const publicKey = keypair.publicKey();
const secretKey = keypair.secretKey();

// Sender wraps CEK to recipient's public key
const wrappedCek = vault.kemWrapCek(cek, publicKey);

// Recipient unwraps
const unwrappedCek = vault.kemUnwrapCek(wrappedCek, secretKey);
```

### Shamir Secret Sharing

```typescript
// Split CEK into 5 shares, need any 3 to reconstruct
const shares = vault.shamirSplit(cek, 3, 5);

// Reconstruct from any 3 shares
const selected = [shares[0], shares[2], shares[4]];
const reconstructed = vault.shamirReconstruct(selected);
```

### HKDF-join for All-Of Policy

```typescript
// Combine multiple keys into joint wrap key
const keys = [
  { kid: 'alice', key: aliceKey },
  { kid: 'bob', key: bobKey },
];

const wrapKey = vault.hkdfJoin(keys, 'doc:123:epoch:0');
```

### Key Commitment

```typescript
// Compute key commitment
const kcmp = vault.keyCommitment(cek);

// Verify
const valid = vault.verifyKeyCommitment(cek, kcmp);
```

## API Reference

### AEAD Encryption

- `aesGcmEncrypt(key, nonce, plaintext, aad)` → `AeadResult`
- `aesGcmDecrypt(key, nonce, ciphertext, aad)` → `Uint8Array`
- `xchachaEncrypt(key, nonce, plaintext, aad)` → `AeadResult`
- `xchachaDecrypt(key, nonce, ciphertext, aad)` → `Uint8Array`

### KEM (ML-KEM-768)

- `kemGenerateKeypair()` → `KemKeypair`
- `kemEncapsulate(recipientPublicKey)` → `KemEncapResult`
- `kemDecapsulate(ciphertext, secretKey)` → `Uint8Array`
- `kemWrapCek(cek, recipientPublicKey)` → `Uint8Array`
- `kemUnwrapCek(wrappedCek, secretKey)` → `Uint8Array`

### Key Derivation

- `hkdfExpand(ikm, salt, info, length)` → `Uint8Array`
- `hkdfJoin(keys, context)` → `Uint8Array`
- `deriveCek(seed, context)` → `Uint8Array`
- `deriveKid(publicKey)` → `string`
- `deriveSymmetricKid(key)` → `string`

### Shamir Secret Sharing

- `shamirSplit(secret, threshold, totalShares)` → `SecretShare[]`
- `shamirReconstruct(shares)` → `Uint8Array`
- `shamirSplitAndWrap(secret, threshold, publicKeys)` → `WrappedShare[]`
- `shamirUnwrapAndReconstruct(wrappedShares, secretKeys)` → `Uint8Array`

### Utilities

- `generateCek()` → `Uint8Array` (32 bytes)
- `generateNonceAesGcm()` → `Uint8Array` (12 bytes)
- `generateNonceXchacha()` → `Uint8Array` (24 bytes)
- `randomBytes(length)` → `Uint8Array`
- `keyCommitment(cek)` → `Uint8Array`
- `verifyKeyCommitment(cek, kcmp)` → `boolean`
- `sha256(data)` → `Uint8Array`
- `blake2s256(data)` → `Uint8Array`
- `computeSummary(digest)` → `Uint8Array` (16 bytes)
- `constantTimeEq(a, b)` → `boolean`
- `toBase64Url(data)` → `string`
- `fromBase64Url(encoded)` → `Uint8Array`
- `toHex(data)` → `string`
- `fromHex(encoded)` → `Uint8Array`
- `generateUuid()` → `string`
- `canonicalAad(headerFields)` → `Uint8Array`
- `buildContext(docId, epoch)` → `string`

## Building from Source

```bash
# Install wasm-pack
curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh

# Build for web
wasm-pack build --target web --release

# Build for Node.js
wasm-pack build --target nodejs --release

# Run tests
cargo test
wasm-pack test --headless --firefox
```

## License

Proprietary - Copyright © 2025 Ajna Inc. All rights reserved.
