UNPKG

@beraji/wallet-sdk

Version:

Beraji: Distributed Secret Sharing.

119 lines 5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ExtendedElGamal = exports.ElGamal = exports.parity = exports.xor = void 0; const utils_1 = require("@noble/hashes/utils"); const edtss_1 = require("./edtss"); const xor = (a, b) => { if (a.length !== b.length) throw new Error('Invalid buffer length'); const c = new Uint8Array(a.length); for (let i = 0; i < a.length; i++) c[i] = a[i] ^ b[i]; return c; }; exports.xor = xor; const parity = (a) => { let b = a.reduce((x, y) => x ^ y, 0); b = b ^ (b >> 1); b = b ^ (b >> 2); b = b ^ (b >> 4); return b & 1; }; exports.parity = parity; class ElGamal { constructor() { this.encrypt = (msg, pubkey) => { if (msg.length != ElGamal.plainTextLength) throw new Error(`Invalid block length. It must be 32 bytes instead of ${msg.length} bytes.`); const r = edtss_1.EdCurve.ff.rand(); const R = edtss_1.EdCurve.baseMul(r); const m = (0, exports.xor)(msg, R); if ((0, utils_1.bytesToHex)(m) !== (0, utils_1.bytesToHex)(edtss_1.EdCurve.ff.norm(m))) return this.encrypt(msg, pubkey); const s = edtss_1.EdCurve.mulScalar(pubkey, r); const c = edtss_1.EdCurve.ff.add(m, s); return new Uint8Array([...R, ...c]); }; this.decrypt = (cipher, privkey) => { if (privkey.length !== ElGamal.privateKeyLength) throw new Error('Invalid private key length'); if (cipher.length !== ElGamal.cipherTextLength) throw new Error('Invalid cipher text length'); const priv = edtss_1.EdCurve.getDerivedKey(privkey); const R = cipher.subarray(0, 32); const c = cipher.subarray(32, ElGamal.cipherTextLength); const s = edtss_1.EdCurve.mulScalar(R, priv); const m = edtss_1.EdCurve.ff.sub(c, s); const msg = (0, exports.xor)(m, R); return msg; }; } } exports.ElGamal = ElGamal; ElGamal.publicKeyLength = 32; ElGamal.privateKeyLength = 32; ElGamal.plainTextLength = 32; ElGamal.cipherTextLength = 64; class ExtendedElGamal { constructor() { this._enc = (msg, pubkey) => { const length = msg.length; if (length > ExtendedElGamal.plainTextLength) throw new Error(`Invalid block length. It must be 30 bytes instead of ${length} bytes.`); const par = (0, exports.parity)(msg); const padding = (0, utils_1.randomBytes)(ExtendedElGamal.plainTextLength - length); const m = new Uint8Array([par, length, ...padding, ...msg]); const r = edtss_1.EdCurve.ff.rand(); const R = edtss_1.EdCurve.baseMul(r); const s = edtss_1.EdCurve.mulScalar(pubkey, r); const c = (0, exports.xor)(m, s); return new Uint8Array([...R, ...c]); }; this._dec = (cipher, privkey) => { if (privkey.length !== ExtendedElGamal.privateKeyLength) throw new Error('Invalid private key length'); if (cipher.length % ExtendedElGamal.cipherTextLength !== 0) throw new Error('Invalid cipher text length'); const R = cipher.subarray(0, 32); const c = cipher.subarray(32, ExtendedElGamal.cipherTextLength); const s = edtss_1.EdCurve.mulScalar(R, privkey); const p = (0, exports.xor)(c, s); const par = p[0]; const length = p[1]; const msg = p.subarray(ExtendedElGamal.blockLength - length, ExtendedElGamal.blockLength); if (par !== (0, exports.parity)(msg)) throw new Error('Incorrect cipher text'); return msg; }; this.encrypt = (m, pubkey) => { let c = []; let offset = 0; while (offset < m.length) { c.push([ ...this._enc(m.subarray(offset, offset + ExtendedElGamal.plainTextLength), pubkey), ]); offset = offset + ExtendedElGamal.plainTextLength; } return new Uint8Array(c.flat()); }; this.decrypt = (c, privkey) => { const priv = edtss_1.EdCurve.getDerivedKey(privkey); let m = []; let offset = 0; while (offset < c.length) { m.push([ ...this._dec(c.subarray(offset, offset + ExtendedElGamal.cipherTextLength), priv), ]); offset = offset + ExtendedElGamal.cipherTextLength; } return new Uint8Array(m.flat()); }; } } exports.ExtendedElGamal = ExtendedElGamal; ExtendedElGamal.publicKeyLength = 32; ExtendedElGamal.privateKeyLength = 32; ExtendedElGamal.blockLength = 32; ExtendedElGamal.plainTextLength = 30; ExtendedElGamal.cipherTextLength = 64; //# sourceMappingURL=elgamal.js.map