Skip to main content

Encryption Examples

Strata uses Web Crypto for encrypted values. Create an instance with encryption enabled, then provide a password at the operation or instance level. A plain defineStorage() instance does not initialize the encryption manager, even if a later set() passes encrypt: true.

Basic Encryption​

import { defineStorage } from 'strata-storage';

const storage = defineStorage({ encryption: { enabled: true } });
const password = await askUserForPassword();

await storage.set('private-draft', { text: 'A draft' }, {
encryptionPassword: password,
});
const draft = await storage.get<{ text: string }>('private-draft', {
encryptionPassword: password,
});

The password must be available again to decrypt the value. Do not hard-code it or save it beside the encrypted data.

Global Encryption​

const storage = defineStorage({
encryption: { enabled: true, password },
});

await storage.set('private-draft', { text: 'A draft' });
const draft = await storage.get('private-draft');

The configured password applies to encrypted operations on that instance. Protect it in the calling application.

Selective Encryption​

const storage = defineStorage({ encryption: { enabled: true } });

await storage.set('theme', 'dark', { encrypt: false });
await storage.set('private-draft', draft, {
encrypt: true,
encryptionPassword: password,
});

const savedTheme = await storage.get('theme');
const savedDraft = await storage.get('private-draft', {
encryptionPassword: password,
});

When encryption is enabled globally, mark each intentionally plain write with encrypt: false.

Password Management​

Use an application-owned unlock step. Do not treat a missing verification value as a successful unlock. For example, create a marker after the user first sets a password, then require that marker on later unlocks:

const storage = defineStorage({ encryption: { enabled: true } });

async function createPassword(password: string): Promise<void> {
await storage.set('_verification', 'ready', { encryptionPassword: password });
}

async function unlock(password: string): Promise<boolean> {
try {
return await storage.get<string>('_verification', {
encryptionPassword: password,
}) === 'ready';
} catch {
return false;
}
}

This checks whether the supplied password decrypts the marker. It is a local example, not an account authentication system.

Key Derivation​

Strata derives an encryption key from the supplied password with PBKDF2. The encryption config accepts iterations, saltLength, keyLength, and algorithm. It generates a fresh salt for each encrypted write, so the application does not need to hash the password itself.

const storage = defineStorage({
encryption: {
enabled: true,
iterations: 600_000,
saltLength: 16,
keyLength: 256,
algorithm: 'AES-GCM',
},
});

Encrypted File Storage​

A File is not stored as a live browser object. Convert its bytes to a serializable value before writing, and size it for the chosen adapter's quota:

const bytes = new Uint8Array(await file.arrayBuffer());
await storage.set(`file:${file.name}`, Array.from(bytes), {
storage: 'indexedDB',
encrypt: true,
encryptionPassword: password,
});

Secure Form Data​

async function saveDraft(formId: string, value: unknown, password: string) {
await storage.set(`form:${formId}`, value, {
encrypt: true,
encryptionPassword: password,
ttl: 3_600_000,
});
}

Keep the password available for a later read, and remove the draft when the user discards it.

See Also​