Files
WebDrop/web/src/core-bridge/worker/passkeyCrypto.test.ts
T

22 lines
1.5 KiB
TypeScript

import { describe, expect, it } from 'vitest';
import { openPasskeyKey, sealPasskeyKey } from './passkeyCrypto';
import { bytes, openJson, sealJson } from './accountCrypto';
describe('Passkey recovery key envelopes', () => {
it('recovers the same non-exportable vault key without exposing plaintext to the backend', async () => {
const material = crypto.getRandomValues(new Uint8Array(32)); const prf = crypto.getRandomValues(new Uint8Array(32));
const key = await crypto.subtle.importKey('raw', bytes(material), 'AES-GCM', false, ['encrypt', 'decrypt']);
const vault = await sealJson({ private: 'test-private-identity' }, key);
const envelope = await sealPasskeyKey(material, bytes(prf), 'alice', 'credential-a');
expect(envelope).not.toContain('test-private-identity');
const recovered = await openPasskeyKey(envelope, bytes(prf), 'alice', 'credential-a');
expect(recovered.extractable).toBe(false); expect(await openJson(vault, recovered)).toEqual({ private: 'test-private-identity' });
await expect(openPasskeyKey(envelope, bytes(prf), 'bob', 'credential-a')).rejects.toThrow();
await expect(openPasskeyKey(envelope, bytes(prf), 'alice', 'credential-b')).rejects.toThrow();
await expect(openPasskeyKey(envelope, bytes(crypto.getRandomValues(new Uint8Array(32))), 'alice', 'credential-a')).rejects.toThrow();
});
it('rejects malformed PRF outputs', async () => {
await expect(sealPasskeyKey(new Uint8Array(32), new ArrayBuffer(31), 'alice', 'credential')).rejects.toThrow();
});
});