src/ff-elgamal/encryption.ts
/** * Encryption * * ElGamal Finite Field Encryption * - encode and decode messages * - encrypt and decrypt messages * - homomorphically add encrypted messages * - decrypt cipher texts with a private key share * - combine decrypted shares */ Missing semicolonimport BN = require('bn.js')Missing semicolonimport { GlobalHelper } from '../index'Missing semicolonimport { Cipher, SystemParameters, isCipher, isSystemParameters } from './index' // encode a message m to g^mexport const encodeMessage = (m: number | BN, sysParams: SystemParameters): BN => {Missing semicolon isSystemParameters(sysParams)Missing semicolon m = typeof m === 'number' ? GlobalHelper.newBN(m) : mMissing semicolon return GlobalHelper.powBN(sysParams.g, m, sysParams.p)Missing semicolon} // decode a message g^m to mTODO found// TODO: use baby-step giant-step instead of brute forceexport const decodeMessage = (mh: number | BN, sysParams: SystemParameters): BN => {Missing semicolon isSystemParameters(sysParams)Missing semicolon mh = typeof mh === 'number' ? GlobalHelper.newBN(mh) : mh Missing semicolon let m = GlobalHelper.newBN(0) while (!GlobalHelper.timingSafeEqualBN(encodeMessage(m, sysParams), mh)) {Missing semicolon m = m.add(GlobalHelper.newBN(1)) }Missing semicolon return mMissing semicolon} TODO found// TODO: test encryption and both decryption for the whole message range// (to verify the correct implementation and usage of decodeMessage) // Finite Field ElGamal Encryption//// given:// - p: prime number// - g: generator// - h: public key (g^privateKey)// - m: message//// steps:// 1. pick random value r: 0 < r < q// 2. compute c1 = g^r// 3. compute s = h^r// 4. compute mh = g^message (encode it to make it "homomorphic")// 5. compute c2 = s*mhexport const encrypt = ( message: number | BN, sysParams: SystemParameters, publicKey: BN, log = false): Cipher => {Missing semicolon isSystemParameters(sysParams)Missing semicolon const m = typeof message === 'number' ? GlobalHelper.newBN(message) : message Missing semicolon const r = GlobalHelper.getSecureRandomValue(sysParams.q)Missing semicolon const c1 = GlobalHelper.powBN(sysParams.g, r, sysParams.p)Missing semicolon const s = GlobalHelper.powBN(publicKey, r, sysParams.p)Missing semicolon const mh = encodeMessage(m, sysParams)Missing semicolon const c2 = GlobalHelper.mulBN(s, mh, sysParams.p) unused expression, expected an assignment or function call
Missing semicolon log && console.log('enc secret (r)', r)unused expression, expected an assignment or function call
Missing semicolon log && console.log('a\t\t', c1)unused expression, expected an assignment or function call
Missing semicolon log && console.log('h^r\t\t', s)Missing semicolon
unused expression, expected an assignment or function call log && console.log('g^m\t\t', mh)unused expression, expected an assignment or function call
Missing semicolon log && console.log('b\t\t', c2)unused expression, expected an assignment or function call
Missing semicolon log && console.log('------------------------') Missing semicolon return { a: c1, b: c2, r }Missing semicolon} // Finite Field ElGamal Decryption//// given:// - p: prime number// - g: generator// - x: private key// - c1,c2: cipher//// steps:// 1. compute s = c1^x// 2. compute s^-1 = multiplicative inverse of s// 3. compute mh = c2 * s^-1// 4. compute m (decode mh using brute force)export const decrypt1 = ( cipherText: Cipher, sk: BN, sysParams: SystemParameters, log = false): BN => {Missing semicolon isCipher(cipherText)Missing semicolon isSystemParameters(sysParams) Missing semicolon const { a: c1, b: c2 } = cipherText Missing semicolon const s = GlobalHelper.powBN(c1, sk, sysParams.p)Missing semicolon const sInverse = GlobalHelper.invmBN(s, sysParams.p)Missing semicolon const mh = GlobalHelper.mulBN(c2, sInverse, sysParams.p)Missing semicolon const m = decodeMessage(mh, sysParams) unused expression, expected an assignment or function call
Missing semicolon log && console.log('s\t\t', s)unused expression, expected an assignment or function call
Missing semicolon log && console.log('s^-1\t\t', sInverse)Missing semicolon
unused expression, expected an assignment or function call log && console.log('mh\t\t', mh)Missing semicolon
unused expression, expected an assignment or function call log && console.log('plaintext d1\t', m)Missing semicolon
unused expression, expected an assignment or function call log && console.log('------------------------') Missing semicolon return mMissing semicolon} // Finite Field ElGamal Decryption Alternative (using Euler's Theorem)//// given:// - p: prime number// - g: generator// - x: private key// - c1,c2: cipher//// steps:// 1. compute s = c1^x// 2. compute s^-1 = multiplicative inverse of s// 3. compute s^(p-2)// 4. compute mh = c2 * s^(p-2)// 5. compute m (decode mh using brute force)export const decrypt2 = ( cipherText: Cipher, sk: BN, sysParams: SystemParameters, log = false): BN => {Missing semicolon isCipher(cipherText)Missing semicolon isSystemParameters(sysParams) Missing semicolon const { a: c1, b: c2 } = cipherText Missing semicolon const s = GlobalHelper.powBN(c1, sk, sysParams.p)Missing semicolon const sPowPMinus2 = GlobalHelper.powBN(s, sysParams.p.sub(GlobalHelper.newBN(2)), sysParams.p)Missing semicolon const mh = GlobalHelper.mulBN(c2, sPowPMinus2, sysParams.p)Missing semicolon const m = decodeMessage(mh, sysParams) Missing semicolon
unused expression, expected an assignment or function call log && console.log('s\t\t', s)Missing semicolon
unused expression, expected an assignment or function call log && console.log('s^(p-2)\t\t', sPowPMinus2)unused expression, expected an assignment or function call
Missing semicolon log && console.log('mh\t', mh)Missing semicolon
unused expression, expected an assignment or function call log && console.log('plaintext d2\t', m)unused expression, expected an assignment or function call
Missing semicolon log && console.log('------------------------') Missing semicolon return mMissing semicolon} // homomorphic additionexport const add = (em1: Cipher, em2: Cipher, sysParams: SystemParameters): Cipher => {Missing semicolon isCipher(em1)Missing semicolon isCipher(em2)Missing semicolon isSystemParameters(sysParams) return { a: GlobalHelper.mulBN(em1.a, em2.a, sysParams.p), b: GlobalHelper.mulBN(em1.b, em2.b, sysParams.p),Missing semicolon }Missing semicolon} // decrypt a cipher text with a private key shareexport const decryptShare = (params: SystemParameters, cipher: Cipher, secretKeyShare: BN): BN => {Missing semicolon isSystemParameters(params)Missing semicolon isCipher(cipher)Missing semicolon return GlobalHelper.powBN(cipher.a, secretKeyShare, params.p)Missing semicolon} // combine decrypted sharesexport const combineDecryptedShares = ( params: SystemParameters, cipher: Cipher, decryptedShares: BN[]): BN => {Missing semicolon isSystemParameters(params)Missing semicolon isCipher(cipher) const mh = GlobalHelper.divBN( cipher.b, decryptedShares.reduce((product, share) => GlobalHelper.mulBN(product, share, params.p)), params.pMissing semicolon ) Missing semicolon return decodeMessage(mh, params)Missing semicolon}