UNPKG

epir

Version:

EllipticPIR client library (Node.js / TypeScript bindings).

216 lines (179 loc) 6.98 kB
import crypto from 'crypto'; import { EpirCreateFunction, DecryptionContextCreateFunction, SCALAR_SIZE, CIPHER_SIZE, MG_DEFAULT_PATH } from '../types'; import { createEpir, createDecryptionContext } from '../addon'; export let x: number; export let y: number; export let z: number; export let w: number; export const xorshift_init = (): void => { x = 123456789; y = 362436069; z = 521288629; w = 88675123; }; export const shiftL = (n: number, cnt: number): number => { return (n * (2 ** cnt)) & 0xffffffff; }; export const xorshift = (): number => { const t = x ^ (shiftL(x, 11)); x = y; y = z; z = w; w = (w ^ (w >>> 19)) ^ (t ^ (t >>> 8)); return w; }; export const sha256sum = (buf: ArrayBuffer): ArrayBuffer => { const hash = crypto.createHash('sha256'); hash.update(new Uint8Array(buf)); return new Uint8Array(Buffer.from(hash.digest('hex'), 'hex')); }; export const generateRandomScalars = (cnt: number): ArrayBuffer => { const r = new Uint8Array(cnt * SCALAR_SIZE); xorshift_init(); for(let i=0; i<cnt; i++) { for(let j=0; j<SCALAR_SIZE; j++) { r[i * SCALAR_SIZE + j] = xorshift() & 0xff; } r[(i + 1) * SCALAR_SIZE - 1] &= 0x1f; } return r.buffer; }; export const privkey = new Uint8Array([ 0x7e, 0xf6, 0xad, 0xd2, 0xbe, 0xd5, 0x9a, 0x79, 0xba, 0x6e, 0xdc, 0xfb, 0xa4, 0x8f, 0xde, 0x7a, 0x55, 0x31, 0x75, 0x4a, 0xf5, 0x93, 0x76, 0x34, 0x6c, 0x8b, 0x52, 0x84, 0xee, 0xf2, 0x52, 0x07 ]); export const pubkey = new Uint8Array([ 0x9c, 0x76, 0x82, 0x3d, 0xbd, 0xb9, 0xbf, 0x04, 0x8f, 0xc5, 0xc2, 0xaf, 0x00, 0x0e, 0x28, 0xa1, 0x48, 0xee, 0x02, 0x19, 0x99, 0xfb, 0x7f, 0x21, 0xca, 0x1f, 0x84, 0xb8, 0xfe, 0x73, 0xd7, 0xe8 ]); export const msg = 0x12345678 & ((1 << 24) - 1); export const r = new Uint8Array([ 0x42, 0xff, 0x2d, 0x98, 0x4a, 0xe5, 0xa2, 0x8f, 0x7d, 0x02, 0x69, 0x87, 0xc7, 0x10, 0x9a, 0x7b, 0x3a, 0x1d, 0x36, 0x58, 0x82, 0x5a, 0x09, 0x17, 0xe1, 0x69, 0x3e, 0x83, 0xa5, 0x71, 0x5d, 0x09 ]); export const cipher = new Uint8Array([ 0x11, 0xa9, 0x4e, 0xb7, 0x18, 0x53, 0x7e, 0x94, 0x7d, 0x0f, 0xf3, 0x0c, 0xdd, 0xae, 0x16, 0xae, 0xab, 0x42, 0x9e, 0xac, 0x09, 0x2b, 0x22, 0x00, 0x06, 0xb1, 0x9c, 0xcc, 0xb5, 0x26, 0xb4, 0x30, 0xeb, 0x76, 0x83, 0xc0, 0xdf, 0x90, 0x3a, 0x88, 0xf6, 0xf1, 0x09, 0x52, 0xbc, 0xa4, 0xd6, 0x45, 0x28, 0x4f, 0xf7, 0xed, 0x95, 0xc6, 0xa4, 0xe9, 0x67, 0xf5, 0xe7, 0xae, 0x22, 0xc9, 0x33, 0xcb ]); export const mGHash = new Uint8Array([ 0x1c, 0x09, 0xf4, 0x62, 0xf1, 0xb5, 0x8f, 0xc1, 0x40, 0xc9, 0x3c, 0xda, 0x6f, 0xec, 0x88, 0x85, 0x08, 0x44, 0xe3, 0xf0, 0x04, 0xb7, 0x24, 0x87, 0xb6, 0x53, 0x39, 0xbd, 0xc0, 0xe4, 0x17, 0x97 ]); export const index_counts = [1000, 1000, 1000]; export const ciphers_count = 3000; export const elements_count = 1000 * 1000 * 1000; export const idx = 12345678; export const rows = [ Math.floor(idx / (1000 * 1000)), Math.floor((idx % (1000 * 1000)) / 1000), (idx % 1000) ]; export const selectorHash = new Uint8Array([ 0xda, 0x20, 0x9d, 0x4f, 0x85, 0xad, 0x0d, 0xb2, 0x68, 0x45, 0x6f, 0x0d, 0x4e, 0x9e, 0x90, 0x7f, 0x8f, 0x87, 0x31, 0xa6, 0x69, 0x5d, 0xa5, 0x5f, 0x1f, 0x3d, 0x19, 0x2f, 0x59, 0xac, 0xe9, 0x0c ]); export const runTests = (createEpir: EpirCreateFunction, createDecryptionContext: DecryptionContextCreateFunction): void => { const epirPromise = createEpir(); const decCtxPromise = createDecryptionContext(MG_DEFAULT_PATH); describe('ECElGamal', () => { test('create private key', async () => { const epir = await epirPromise; const privkey = epir.createPrivkey(); expect(privkey.byteLength).toBe(SCALAR_SIZE); }); test('create public key', async () => { const epir = await epirPromise; const pubkeyTest = epir.createPubkey(privkey.buffer); expect(new Uint8Array(pubkeyTest)).toEqual(pubkey); }); test('encrypt (normal)', async () => { const epir = await epirPromise; const cipherTest = epir.encrypt(pubkey.buffer, msg, r.buffer); expect(new Uint8Array(cipherTest)).toEqual(cipher); }); test('encrypt (fast)', async () => { const epir = await epirPromise; const cipherTest = epir.encryptFast(privkey.buffer, msg, r.buffer); expect(new Uint8Array(cipherTest)).toEqual(cipher); }); test('create DecryptionContext from ArrayBuffer', async () => { const decCtx = await decCtxPromise; const decCtx2 = await createDecryptionContext(decCtx.getMG()); const mG = decCtx2.getMG(); expect(sha256sum(mG)).toEqual(mGHash); }, 30 * 1000); //test('interpolation search of mG', async () => { //}); test('decrypt (success)', async () => { const decCtx = await decCtxPromise; expect(decCtx.decryptCipher(privkey.buffer, cipher.buffer)).toBe(msg); }); test('decrypt (fail)', async () => { const decCtx = await decCtxPromise; expect(() => decCtx.decryptCipher(pubkey.buffer, cipher.buffer)).toThrow(/^Failed to decrypt\.$/); }); test('random encrypt (normal)', async () => { const epir = await epirPromise; const decCtx = await decCtxPromise; const cipherTest = epir.encrypt(pubkey.buffer, msg); expect(decCtx.decryptCipher(privkey.buffer, cipherTest)).toBe(msg); }); test('random encrypt (fast)', async () => { const epir = await epirPromise; const decCtx = await decCtxPromise; const cipherTest = epir.encryptFast(privkey.buffer, msg); expect(decCtx.decryptCipher(privkey.buffer, cipherTest)).toBe(msg); }); }); describe('Selector', () => { test('ciphers count', async () => { const epir = await epirPromise; expect(epir.ciphersCount(index_counts)).toBe(ciphers_count); }); test('elements count', async () => { const epir = await epirPromise; expect(epir.elementsCount(index_counts)).toBe(elements_count); }); //test('create choice', async () => { //}); test('create selector (deterministic, normal)', async () => { const epir = await epirPromise; const selector = await epir.createSelector(pubkey.buffer, index_counts, idx, generateRandomScalars(ciphers_count)); expect(sha256sum(selector)).toEqual(selectorHash); }, 30 * 1000); test('create selector (deterministic, fast)', async () => { const epir = await epirPromise; const selector = await epir.createSelectorFast(privkey.buffer, index_counts, idx, generateRandomScalars(ciphers_count)); expect(sha256sum(selector)).toEqual(selectorHash); }, 30 * 1000); test('create selector (random, normal)', async () => { const epir = await epirPromise; const selector = await epir.createSelector(pubkey.buffer, index_counts, idx); expect(selector.byteLength).toBe(ciphers_count * CIPHER_SIZE); }, 30 * 1000); test('create selector (random, fast)', async () => { const epir = await epirPromise; const selector = await epir.createSelectorFast(privkey.buffer, index_counts, idx); expect(selector.byteLength).toBe(ciphers_count * CIPHER_SIZE); }, 30 * 1000); }); }; if(require.main === null) { runTests(createEpir, createDecryptionContext); }