@vairogs.lv/sdk
v1.0.0
Published
TypeScript SDK for Vairogs.lv Tag API v2 - Zero-knowledge password manager API client
Maintainers
Readme
@vairogs/sdk
TypeScript SDK for Vairogs.lv Tag API v2 - Zero-knowledge password manager API client.
Installation
npm install @vairogs/sdkQuick Start
import { VairogsClient } from '@vairogs/sdk';
const client = new VairogsClient({
accessKey: 'vgtk_a_xxx', // Sent to server for authentication
decryptKey: 'vgtk_d_xxx', // NEVER sent - used locally for decryption
});
// List and decrypt all passwords
const passwords = await client.listPasswords();
for (const item of passwords) {
console.log(`${item.title}: ${item.data.username}`);
}
// Create a new password
await client.createPassword({
title: 'GitHub',
username: 'myuser',
password: 'secret123',
url: 'https://github.com',
notes: 'Personal account',
});API Reference
Constructor
const client = new VairogsClient({
accessKey: string; // Required: vgtk_a_xxx
decryptKey: string; // Required: vgtk_d_xxx
baseUrl?: string; // Optional: default 'https://vairogs.lv'
timeout?: number; // Optional: default 30000ms
});Reading Items
// Get tag info
const info = await client.getInfo();
// List all items (encrypted)
const items = await client.listItems({ type: ItemType.PASSWORD });
// Decrypt a single item
const decrypted = await client.decryptItem(item);
// Convenience methods (list + decrypt)
const passwords = await client.listPasswords();
const notes = await client.listNotes();
const totps = await client.listTotps();Creating Items
// Create password
await client.createPassword({
title: 'GitHub',
username: 'myuser',
password: 'secret123',
url: 'https://github.com',
notes: 'Optional notes',
});
// Create note
await client.createNote({
title: 'My Note',
content: 'Note content here',
});
// Create TOTP
await client.createTotp({
title: 'GitHub 2FA',
secret: 'JBSWY3DPEHPK3PXP',
issuer: 'GitHub',
account: '[email protected]',
});File Operations
import fs from 'fs';
// Upload an image with thumbnail
const imageBuffer = fs.readFileSync('./photo.jpg');
await client.uploadImage({
title: 'Photo',
file: imageBuffer,
fileName: 'photo.jpg',
mimeType: 'image/jpeg',
notes: 'My photo',
});
// Upload a document
const docBuffer = fs.readFileSync('./document.pdf');
await client.uploadDocument({
title: 'Document',
file: docBuffer,
fileName: 'document.pdf',
mimeType: 'application/pdf',
});
// Download and decrypt a file
const decryptedFile = await client.downloadFile(itemId);
fs.writeFileSync('./downloaded.jpg', decryptedFile);
// Download thumbnail
const thumbnail = await client.downloadFile(itemId, 'thumbnail');Two-Key Architecture
The SDK uses a two-key architecture for zero-knowledge encryption:
- Access Key (
vgtk_a_xxx): Sent to the server for API authentication - Decryption Key (
vgtk_d_xxx): NEVER sent to the server, used locally to derive the X25519 keypair for encryption/decryption
How It Works
- Key Derivation: The decryption key is used with PBKDF2 (100k iterations) to derive an X25519 keypair
- Encryption: Data is encrypted with AES-256-GCM using a random DEK
- Key Wrapping: The DEK is wrapped with NaCl box for both the main user and MCP client
- Storage: Only encrypted data and wrapped keys are sent to the server
Cryptographic Details
| Parameter | Value |
|-----------|-------|
| PBKDF2 Iterations | 100,000 |
| Key Derivation Salt | vairogs-mcp-key-derivation-v1 |
| Data Encryption | AES-256-GCM |
| IV Size | 12 bytes |
| Auth Tag Size | 16 bytes |
| Key Wrapping | NaCl box (X25519 + XSalsa20-Poly1305) |
Error Handling
import { VairogsError, VairogsApiError, VairogsCryptoError } from '@vairogs/sdk';
try {
await client.listPasswords();
} catch (error) {
if (error instanceof VairogsApiError) {
console.error(`API Error: ${error.code} (${error.statusCode})`);
} else if (error instanceof VairogsCryptoError) {
console.error(`Crypto Error: ${error.code}`);
} else if (error instanceof VairogsError) {
console.error(`Error: ${error.code}`);
}
}Advanced Usage
For advanced users, the SDK exports crypto utilities:
import {
deriveKeypairFromDecryptKey,
generateDEK,
aesEncrypt,
aesDecrypt,
CRYPTO_CONSTANTS,
} from '@vairogs/sdk';
// Derive keypair manually
const keypair = await deriveKeypairFromDecryptKey('vgtk_d_xxx');
// Generate a random DEK
const dek = generateDEK();
// Encrypt/decrypt manually
const encrypted = await aesEncrypt('secret data', dek);
const decrypted = await aesDecrypt(encrypted, dek);License
MIT
