feat: initial public release (MAESTRO)

This commit is contained in:
oss-sync
2026-06-03 05:08:00 +00:00
commit f5c7666f6b
823 changed files with 184150 additions and 0 deletions
+51
View File
@@ -0,0 +1,51 @@
import { describe, it, expect, beforeEach } from 'vitest';
import { mkdtempSync, rmSync } from 'fs';
import { tmpdir } from 'os';
import { join } from 'path';
import {
initMasterKey, generateUserDek, encryptUserDek, decryptUserDek,
encryptStateBlob, decryptStateBlob,
} from './sessions.js';
describe('envelope encryption', () => {
let dir: string;
let masterKeyPath: string;
beforeEach(() => {
dir = mkdtempSync(join(tmpdir(), 'crypto-test-'));
masterKeyPath = join(dir, 'master.key');
});
it('initMasterKey writes a 32-byte file when missing', () => {
const key = initMasterKey(masterKeyPath);
expect(key.length).toBe(32);
const reread = initMasterKey(masterKeyPath);
expect(reread.equals(key)).toBe(true);
rmSync(dir, { recursive: true, force: true });
});
it('round-trips a user DEK through master key envelope', () => {
const master = initMasterKey(masterKeyPath);
const dek = generateUserDek();
const enc = encryptUserDek(master, dek);
const dec = decryptUserDek(master, enc);
expect(dec.equals(dek)).toBe(true);
rmSync(dir, { recursive: true, force: true });
});
it('round-trips a state blob through user DEK', () => {
const dek = generateUserDek();
const payload = JSON.stringify({ cookies: [{ name: 'sid', value: 'abc' }] });
const enc = encryptStateBlob(dek, payload);
const dec = decryptStateBlob(dek, enc);
expect(dec).toBe(payload);
rmSync(dir, { recursive: true, force: true });
});
it('decryptStateBlob throws on tampered ciphertext', () => {
const dek = generateUserDek();
const enc = encryptStateBlob(dek, 'hello');
enc[enc.length - 1] ^= 0xff;
expect(() => decryptStateBlob(dek, enc)).toThrow();
});
});
+61
View File
@@ -0,0 +1,61 @@
import { randomBytes, createCipheriv, createDecipheriv } from 'crypto';
import { existsSync, readFileSync, writeFileSync, chmodSync, mkdirSync } from 'fs';
import { dirname } from 'path';
const ALGO = 'aes-256-gcm';
const IV_LEN = 12;
const TAG_LEN = 16;
/** Read or initialize the master key (32 bytes) at `path`. File mode is forced to 0600. */
export function initMasterKey(path: string): Buffer {
if (existsSync(path)) {
const buf = readFileSync(path);
if (buf.length !== 32) {
throw new Error(`Master key at ${path} is not 32 bytes (got ${buf.length})`);
}
return buf;
}
mkdirSync(dirname(path), { recursive: true, mode: 0o700 });
const key = randomBytes(32);
writeFileSync(path, key, { mode: 0o600 });
chmodSync(path, 0o600);
return key;
}
export function generateUserDek(): Buffer {
return randomBytes(32);
}
function encrypt(key: Buffer, plaintext: Buffer): Buffer {
const iv = randomBytes(IV_LEN);
const cipher = createCipheriv(ALGO, key, iv);
const ciphertext = Buffer.concat([cipher.update(plaintext), cipher.final()]);
const tag = cipher.getAuthTag();
return Buffer.concat([iv, ciphertext, tag]);
}
function decrypt(key: Buffer, blob: Buffer): Buffer {
if (blob.length < IV_LEN + TAG_LEN) throw new Error('blob too short');
const iv = blob.subarray(0, IV_LEN);
const tag = blob.subarray(blob.length - TAG_LEN);
const ciphertext = blob.subarray(IV_LEN, blob.length - TAG_LEN);
const decipher = createDecipheriv(ALGO, key, iv);
decipher.setAuthTag(tag);
return Buffer.concat([decipher.update(ciphertext), decipher.final()]);
}
export function encryptUserDek(masterKey: Buffer, dek: Buffer): Buffer {
return encrypt(masterKey, dek);
}
export function decryptUserDek(masterKey: Buffer, enc: Buffer): Buffer {
return decrypt(masterKey, enc);
}
export function encryptStateBlob(dek: Buffer, plaintext: string): Buffer {
return encrypt(dek, Buffer.from(plaintext, 'utf-8'));
}
export function decryptStateBlob(dek: Buffer, blob: Buffer): string {
return decrypt(dek, blob).toString('utf-8');
}