UNPKG

epir

Version:

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

96 lines (88 loc) 3.16 kB
import { MG_SIZE } from './types'; import { createLibEpirHelper, LibEpirHelper } from './wasm.libepir'; import { arrayBufferConcat } from './util'; const worker: Worker = self as unknown as Worker; // For mG.bin generation. const mGGenerateCompute = async ( helper: LibEpirHelper, params: { nThreads: number, mmax: number, ctx: ArrayBuffer, mG_p3: ArrayBuffer, threadId: number, cbInterval: number }) => { const mG_count = Math.ceil(params.mmax / params.nThreads) - 1; const ctx_ = helper.malloc(params.ctx); const mG_ = helper.malloc(mG_count * MG_SIZE); const mG_p3_ = helper.malloc(params.mG_p3); let pointsComputed = 0; const cb = helper.addFunction(() => { pointsComputed++; if(pointsComputed % params.cbInterval == 0 || pointsComputed === mG_count) { worker.postMessage({ method: 'mg_generate_cb', pointsComputed: pointsComputed }); } }, 'vi'); // Run. helper.call('mG_generate_compute', ctx_, mG_, mG_count, mG_p3_, params.nThreads + params.threadId, params.nThreads, cb, null); helper.removeFunction(cb); // Sort. helper.call('mG_sort', mG_, mG_count); const mG = helper.slice(mG_, mG_count * MG_SIZE); helper.free(ctx_); helper.free(mG_); helper.free(mG_p3_); worker.postMessage({ method: 'mg_generate_compute', mG: mG, }, [mG]); }; // For selector creation. const selectorCreate = async ( helper: LibEpirHelper, params: { choices: ArrayBuffer, key: ArrayBuffer, random: ArrayBuffer, isFast: boolean }) => { const key_ = helper.malloc(params.key); const cipher_ = helper.malloc(64); const random_ = helper.malloc(32); const encryptFn = (params.isFast ? 'ecelgamal_encrypt_fast' : 'ecelgamal_encrypt'); const choicesView = new Uint8Array(params.choices); const selector: ArrayBuffer[] = []; for(let i=0; i<params.choices.byteLength; i++) { helper.set(params.random, i * 32, 32, random_); helper.call(encryptFn, cipher_, key_, choicesView[i], 0, random_); selector.push(helper.slice(cipher_, 64)); } const selectorConcat = arrayBufferConcat(selector); worker.postMessage({ method: 'selector_create', selector: selectorConcat, }, [selectorConcat]); helper.free(key_); helper.free(cipher_); helper.free(random_); }; // For reply decryption. const decryptMGMany = async ( helper: LibEpirHelper, params: { ciphers: ArrayBuffer, privkey: ArrayBuffer }) => { const privkey_ = helper.malloc(params.privkey); const cipher_ = helper.malloc(64); const mG = new Uint8Array(32 * (params.ciphers.byteLength / 64)); for(let i=0; 64*i<params.ciphers.byteLength; i++) { helper.set(params.ciphers, i * 64, 64, cipher_); helper.call('ecelgamal_decrypt_to_mG', privkey_, cipher_); mG.set(helper.subarray(cipher_, 32), i * 32); } worker.postMessage({ method: 'decrypt_mG_many', mG: mG.buffer, }, [mG.buffer]); helper.free(privkey_); helper.free(cipher_); }; worker.onmessage = async (ev) => { const helper = await createLibEpirHelper(); switch(ev.data.method) { case 'mg_generate_compute': mGGenerateCompute(helper, ev.data); break; case 'selector_create': selectorCreate(helper, ev.data); break; case 'decrypt_mG_many': decryptMGMany(helper, ev.data); break; } };