mirror of
https://github.com/DeBrosOfficial/orama.git
synced 2026-03-27 19:54:13 +00:00
81 lines
2.5 KiB
TypeScript
81 lines
2.5 KiB
TypeScript
import { describe, it, expect } from 'vitest';
|
|
import { split, combine } from '../../../src/vault/crypto/shamir';
|
|
|
|
describe('Shamir SSS', () => {
|
|
it('2-of-3 round-trip', () => {
|
|
const secret = new Uint8Array([42]);
|
|
const shares = split(secret, 3, 2);
|
|
expect(shares).toHaveLength(3);
|
|
|
|
const recovered = combine([shares[0]!, shares[1]!]);
|
|
expect(recovered).toEqual(secret);
|
|
|
|
const recovered2 = combine([shares[0]!, shares[2]!]);
|
|
expect(recovered2).toEqual(secret);
|
|
});
|
|
|
|
it('3-of-5 multi-byte', () => {
|
|
const secret = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
|
|
const shares = split(secret, 5, 3);
|
|
expect(shares).toHaveLength(5);
|
|
const recovered = combine([shares[0]!, shares[2]!, shares[4]!]);
|
|
expect(recovered).toEqual(secret);
|
|
});
|
|
|
|
it('all C(5,3) subsets reconstruct', () => {
|
|
const secret = new Uint8Array([42, 137, 255, 0]);
|
|
const shares = split(secret, 5, 3);
|
|
for (let i = 0; i < 5; i++) {
|
|
for (let j = i + 1; j < 5; j++) {
|
|
for (let l = j + 1; l < 5; l++) {
|
|
const recovered = combine([shares[i]!, shares[j]!, shares[l]!]);
|
|
expect(recovered).toEqual(secret);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
it('share indices are 1..N', () => {
|
|
const shares = split(new Uint8Array([42]), 5, 3);
|
|
expect(shares.map(s => s.x)).toEqual([1, 2, 3, 4, 5]);
|
|
});
|
|
|
|
it('throws on K < 2', () => {
|
|
expect(() => split(new Uint8Array([1]), 3, 1)).toThrow('Threshold K must be at least 2');
|
|
});
|
|
|
|
it('throws on N < K', () => {
|
|
expect(() => split(new Uint8Array([1]), 2, 3)).toThrow('Share count N must be >= threshold K');
|
|
});
|
|
|
|
it('throws on N > 255', () => {
|
|
expect(() => split(new Uint8Array([1]), 256, 2)).toThrow('Maximum 255 shares');
|
|
});
|
|
|
|
it('throws on empty secret', () => {
|
|
expect(() => split(new Uint8Array(0), 3, 2)).toThrow('Secret must not be empty');
|
|
});
|
|
|
|
it('throws on duplicate shares', () => {
|
|
expect(() => combine([
|
|
{ x: 1, y: new Uint8Array([1]) },
|
|
{ x: 1, y: new Uint8Array([2]) },
|
|
])).toThrow('Duplicate share indices');
|
|
});
|
|
|
|
it('throws on mismatched lengths', () => {
|
|
expect(() => combine([
|
|
{ x: 1, y: new Uint8Array([1, 2]) },
|
|
{ x: 2, y: new Uint8Array([3]) },
|
|
])).toThrow('same data length');
|
|
});
|
|
|
|
it('large secret (256 bytes)', () => {
|
|
const secret = new Uint8Array(256);
|
|
for (let i = 0; i < 256; i++) secret[i] = i;
|
|
const shares = split(secret, 10, 5);
|
|
const recovered = combine(shares.slice(0, 5));
|
|
expect(recovered).toEqual(secret);
|
|
});
|
|
});
|