epir
Version:
EllipticPIR client library (Node.js / TypeScript bindings).
79 lines (66 loc) • 3.1 kB
text/typescript
import { DecryptionContextBase, SelectorFactoryBase, CIPHER_SIZE, MG_DEFAULT_PATH } from '../types';
import { createDecryptionContext, SelectorFactory } from '../addon';
import { privkey, pubkey, idx } from './addon';
export const checkSelector = (
decCtx: DecryptionContextBase, privkey: ArrayBuffer, indexCounts: number[], idx: number, selector: ArrayBuffer): boolean => {
const nCiphers = indexCounts.reduce((acc, v) => acc + v, 0);
if(selector.byteLength != nCiphers * CIPHER_SIZE) return false;
let prod = indexCounts.reduce((acc, v) => acc * v, 1);
let offset = 0;
for(let ic=0; ic<indexCounts.length; ic++) {
const cols = indexCounts[ic];
prod /= cols;
const rows = Math.floor(idx / prod);
idx -= rows * prod;
for(let r=0; r<cols; r++) {
const msg = (r == rows ? 1 : 0);
const decrypted = decCtx.decryptCipher(privkey, selector.slice(offset * CIPHER_SIZE, (offset + 1) * CIPHER_SIZE));
if(decrypted != msg) return false;
offset++;
}
}
return true;
};
const INDEX_COUNTS = [100, 100, 100];
const CAPACITIES = [1000, 10];
export const runTests = (
createSelectorFactory: (isFast: boolean, key: ArrayBuffer, capacities?: number[]) => SelectorFactoryBase): void => {
const decCtxPromise = createDecryptionContext(MG_DEFAULT_PATH);
test('normal', async () => {
const decCtx = await decCtxPromise;
const selectorFactory = createSelectorFactory(false, pubkey.buffer, CAPACITIES);
await selectorFactory.fill();
const selector = selectorFactory.create(INDEX_COUNTS, idx);
expect(checkSelector(decCtx, privkey.buffer, INDEX_COUNTS, idx, selector)).toBe(true);
});
test('fast', async () => {
const decCtx = await decCtxPromise;
const selectorFactory = createSelectorFactory(true, privkey.buffer, CAPACITIES);
await selectorFactory.fill();
const selector = selectorFactory.create(INDEX_COUNTS, idx);
expect(checkSelector(decCtx, privkey.buffer, INDEX_COUNTS, idx, selector)).toBe(true);
});
test('insufficient', async () => {
const selectorFactory = createSelectorFactory(true, privkey.buffer, [100, 10]);
await selectorFactory.fill();
expect(() => { selectorFactory.create(INDEX_COUNTS, idx) }).toThrow(/^Insufficient ciphers cache\.$/);
});
test('fill twice', async () => {
const decCtx = await decCtxPromise;
const selectorFactory = createSelectorFactory(true, privkey.buffer, CAPACITIES);
await selectorFactory.fill();
await selectorFactory.fill();
const selector = selectorFactory.create(INDEX_COUNTS, idx);
expect(checkSelector(decCtx, privkey.buffer, INDEX_COUNTS, idx, selector)).toBe(true);
});
test('don\'t refill', async () => {
const decCtx = await decCtxPromise;
const selectorFactory = createSelectorFactory(true, privkey.buffer, CAPACITIES);
await selectorFactory.fill();
const selector = selectorFactory.create(INDEX_COUNTS, idx, false);
expect(checkSelector(decCtx, privkey.buffer, INDEX_COUNTS, idx, selector)).toBe(true);
});
};
if(require.main === null) {
runTests((isFast: boolean, key: ArrayBuffer, capacities?: number[]) => new SelectorFactory(isFast, key, capacities));
}