2018-06-12 12:31:38 +00:00
|
|
|
/*
|
|
|
|
|
|
|
|
|
2018-07-07 08:52:47 +00:00
|
|
|
Code by Bingsheng Zhang, Thomas Smith, Vincent de Almeida
|
2018-06-12 12:31:38 +00:00
|
|
|
|
2018-07-07 08:52:47 +00:00
|
|
|
Dependencies can be found in 'package.json' and installed using 'npm install'
|
2018-06-12 12:31:38 +00:00
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
var port = 8080;
|
|
|
|
|
|
|
|
var Buffer = require('buffer').Buffer;
|
2018-07-07 08:52:47 +00:00
|
|
|
var CTX = require('milagro-crypto-js');
|
|
|
|
|
|
|
|
var express = require('express');
|
|
|
|
var bodyParser = require("body-parser");
|
2018-06-12 12:31:38 +00:00
|
|
|
var app = express();
|
|
|
|
|
2018-07-07 08:52:47 +00:00
|
|
|
// Express server configuration
|
2018-06-12 12:31:38 +00:00
|
|
|
app.use(express.static('test'));
|
2018-07-07 08:52:47 +00:00
|
|
|
app.use(bodyParser.urlencoded({ extended: false }));
|
|
|
|
app.use(bodyParser.json());
|
|
|
|
|
2018-06-12 12:31:38 +00:00
|
|
|
//default test
|
|
|
|
app.get('/', function(request, response){
|
|
|
|
|
|
|
|
var data = {
|
|
|
|
message: 'hello world',
|
|
|
|
value: 5
|
2018-07-07 08:52:47 +00:00
|
|
|
};
|
2018-06-12 12:31:38 +00:00
|
|
|
|
|
|
|
|
|
|
|
//response.send('Hey there'+request.ip);
|
|
|
|
response.json(data);
|
|
|
|
console.log('request from'+request.ip);
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
//parameter generation function
|
|
|
|
app.get('/param', function(request, response){
|
|
|
|
var param = gpGen();
|
|
|
|
|
|
|
|
console.log('Generated Param:' + param);
|
|
|
|
response.json(param);
|
|
|
|
|
2018-07-07 08:52:47 +00:00
|
|
|
});
|
2018-06-12 12:31:38 +00:00
|
|
|
|
|
|
|
//combine public keys and return the full combined one - JSON Version
|
|
|
|
app.get('/combpk', function(request, response){
|
2018-07-07 08:52:47 +00:00
|
|
|
console.log('\nEndpoint /combpk called');
|
2018-06-12 12:31:38 +00:00
|
|
|
|
2018-07-07 08:52:47 +00:00
|
|
|
var partials = request.query['PK'];
|
2018-06-12 12:31:38 +00:00
|
|
|
|
|
|
|
var parsed = [];
|
|
|
|
|
|
|
|
|
|
|
|
console.log('Combining...');
|
|
|
|
for (var i = partials.length - 1; i >= 0; i--) {
|
|
|
|
console.log('PK' +i+ ': '+partials[i]);
|
|
|
|
parsed.push(JSON.parse(partials[i]));
|
|
|
|
}
|
|
|
|
|
2018-07-07 08:52:47 +00:00
|
|
|
var PK = combine_pks(parsed);
|
2018-06-12 12:31:38 +00:00
|
|
|
response.json(PK);
|
|
|
|
|
2018-07-07 08:52:47 +00:00
|
|
|
});
|
2018-06-12 12:31:38 +00:00
|
|
|
|
|
|
|
|
|
|
|
//byte array version
|
2018-07-07 08:52:47 +00:00
|
|
|
app.post('/cmpkstring', function(request, response){
|
|
|
|
console.log('\nEndpoint /cmpkstring called');
|
2018-06-12 12:31:38 +00:00
|
|
|
var ctx = new CTX("BN254CX");
|
|
|
|
|
2018-07-07 08:52:47 +00:00
|
|
|
var partials = request.body.PKs;
|
2018-06-12 12:31:38 +00:00
|
|
|
var parsed = [];
|
|
|
|
|
2018-07-07 08:52:47 +00:00
|
|
|
if(partials.length > 1)//if we're submitting more than one key
|
2018-06-12 12:31:38 +00:00
|
|
|
{
|
2018-07-07 08:52:47 +00:00
|
|
|
console.log('Combining ' + partials.length + " public keys into one...");
|
2018-06-12 12:31:38 +00:00
|
|
|
for (var i = partials.length - 1; i >= 0; i--) {
|
2018-07-07 08:52:47 +00:00
|
|
|
console.log('PK' + i + ': ' + partials[i]);
|
|
|
|
var bytes = Buffer.from(partials[i].split(','), 'hex');
|
|
|
|
var pk = new ctx.ECP.fromBytes(bytes);
|
|
|
|
parsed.push(pk);
|
2018-06-12 12:31:38 +00:00
|
|
|
}
|
|
|
|
}
|
2018-07-07 08:52:47 +00:00
|
|
|
else if(partials.length === 1)
|
2018-06-12 12:31:38 +00:00
|
|
|
{
|
2018-07-07 08:52:47 +00:00
|
|
|
console.log("Combining just one public key...");
|
|
|
|
var bytes = Buffer.from(partials[0].split(','), 'hex');
|
2018-06-12 12:31:38 +00:00
|
|
|
var pk = new ctx.ECP.fromBytes(bytes);
|
|
|
|
parsed.push(pk);
|
|
|
|
}
|
|
|
|
|
2018-07-07 08:52:47 +00:00
|
|
|
response.json(combine_pks(parsed));
|
|
|
|
});
|
2018-06-12 12:31:38 +00:00
|
|
|
|
|
|
|
|
|
|
|
//addition function on homomorphically encrypted variables
|
|
|
|
//this may need some work, different method of serialisation maybe?
|
|
|
|
app.get('/addec', function(request, response){
|
|
|
|
var c1 = request.query['C1'];
|
|
|
|
var c2 = request.query['C2'];
|
|
|
|
var number = request.query['number']; //number of ciphertexts to add
|
|
|
|
//all the list of ciphertext objects to give to the function
|
|
|
|
var parsed = [];
|
|
|
|
|
|
|
|
var ctx = new CTX("BN254CX");
|
|
|
|
console.log('Addec:');
|
|
|
|
|
|
|
|
if(number == c1.length)
|
|
|
|
{
|
|
|
|
for (var i = 0; i < c1.length; i++) {
|
|
|
|
console.log(i + ".C1: " + c1[i]);
|
|
|
|
var c1Bytes = Buffer.from(c1[i].split(','), 'hex');
|
|
|
|
var newC1 = new ctx.ECP.fromBytes(c1Bytes);
|
|
|
|
|
|
|
|
var cipher =
|
|
|
|
{
|
|
|
|
C1:newC1,
|
|
|
|
C2:null
|
|
|
|
};
|
|
|
|
parsed.push(cipher);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
for (var j = 0; j < c2.length; j++) {
|
|
|
|
console.log(j + ".C2: " + c2[j]);
|
|
|
|
var c2Bytes = Buffer.from(c2[j].split(','), 'hex');
|
|
|
|
var newC2 = new ctx.ECP.fromBytes(c2Bytes);
|
|
|
|
|
|
|
|
parsed[j].C2 = newC2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
else if(number == 1)
|
|
|
|
{
|
|
|
|
console.log("only one cipher");
|
|
|
|
var c1Bytes = Buffer.from(c1.split(','), 'hex');
|
|
|
|
var newC1 = new ctx.ECP.fromBytes(c1Bytes);
|
|
|
|
console.log("C1: " + c1);
|
|
|
|
var c2Bytes = Buffer.from(c2.split(','), 'hex');
|
|
|
|
var newC2 = new ctx.ECP.fromBytes(c2Bytes);
|
|
|
|
console.log("C2: " + c2);
|
|
|
|
|
|
|
|
var cipher =
|
|
|
|
{
|
|
|
|
C1:newC1,
|
|
|
|
C2:newC2
|
|
|
|
};
|
|
|
|
parsed.push(cipher);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
response.json(add(parsed));
|
2018-07-07 08:52:47 +00:00
|
|
|
});
|
2018-06-12 12:31:38 +00:00
|
|
|
|
|
|
|
|
|
|
|
//tally partially decrypted ciphertexts
|
|
|
|
app.get('/tally', function(request, response){
|
2018-07-07 08:52:47 +00:00
|
|
|
console.log("\nEndpoint /tally called");
|
2018-06-12 12:31:38 +00:00
|
|
|
var amount = request.query['number'];//number of decryptions taking in
|
|
|
|
var paramString = request.query['param'];//event group parameter in JSON
|
|
|
|
var partialsStrings = request.query['decs'];//array of partial decryption(s) in bytes
|
|
|
|
var ciphertextString = request.query['cipher'];//ciphertext being decrypted in JSON
|
|
|
|
|
|
|
|
//re-build parameters
|
2018-07-07 08:52:47 +00:00
|
|
|
var tempParams = JSON.parse(JSON.parse(paramString).crypto);
|
2018-06-12 12:31:38 +00:00
|
|
|
var ctx = new CTX("BN254CX"); //new context we can use
|
|
|
|
var n = new ctx.BIG();
|
|
|
|
var g1 = new ctx.ECP();
|
|
|
|
var g2 = new ctx.ECP2();
|
|
|
|
|
|
|
|
//copying the values
|
|
|
|
n.copy(tempParams.n);
|
|
|
|
g1.copy(tempParams.g1);
|
|
|
|
g2.copy(tempParams.g2);
|
|
|
|
|
|
|
|
var params = {
|
|
|
|
n:n,
|
|
|
|
g1:g1,
|
|
|
|
g2:g2
|
2018-07-07 08:52:47 +00:00
|
|
|
};
|
2018-06-12 12:31:38 +00:00
|
|
|
|
|
|
|
//re-build partial decryptions
|
2018-07-07 08:52:47 +00:00
|
|
|
var partials = [];
|
2018-06-12 12:31:38 +00:00
|
|
|
if(amount == partialsStrings.length)
|
|
|
|
{
|
|
|
|
console.log(amount + " partial decryptions");
|
|
|
|
for(var i = 0; i < partialsStrings.length; i++)
|
|
|
|
{
|
|
|
|
var bytes = Buffer.from(partialsStrings[i].split(','), 'hex');
|
2018-07-07 08:52:47 +00:00
|
|
|
|
2018-06-12 12:31:38 +00:00
|
|
|
var dec = {
|
|
|
|
D:new ctx.ECP.fromBytes(bytes)
|
2018-07-07 08:52:47 +00:00
|
|
|
};
|
|
|
|
|
2018-06-12 12:31:38 +00:00
|
|
|
partials.push(dec);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(amount == 1)
|
|
|
|
{
|
2018-07-07 08:52:47 +00:00
|
|
|
console.log("\nOnly one partial decryption received\n");
|
|
|
|
console.log(JSON.parse(paramString).crypto + "\n");
|
|
|
|
|
2018-06-12 12:31:38 +00:00
|
|
|
var bytes = Buffer.from(partialsStrings.split(','), 'hex');
|
|
|
|
var dec = {
|
2018-07-07 08:52:47 +00:00
|
|
|
D : new ctx.ECP.fromBytes(bytes)
|
|
|
|
};
|
|
|
|
|
2018-06-12 12:31:38 +00:00
|
|
|
partials.push(dec);
|
|
|
|
}
|
|
|
|
|
|
|
|
//re-build combined ciphertext
|
|
|
|
var tempCipher = JSON.parse(ciphertextString);
|
|
|
|
|
2018-07-07 08:52:47 +00:00
|
|
|
var cipher = {
|
2018-06-12 12:31:38 +00:00
|
|
|
C1: new ctx.ECP(),
|
|
|
|
C2: new ctx.ECP()
|
2018-07-07 08:52:47 +00:00
|
|
|
};
|
|
|
|
|
2018-06-12 12:31:38 +00:00
|
|
|
cipher.C1.copy(tempCipher.C1);
|
|
|
|
cipher.C2.copy(tempCipher.C2);
|
|
|
|
|
|
|
|
response.json(tally(params, partials, cipher))
|
2018-07-07 08:52:47 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
app.post('/comb_sks', function(request, response){
|
|
|
|
console.log("\nEndpoint /comb_sks called");
|
|
|
|
const SKsAsStrings = request.body.SKs;
|
|
|
|
|
|
|
|
// Parse and combine the secret keys
|
|
|
|
var ctx = new CTX("BN254CX");
|
|
|
|
var parsedSKs = [];
|
|
|
|
|
|
|
|
for(var i = 0; i < SKsAsStrings.length; i++) {
|
|
|
|
var skBytes = SKsAsStrings[i].split(",");
|
|
|
|
parsedSKs.push(new ctx.BIG.fromBytes(skBytes));
|
|
|
|
}
|
|
|
|
|
|
|
|
console.log("Combining " + parsedSKs.length + " SKs...");
|
|
|
|
var SKBytes = [];
|
|
|
|
combine_sks(parsedSKs).SK.toBytes(SKBytes);
|
|
|
|
|
|
|
|
response.send(SKBytes.toString());
|
|
|
|
});
|
|
|
|
|
|
|
|
app.post('/get_tally', function(request, response){
|
|
|
|
const COUNT = request.body.count;
|
|
|
|
const TEMP_PARAMS = JSON.parse(JSON.parse(request.body.param).crypto);
|
|
|
|
const C1s = request.body.ciphers.c1s;
|
|
|
|
const C2s = request.body.ciphers.c2s;
|
|
|
|
const SK = request.body.sk;
|
2018-06-12 12:31:38 +00:00
|
|
|
|
2018-07-07 08:52:47 +00:00
|
|
|
console.log("\nFrom /get_tally - C1 array length (num of voters for the opt): " + C1s.length);
|
2018-06-12 12:31:38 +00:00
|
|
|
|
2018-07-07 08:52:47 +00:00
|
|
|
//re-build parameters
|
|
|
|
var ctx = new CTX("BN254CX"); //new context we can use
|
|
|
|
var n = new ctx.BIG();
|
|
|
|
var g1 = new ctx.ECP();
|
|
|
|
var g2 = new ctx.ECP2();
|
|
|
|
|
|
|
|
n.copy(TEMP_PARAMS.n);
|
|
|
|
g1.copy(TEMP_PARAMS.g1);
|
|
|
|
g2.copy(TEMP_PARAMS.g2);
|
|
|
|
|
|
|
|
var params = {
|
|
|
|
n:n,
|
|
|
|
g1:g1,
|
|
|
|
g2:g2
|
|
|
|
};
|
|
|
|
|
|
|
|
//rebuild our secret key
|
|
|
|
var skBytes = SK.split(",");
|
|
|
|
var sk = new ctx.BIG.fromBytes(skBytes);
|
|
|
|
|
|
|
|
var tally = 0;
|
|
|
|
|
|
|
|
for(var i = 0; i < COUNT; i++) {
|
|
|
|
var c1Bytes = Buffer.from(C1s[i].split(','), 'hex');
|
|
|
|
var newC1 = new ctx.ECP.fromBytes(c1Bytes);
|
|
|
|
|
|
|
|
var c2Bytes = Buffer.from(C2s[i].split(','), 'hex');
|
|
|
|
var newC2 = new ctx.ECP.fromBytes(c2Bytes);
|
|
|
|
|
|
|
|
var cipher = {C1: newC1, C2: newC2};
|
|
|
|
tally += decrypt(params, sk, cipher).M;
|
|
|
|
}
|
|
|
|
|
|
|
|
console.log("Tally: " + tally + "\n");
|
|
|
|
|
|
|
|
response.send("" + tally);
|
|
|
|
});
|
2018-06-12 12:31:38 +00:00
|
|
|
|
|
|
|
var server = app.listen(port, function(){
|
|
|
|
var host = server.address().address;
|
|
|
|
var appPort = server.address().port;
|
|
|
|
|
|
|
|
console.log('Server listening on ' + host + ':'+ port);
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
Cryptography functions written by Bingsheng Zhang
|
|
|
|
|
|
|
|
Uses the milagro-crypto-js library at:
|
|
|
|
https://github.com/milagro-crypto/milagro-crypto-js
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
//Group parameter generator: returns rng object and generators g1,g2 for G1,G2 as well as order
|
|
|
|
gpGen = function(){
|
|
|
|
//init, and base generators
|
|
|
|
var ctx = new CTX("BN254CX");
|
|
|
|
|
|
|
|
var n=new ctx.BIG(0); n.rcopy(ctx.ROM_CURVE.CURVE_Order);
|
|
|
|
|
|
|
|
//get generator P for G1
|
|
|
|
P = new ctx.ECP(0);
|
|
|
|
gx = new ctx.BIG(0);
|
|
|
|
gx.rcopy(ctx.ROM_CURVE.CURVE_Gx);
|
|
|
|
if (ctx.ECP.CURVETYPE != ctx.ECP.MONTGOMERY) {
|
|
|
|
gy = new ctx.BIG(0);
|
|
|
|
gy.rcopy(ctx.ROM_CURVE.CURVE_Gy);
|
|
|
|
P.setxy(gx, gy);
|
|
|
|
} else P.setx(gx);
|
|
|
|
|
|
|
|
//get generator Q for G2
|
|
|
|
var A=new ctx.BIG(0);
|
|
|
|
var B=new ctx.BIG(0);
|
|
|
|
A.rcopy(ctx.ROM_CURVE.CURVE_Pxa);
|
|
|
|
B.rcopy(ctx.ROM_CURVE.CURVE_Pxb);
|
|
|
|
var Qx=new ctx.FP2(0); Qx.bset(A,B);
|
|
|
|
A.rcopy(ctx.ROM_CURVE.CURVE_Pya);
|
|
|
|
B.rcopy(ctx.ROM_CURVE.CURVE_Pyb);
|
|
|
|
var Qy=new ctx.FP2(0); Qy.bset(A,B);
|
|
|
|
var Q=new ctx.ECP2();
|
|
|
|
Q.setxy(Qy,Qy);
|
|
|
|
|
|
|
|
return{
|
|
|
|
n:n,
|
|
|
|
g1:P,
|
|
|
|
g2:Q
|
|
|
|
}
|
2018-07-07 08:52:47 +00:00
|
|
|
};
|
2018-06-12 12:31:38 +00:00
|
|
|
|
|
|
|
|
|
|
|
//creates ElGamal public and secret key
|
|
|
|
keyGen=function(params){
|
|
|
|
var ctx = new CTX("BN254CX");
|
|
|
|
//set rng
|
|
|
|
var RAW = [];
|
|
|
|
var d = new Date();//time for seed, not secure
|
|
|
|
var rng = new ctx.RAND();
|
|
|
|
rng.clean();
|
|
|
|
RAW[0] = d.getSeconds();
|
|
|
|
RAW[1] = d.getMinutes();
|
|
|
|
RAW[2] = d.getMilliseconds();
|
|
|
|
rng.seed(3, RAW);
|
|
|
|
|
|
|
|
//ElGamal
|
|
|
|
var sk = new ctx.BIG(0);
|
|
|
|
sk = ctx.BIG.randomnum(params.n,rng);
|
|
|
|
var pk = new ctx.ECP(0);
|
|
|
|
pk = ctx.PAIR.G1mul(params.g1,sk);
|
|
|
|
|
|
|
|
|
|
|
|
return{
|
|
|
|
PK:pk,
|
|
|
|
SK:sk
|
|
|
|
}
|
2018-07-07 08:52:47 +00:00
|
|
|
};
|
2018-06-12 12:31:38 +00:00
|
|
|
|
|
|
|
|
|
|
|
//combine multiple public key together
|
|
|
|
//the input is an array of PKs
|
2018-07-07 08:52:47 +00:00
|
|
|
combine_pks=function(PKs){
|
2018-06-12 12:31:38 +00:00
|
|
|
var ctx = new CTX("BN254CX");
|
|
|
|
var pk=new ctx.ECP();
|
|
|
|
//copy the first pk
|
|
|
|
pk.copy(PKs[0]);
|
|
|
|
//multiple the rest PKs
|
|
|
|
for(i=1;i<PKs.length;i++){
|
|
|
|
pk.add(PKs[i]);
|
|
|
|
}
|
|
|
|
|
2018-07-07 08:52:47 +00:00
|
|
|
return {
|
|
|
|
PK : pk
|
2018-06-12 12:31:38 +00:00
|
|
|
}
|
2018-07-07 08:52:47 +00:00
|
|
|
};
|
2018-06-12 12:31:38 +00:00
|
|
|
|
2018-07-07 08:52:47 +00:00
|
|
|
// Written by Vincent de Almeida: Combines multiple secret keys together
|
|
|
|
// The SKs in the SKs array should already have been initialised using 'new ctx.BIG.fromBytes()'
|
|
|
|
combine_sks=function(SKs) {
|
|
|
|
// 'add' the rest of the sks to the first
|
|
|
|
var sk = SKs[0];
|
|
|
|
|
|
|
|
for(var i = 1; i < SKs.length; i++) {
|
|
|
|
sk.add(SKs[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
return {
|
|
|
|
SK: sk
|
|
|
|
}
|
|
|
|
};
|
2018-06-12 12:31:38 +00:00
|
|
|
|
|
|
|
//ElGamal encryption
|
|
|
|
encrypt=function(params,PK, m){
|
|
|
|
var ctx = new CTX("BN254CX");
|
|
|
|
//set rand
|
|
|
|
var RAW = [];
|
|
|
|
var d = new Date();//time for seed, not secure
|
|
|
|
var rng = new ctx.RAND();
|
|
|
|
rng.clean();
|
|
|
|
RAW[0] = d.getSeconds();
|
|
|
|
RAW[1] = d.getMinutes();
|
|
|
|
RAW[2] = d.getMilliseconds();
|
|
|
|
rng.seed(3, RAW);
|
|
|
|
|
|
|
|
var r=new ctx.BIG.randomnum(params.n,rng);
|
|
|
|
var M=new ctx.BIG(m);
|
|
|
|
|
|
|
|
var C1=new ctx.ECP();
|
|
|
|
C1 = ctx.PAIR.G1mul(params.g1,r);
|
|
|
|
|
|
|
|
var gM=new ctx.ECP();
|
|
|
|
gM = ctx.PAIR.G1mul(params.g1,M);
|
|
|
|
|
|
|
|
var C2=new ctx.ECP();
|
|
|
|
C2 = ctx.PAIR.G1mul(PK,r);
|
|
|
|
C2.mul(r);
|
|
|
|
C2.add(gM);
|
|
|
|
|
|
|
|
return{
|
|
|
|
C1:C1,
|
|
|
|
C2:C2
|
|
|
|
}
|
2018-07-07 08:52:47 +00:00
|
|
|
};
|
2018-06-12 12:31:38 +00:00
|
|
|
|
|
|
|
|
|
|
|
//add ciphertexts
|
|
|
|
add=function(Ciphers){
|
|
|
|
var ctx = new CTX("BN254CX");
|
|
|
|
var s1=new ctx.ECP();
|
|
|
|
var s2=new ctx.ECP();
|
|
|
|
//copy the first cipher
|
|
|
|
s1.copy(Ciphers[0].C1);
|
|
|
|
s2.copy(Ciphers[0].C2);
|
|
|
|
//multiple the rest ciphertexts
|
|
|
|
for(i=1;i<Ciphers.length;i++){
|
|
|
|
s1.add(Ciphers[i].C1);
|
|
|
|
}
|
|
|
|
//no idea why I need two loops
|
|
|
|
for(j=1;j<Ciphers.length;j++){
|
|
|
|
s2.add(Ciphers[j].C2);
|
|
|
|
}
|
|
|
|
|
|
|
|
return{
|
|
|
|
C1:s1,
|
|
|
|
C2:s2
|
|
|
|
}
|
2018-07-07 08:52:47 +00:00
|
|
|
};
|
2018-06-12 12:31:38 +00:00
|
|
|
|
|
|
|
|
|
|
|
//ElGamal decryption
|
|
|
|
decrypt=function(params,SK, C){
|
|
|
|
var ctx = new CTX("BN254CX");
|
|
|
|
var D=new ctx.ECP();
|
|
|
|
D = ctx.PAIR.G1mul(C.C1,SK);
|
|
|
|
|
|
|
|
var gM=new ctx.ECP();
|
|
|
|
gM.copy(C.C2);
|
|
|
|
gM.sub(D);
|
|
|
|
|
|
|
|
//search for message by brute force
|
|
|
|
var B;
|
|
|
|
for (j = 0; j < 1000; j++) {
|
|
|
|
//use D as temp var
|
|
|
|
B = new ctx.BIG(j);
|
|
|
|
D = ctx.PAIR.G1mul(params.g1,B);
|
|
|
|
if (D.equals(gM))
|
|
|
|
return{
|
|
|
|
M:j
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
return{
|
|
|
|
M: "Error"
|
|
|
|
}
|
2018-07-07 08:52:47 +00:00
|
|
|
};
|
2018-06-12 12:31:38 +00:00
|
|
|
|
|
|
|
|
|
|
|
//ElGamal partial decryption
|
|
|
|
partDec=function(SK, C){
|
|
|
|
var ctx = new CTX("BN254CX");
|
|
|
|
var D=new ctx.ECP();
|
|
|
|
D = ctx.PAIR.G1mul(C.C1,SK);
|
|
|
|
|
|
|
|
return{
|
|
|
|
D: D
|
|
|
|
}
|
2018-07-07 08:52:47 +00:00
|
|
|
};
|
2018-06-12 12:31:38 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//Tally, combine partial decryption
|
|
|
|
//Ds is the array of partial decryptions; C is the ciphertext.
|
|
|
|
tally=function(params,Ds, C){
|
|
|
|
var ctx = new CTX("BN254CX");
|
|
|
|
var D=new ctx.ECP();
|
|
|
|
D.copy(Ds[0].D);
|
|
|
|
|
|
|
|
//combine D
|
|
|
|
for(i=1;i<Ds.length;i++){
|
|
|
|
D.add(Ds[i].D);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var gM=new ctx.ECP();
|
|
|
|
gM.copy(C.C2);
|
|
|
|
gM.sub(D);
|
|
|
|
|
2018-07-07 08:52:47 +00:00
|
|
|
//search for message by brute force
|
2018-06-12 12:31:38 +00:00
|
|
|
var B;
|
2018-07-07 08:52:47 +00:00
|
|
|
for (var j = 0; j < 1000; j++) {
|
2018-06-12 12:31:38 +00:00
|
|
|
//use D as temp var
|
|
|
|
B = new ctx.BIG(j);
|
|
|
|
D = ctx.PAIR.G1mul(params.g1,B);
|
|
|
|
if (D.equals(gM))
|
|
|
|
return{
|
2018-07-07 08:52:47 +00:00
|
|
|
M: j
|
2018-06-12 12:31:38 +00:00
|
|
|
}
|
|
|
|
|
2018-07-07 08:52:47 +00:00
|
|
|
}
|
2018-06-12 12:31:38 +00:00
|
|
|
|
|
|
|
|
|
|
|
return{
|
|
|
|
M: "Error"
|
|
|
|
}
|
2018-07-07 08:52:47 +00:00
|
|
|
};
|
2018-06-12 12:31:38 +00:00
|
|
|
|
|
|
|
|
|
|
|
|