meck93/evote-crypto

View on GitHub
src/ff-elgamal/encryption.ts

Summary

Maintainability
A
0 mins
Test Coverage
/**
* 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 semicolon
import BN = require('bn.js')
Missing semicolon
import { GlobalHelper } from '../index'
Missing semicolon
import { Cipher, SystemParameters, isCipher, isSystemParameters } from './index'
 
// encode a message m to g^m
export const encodeMessage = (m: number | BN, sysParams: SystemParameters): BN => {
Missing semicolon
isSystemParameters(sysParams)
Missing semicolon
m = typeof m === 'number' ? GlobalHelper.newBN(m) : m
Missing semicolon
return GlobalHelper.powBN(sysParams.g, m, sysParams.p)
Missing semicolon
}
 
// decode a message g^m to m
TODO found
// TODO: use baby-step giant-step instead of brute force
export 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 m
Missing 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*mh
export 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 m
Missing 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 m
Missing semicolon
}
 
// homomorphic addition
export 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 share
export 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 shares
export 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.p
Missing semicolon
)
 
Missing semicolon
return decodeMessage(mh, params)
Missing semicolon
}