@quantumize/sdk
v1.0.3
Published
Official Node.js SDK and CLI for the Quantumize post-quantum cryptography platform
Maintainers
Readme
@quantumize/sdk
Official Node.js SDK and CLI for the Quantumize post-quantum cryptography platform.
Protect your files with NIST-standardized post-quantum algorithms (ML-KEM, ML-DSA, SLH-DSA, HQC, and more) in a single function call.
Requirements
- Node.js 18 or later
- An active Quantumize account and API key
Installation
# SDK only
npm install @quantumize/sdk
# CLI installed globally
npm install -g @quantumize/sdkReleases are published from version tags named sdk-vX.Y.Z after the tag is
checked against the version in this package.
Algorithm IDs
Crypto operations identify algorithms by a numeric algoId, not by name.
Run client.algorithms.list() or quantumize algos to see the IDs available in your organisation:
const algos = await client.algorithms.list();
// Each entry has: { algoId: number, name: string, category: string, ... }
// Example: { algoId: 1, name: 'CRYSTALS_KYBER', category: 'kem' }quantumize algos
# ID Name Category Status
# ───────────────────────────────────────────────────────
# 1 CRYSTALS_KYBER kem
# 4 CLASSIC_MCELIECE kem
# 1 CRYSTALS_DILITHIUM signing
# 2 FALCON signing
# ...Note:
algoIdvalues are scoped per category — the same number can refer to a different algorithm in KEM vs signing contexts. Always pick IDs from the list for your intended operation type.
Quickstart — SDK
1. Create a client
import { QuantumizeClient } from '@quantumize/sdk';
const client = new QuantumizeClient({
baseUrl: process.env.QUANTUMIZE_BASE_URL, // e.g. https://api.your-instance.com
apiKey: process.env.QUANTUMIZE_API_KEY, // bypasses interactive MFA
});2. Encrypt a file
// Get the numeric algoId from `client.algorithms.list()`
const record = await client.crypto.encrypt('./secret.pdf', {
folderId: 'FOLDER_ID', // from client.folders.list()
algoId: 1, // e.g. 1 = CRYSTALS_KYBER
});
console.log('Stored as record:', record.recordId);3. Decrypt it back (round-trip)
Pass the CryptoRecord returned by encrypt() — it carries the S3 artifact
keys and algorithm ID needed to retrieve and decrypt automatically.
const { data, fileName } = await client.crypto.decrypt(record);
// `data` is a Buffer of the original plaintext bytes
await fs.writeFile('./recovered.pdf', data);4. Sign a file
const record = await client.crypto.sign('./contract.docx', {
folderId: 'FOLDER_ID',
algoId: 1, // e.g. 1 = CRYSTALS_DILITHIUM
});
console.log('Signature record:', record.recordId);5. Verify a signature
Supply the original (pre-signing) file — the SDK uses the server-side
verifySigned endpoint which auto-fetches the stored signature and public key from S3.
const { verified } = await client.crypto.verify(record.recordId, './contract.docx');
console.log(verified ? '✓ Valid' : '✗ Invalid');6. Sign + Encrypt (combined)
Provide separate algorithm IDs for signing and encryption.
const record = await client.crypto.signEncrypt('./payload.bin', {
folderId: 'FOLDER_ID',
signAlgoId: 1, // signing algorithm ID
encryptAlgoId: 1, // encryption algorithm ID
});7. Resolve algorithm name to numeric ID
// Looks up the catalog once and caches it in memory.
const algoId = await client.algorithms.lookupId('CRYSTALS_KYBER');API Reference
new QuantumizeClient(config)
| Option | Type | Description |
|---|---|---|
| baseUrl | string | Backend URL (default: http://localhost:9000) |
| apiKey | string | API key (X-API-Key header) — bypasses interactive MFA |
| token | string | JWT bearer token (set automatically after auth.login()) |
| timeoutMs | number | Request timeout in ms (default: 60 000) |
client.auth
| Method | Description |
|---|---|
| login(email, password) | Log in; JWT stored automatically |
| refresh(refreshToken) | Refresh an expired access token |
| logout(refreshToken?) | Invalidate the current session |
client.apiKeys
| Method | Description |
|---|---|
| create({ name, expiresAt?, orgId? }) | Create an API key — plaintext shown exactly once |
| list() | List all API keys for the account |
| revoke(id) | Revoke a key by ID |
client.crypto
| Method | Signature | Description |
|---|---|---|
| encrypt | (filePath, { folderId, algoId: number }) → CryptoRecord | Encrypt a file |
| decrypt | (record: CryptoRecord) → { data: Buffer, fileName? } | Decrypt — pass record from encrypt() |
| sign | (filePath, { folderId, algoId: number }) → CryptoRecord | Sign a file |
| verify | (recordId, originalFilePath) → { verified: boolean } | Verify — supply original file |
| signEncrypt | (filePath, { folderId, signAlgoId: number, encryptAlgoId: number }) → CryptoRecord | Combined sign+encrypt |
Decrypt:
decrypt(record)downloads the ciphertext and decryption key from secure storage automatically — pass theCryptoRecordreturned byencrypt().
Verify:
verify(recordId, filePath)uses theverifySignedendpoint which fetches the signature and public key from S3. You only supply the original file.
MFA: Crypto operations require MFA when using a JWT. Use an API key (
X-API-Key) for server-to-server integrations — it bypasses the MFA prompt.
client.algorithms
| Method | Description |
|---|---|
| list() | List all algorithms (includes numeric algoId for each) |
| lookupId(name) | Resolve a catalog name to its numeric algoId |
client.folders
| Method | Description |
|---|---|
| list() | List all folders |
| create({ name, parentId? }) | Create a folder |
| get(folderId) | Get folder details |
Error handling
All API errors throw QuantumizeApiError with .statusCode, .message, and optional .code:
import { QuantumizeApiError } from '@quantumize/sdk';
try {
await client.crypto.decrypt(record);
} catch (err) {
if (err instanceof QuantumizeApiError) {
console.error(`API ${err.statusCode}: ${err.message}`);
}
}CLI Reference
# Configure
quantumize config set-url https://api.your-instance.com
quantumize config set-key qz_live_xxxxxxxxxxxx # preferred for automation
quantumize config show
# Or log in interactively
quantumize auth login --email [email protected] --password yourpassword
# Discover algorithm IDs (required for crypto operations)
quantumize algos
# Folders
quantumize folders list
quantumize folders create my-files
# Encrypt (note: --algo-id is a number)
quantumize encrypt secret.pdf --folder-id FOLDER_ID --algo-id 1
# After encrypt the CLI prints all artifact keys needed for decrypt:
# Record ID : 685abc...
# Encrypted file : 685abc....enc
# Decryption key : 685abc....key
# Enc algo ID : 1
#
# To decrypt, copy those values:
quantumize decrypt RECORD_ID \
--encrypted-file "685abc....enc" \
--key-file "685abc....key" \
--algo-id 1 \
--out recovered.pdf
# Sign & Verify
quantumize sign contract.docx --folder-id FOLDER_ID --algo-id 1
quantumize verify RECORD_ID --file contract.docx # exits 0 on valid, 1 on invalid
# Sign + Encrypt
quantumize sign-encrypt payload.bin \
--folder-id FOLDER_ID \
--sign-algo-id 1 \
--encrypt-algo-id 1
# API key management
quantumize keys list
quantumize keys create "CI pipeline" --expires 2027-01-01
quantumize keys revoke KEY_IDRunnable example
Save as example.ts and run with npx tsx example.ts:
import { QuantumizeClient } from '@quantumize/sdk';
import { writeFile } from 'fs/promises';
const client = new QuantumizeClient({
baseUrl: process.env.QUANTUMIZE_BASE_URL ?? 'http://localhost:9000',
apiKey: process.env.QUANTUMIZE_API_KEY!,
});
async function main() {
// 1. Discover available algorithms
const algos = await client.algorithms.list();
const kemAlgo = algos.find((a) => a.name === 'CRYSTALS_KYBER')!;
const sigAlgo = algos.find((a) => a.name === 'CRYSTALS_DILITHIUM')!;
console.log(`Using KEM algoId=${kemAlgo.algoId}, Signing algoId=${sigAlgo.algoId}`);
// 2. Get (or create) a folder
const folders = await client.folders.list();
const folder = folders[0] ?? await client.folders.create({ name: 'sdk-demo' });
// 3. Encrypt + Decrypt round-trip
const record = await client.crypto.encrypt('./README.md', {
folderId: folder._id,
algoId: kemAlgo.algoId,
});
console.log('Encrypted as record:', record.recordId);
const { data } = await client.crypto.decrypt(record);
await writeFile('./README.recovered.md', data);
console.log('Decrypted successfully — content matches original.');
// 4. Sign + Verify round-trip
const signed = await client.crypto.sign('./README.md', {
folderId: folder._id,
algoId: sigAlgo.algoId,
});
const { verified } = await client.crypto.verify(signed.recordId, './README.md');
console.log(verified ? '✓ Signature valid' : '✗ Signature invalid');
}
main().catch(console.error);License
MIT © Quantumize
