123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659 |
- /*
- * Copyright 2018 Scytl Secure Electronic Voting SA
- *
- * All rights reserved
- *
- * See our extended copyright notice in *file 'Copyright.txt' which is part of this source code package
- */
- describe('Homomorphic service...', function() {
- 'use strict';
- var MAX_EXPONENT_BYTES = 2;
- var NUM_GROUP_ELEMENTS = 2;
- var NUM_SINGLE_GROUP_ELEMENTS = 5;
- var G_STR = '2';
- var P_STR = '23';
- var Q_STR = '11';
- var ELEMENT_1_STR = '2';
- var ELEMENT_2_STR = '4';
- var EXPONENT_1_STR = '1';
- var EXPONENT_2_STR = '2';
- var P_LARGE_STR =
- '22588801568735561413035633152679913053449200833478689904902877673687016391844561133376032309307885537704777240609087377993341380751697605235541131273868440070920362148431866829787784445019147999379498503693247429579480289226602748397335327890884464685051682703709742724121783217827040722415360103179289160056581759372475845985438977307323570530753362027145384124771826114651710264766437273044759690955051982839684910462609395741692689616014805965573558015387956017183286848440036954926101719205598449898400180082053755864070690174202432196678045052744337832802051787273056312757384654145455745603262082348042780103679';
- var Q_LARGE_STR =
- '11294400784367780706517816576339956526724600416739344952451438836843508195922280566688016154653942768852388620304543688996670690375848802617770565636934220035460181074215933414893892222509573999689749251846623714789740144613301374198667663945442232342525841351854871362060891608913520361207680051589644580028290879686237922992719488653661785265376681013572692062385913057325855132383218636522379845477525991419842455231304697870846344808007402982786779007693978008591643424220018477463050859602799224949200090041026877932035345087101216098339022526372168916401025893636528156378692327072727872801631041174021390051839';
- var ELEMENT_1_LARGE_STR =
- '8008650650117182055231947796743510595354735701773678127718063162818861428894482760351040442014062206238677757186380515026469824595870224783896120627455841205517047520359887236518609328142965980653129280864098892996273964740090483597375107437139254412471355470548193136206727124381287524666926794272344682267309880188101372142121235759763117992716726731820970068223350454790098901032607754554402031099573358614926437378953856998041036773132081351057601842441454945388068039731483320814325657715553744820319265534754357498649904400594493834709761403358903505501640705996603619499187129497007221246019054462834616450362';
- var ELEMENT_2_LARGE_STR =
- '11633656285653208443919333339470607846301429932894308783457570029107286147936455427826899303856584843544699293627942560893304455970515082299498680026759665698080990494885992738624255552297867735585728427220214607212173788862760053487198296321130486607904876481443447070538549541504734530736112052175501932133880661864111558469545768002897528612084034669926036569715266022136440126595140089621370735885927146016552642348282420224106653601826235849885956583427798077317966671703306684815012981357245529568157986211578924579799810305712551845266909314082456551659795959581952216679219662533353585637849875985836675331118';
- var EXPONENT_1_LARGE_STR =
- '2310427452287266604038074581830299484831755686607108413899820257798165596547227594518989253178264380941033095268581246346863002280809127490132335557543545847332023813499454886051935043363376517658050024793517465349562106228739828060169613880190064891580719513382177220752409776280150551117185655930834371803832590064152233876708731218969195345490200219499344738664373593917843352485459832349992908261365788172930979823955846952949156058247067965643074532679047274706566088888021355575983368719069681293419346162608049979977471053590745499346591475991673763640645139343249862033377744682868210594034732021779460567412';
- var EXPONENT_2_LARGE_STR =
- '7533608948657130117198364792462971241599837777629317286887202126604432685322243335715285630236984093165224740099563982076007648728594011814311120331313200895892632245003875959905589367483155794698953057915454892457379023058909518440394905695255170407948701433659375513788930419544151891518689331636455316691827048845766063478445484089208223819510250476623436782404385896353292653750744111841510466992101967325081746747885221256692886521245630131046183525331085171958919416648097910028887247120874015121272894655357197879292253781160838729753609784455892951965051119314203469298666741439497193677501351952497150273389';
- var _initialized = false;
- var _elGamalPublicKey;
- var _elGamalPrivateKey;
- var _elGamalEncrypter;
- var _elGamalDecrypter;
- var _elGamalKeyPair;
- var _zpSubgroup;
- var _zpGroupElements;
- var _elGamalPublicKeyLarge;
- var _elGamalPrivateKeyLarge;
- var _elGamalEncrypterLarge;
- var _elGamalDecrypterLarge;
- var _zpGroupElementsLarge;
- var _zpGroupElementsLargeNonQR;
- var _singleZpGroupElements;
- var _elGamalEncrypterUsingSeed;
- var _elGamalRandomDecrypter;
- beforeEach(function() {
- if (!_initialized) {
- cryptolib(
- 'commons.utils', 'commons.mathematical', 'homomorphic.service',
- function(box) {
- var converters = new box.commons.utils.Converters();
- var gB64 = converters.base64FromBigInteger(
- new forge.jsbn.BigInteger(G_STR));
- var pB64 = converters.base64FromBigInteger(
- new forge.jsbn.BigInteger(P_STR));
- var qB64 = converters.base64FromBigInteger(
- new forge.jsbn.BigInteger(Q_STR));
- var element1B64 = converters.base64FromBigInteger(
- new forge.jsbn.BigInteger(ELEMENT_1_STR));
- var element2B64 = converters.base64FromBigInteger(
- new forge.jsbn.BigInteger(ELEMENT_2_STR));
- var exponent1B64 = converters.base64FromBigInteger(
- new forge.jsbn.BigInteger(EXPONENT_1_STR));
- var exponent2B64 = converters.base64FromBigInteger(
- new forge.jsbn.BigInteger(EXPONENT_2_STR));
- var elGamalPublicKeyJson = '{"publicKey":{"zpSubgroup":{"g":"' +
- gB64 + '","p":"' + pB64 + '","q":"' + qB64 +
- '"},"elements":["' + element1B64 + '","' + element2B64 + '"]}}';
- var elGamalPrivateKeyJson = '{"privateKey":{"zpSubgroup":{"g":"' +
- gB64 + '","p":"' + pB64 + '","q":"' + qB64 +
- '"},"exponents":["' + exponent1B64 + '","' + exponent2B64 +
- '"]}}';
- var elGamalPublicKeyJsonB64 =
- converters.base64Encode(elGamalPublicKeyJson);
- var elGamalPrivateKeyJsonB64 =
- converters.base64Encode(elGamalPrivateKeyJson);
- _elGamalPublicKey = box.homomorphic.service.createElGamalPublicKey(
- elGamalPublicKeyJsonB64);
- _elGamalPrivateKey =
- box.homomorphic.service.createElGamalPrivateKey(
- elGamalPrivateKeyJsonB64);
- _elGamalKeyPair = new box.homomorphic.service.createElGamalKeyPair(
- _elGamalPublicKey, _elGamalPrivateKey);
- _elGamalEncrypter =
- box.homomorphic.service.createEncrypter(_elGamalPublicKey);
- _elGamalDecrypter =
- box.homomorphic.service.createDecrypter(_elGamalPrivateKey);
- var g = new box.forge.jsbn.BigInteger(G_STR);
- var p = new box.forge.jsbn.BigInteger(P_STR);
- var q = new box.forge.jsbn.BigInteger(Q_STR);
- _zpSubgroup = new box.commons.mathematical.ZpSubgroup(g, p, q);
- _zpGroupElements =
- generateGroupElements(_zpSubgroup, NUM_GROUP_ELEMENTS);
- gB64 = converters.base64FromBigInteger(
- new forge.jsbn.BigInteger(G_STR));
- pB64 = converters.base64FromBigInteger(
- new forge.jsbn.BigInteger(P_LARGE_STR));
- qB64 = converters.base64FromBigInteger(
- new forge.jsbn.BigInteger(Q_LARGE_STR));
- element1B64 = converters.base64FromBigInteger(
- new forge.jsbn.BigInteger(ELEMENT_1_LARGE_STR));
- element2B64 = converters.base64FromBigInteger(
- new forge.jsbn.BigInteger(ELEMENT_2_LARGE_STR));
- exponent1B64 = converters.base64FromBigInteger(
- new forge.jsbn.BigInteger(EXPONENT_1_LARGE_STR));
- exponent2B64 = converters.base64FromBigInteger(
- new forge.jsbn.BigInteger(EXPONENT_2_LARGE_STR));
- var elGamalPublicKeyLargeJson =
- '{"publicKey":{"zpSubgroup":{"g":"' + gB64 + '","p":"' + pB64 +
- '","q":"' + qB64 + '"},"elements":["' + element1B64 + '","' +
- element2B64 + '"]}}';
- var elGamalPrivateKeyLargeJson =
- '{"privateKey":{"zpSubgroup":{"g":"' + gB64 + '","p":"' + pB64 +
- '","q":"' + qB64 + '"},"exponents":["' + exponent1B64 + '","' +
- exponent2B64 + '"]}}';
- var elGamalPublicKeyLargeJsonB64 =
- converters.base64Encode(elGamalPublicKeyLargeJson);
- var elGamalPrivateKeyLargeJsonB64 =
- converters.base64Encode(elGamalPrivateKeyLargeJson);
- _elGamalPublicKeyLarge =
- box.homomorphic.service.createElGamalPublicKey(
- elGamalPublicKeyLargeJsonB64);
- _elGamalPrivateKeyLarge =
- box.homomorphic.service.createElGamalPrivateKey(
- elGamalPrivateKeyLargeJsonB64);
- _elGamalEncrypterLarge =
- box.homomorphic.service.createEncrypter(_elGamalPublicKeyLarge);
- _elGamalDecrypterLarge = box.homomorphic.service.createDecrypter(
- _elGamalPrivateKeyLarge);
- g = new box.forge.jsbn.BigInteger(G_STR);
- p = new box.forge.jsbn.BigInteger(P_LARGE_STR);
- q = new box.forge.jsbn.BigInteger(Q_LARGE_STR);
- var zpSubgroup = new box.commons.mathematical.ZpSubgroup(g, p, q);
- _zpGroupElementsLarge =
- generateGroupElements(zpSubgroup, NUM_GROUP_ELEMENTS);
- g = new box.forge.jsbn.BigInteger(G_STR);
- p = new box.forge.jsbn.BigInteger(P_LARGE_STR);
- q = new box.forge.jsbn.BigInteger(Q_LARGE_STR)
- .subtract(box.forge.jsbn.BigInteger.ONE);
- zpSubgroup = new box.commons.mathematical.ZpSubgroup(g, p, q);
- _zpGroupElementsLargeNonQR =
- generateGroupElements(zpSubgroup, NUM_GROUP_ELEMENTS);
- g = new box.forge.jsbn.BigInteger(G_STR);
- p = new box.forge.jsbn.BigInteger(P_LARGE_STR);
- q = new box.forge.jsbn.BigInteger(Q_LARGE_STR);
- zpSubgroup = new box.commons.mathematical.ZpSubgroup(g, p, q);
- _singleZpGroupElements =
- generateGroupElements(zpSubgroup, NUM_SINGLE_GROUP_ELEMENTS);
- });
- _initialized = true;
- }
- cryptolib('primitives.service', 'homomorphic.service', function(box) {
- // Generate seed and define callback function to initialize random
- // integer generator with seed.
- var seedHex = cryptoPRNG.generateRandomSeedInHex();
- var cryptoRandomInteger;
- var initRandomGenerator = function(box) {
- cryptoRandomInteger = box.primitives.service.getCryptoRandomInteger();
- };
- // Create new encrypter that uses random integer generator initialized
- // with seed.
- initRandomGenerator.prng = cryptoPRNG.createPRNGFromSeed(seedHex);
- cryptolib('primitives.service', initRandomGenerator);
- _elGamalEncrypterUsingSeed = box.homomorphic.service.createEncrypter(
- _elGamalPublicKeyLarge, cryptoRandomInteger);
- // Create new decrypter that uses random integer generator initialized
- // with seed.
- initRandomGenerator.prng = cryptoPRNG.createPRNGFromSeed(seedHex);
- cryptolib('primitives.service', initRandomGenerator);
- _elGamalRandomDecrypter = box.homomorphic.service.createRandomDecrypter(
- _elGamalPublicKeyLarge, cryptoRandomInteger);
- });
- });
- describe('should be able to ..', function() {
- it('create an ElGamal key pair', function() {
- validateElGamalPublicKey(_elGamalKeyPair.getPublicKey());
- validateElGamalPrivateKey(_elGamalKeyPair.getPrivateKey());
- });
- it('and create an ElGamal encrypter', function() {
- validateElGamalPublicKey(_elGamalEncrypter.getElGamalPublicKey());
- });
- it('and create an ElGamal decrypter', function() {
- validateElGamalPrivateKey(_elGamalDecrypter.getElGamalPrivateKey());
- });
- it('and deserialize an ElGamal public key', function() {
- expect(_elGamalPublicKey.getGroup()
- .getGenerator()
- .getElementValue()
- .toString())
- .toEqual(G_STR);
- expect(_elGamalPublicKey.getGroup().getP().toString()).toEqual(P_STR);
- expect(_elGamalPublicKey.getGroup().getQ().toString()).toEqual(Q_STR);
- expect(_elGamalPublicKey.getGroupElementsArray().length).toEqual(2);
- expect(_elGamalPublicKey.getGroupElementsArray()[0]
- .getElementValue()
- .toString())
- .toEqual(ELEMENT_1_STR);
- expect(_elGamalPublicKey.getGroupElementsArray()[1]
- .getElementValue()
- .toString())
- .toEqual(ELEMENT_2_STR);
- });
- it('and deserialize an ElGamal private key', function() {
- expect(_elGamalPrivateKey.getGroup()
- .getGenerator()
- .getElementValue()
- .toString())
- .toEqual(G_STR);
- expect(_elGamalPrivateKey.getGroup().getP().toString()).toEqual(P_STR);
- expect(_elGamalPrivateKey.getGroup().getQ().toString()).toEqual(Q_STR);
- expect(_elGamalPrivateKey.getExponentsArray().length).toEqual(2);
- expect(_elGamalPrivateKey.getExponentsArray()[0].getValue().toString())
- .toEqual(EXPONENT_1_STR);
- expect(_elGamalPrivateKey.getExponentsArray()[1].getValue().toString())
- .toEqual(EXPONENT_2_STR);
- });
- it('and ElGamal encrypt and decrypt some group elements', function() {
- var encryptedGroupElements =
- _elGamalEncrypter.encryptGroupElements(_zpGroupElements);
- var decryptedGroupElements =
- _elGamalDecrypter.decrypt(encryptedGroupElements, true);
- expect(decryptedGroupElements.length).toBe(_zpGroupElements.length);
- for (var i = 0; i < decryptedGroupElements.length; i++) {
- expect(decryptedGroupElements[i].equals(_zpGroupElements[i]))
- .toBeTruthy();
- }
- });
- it('and ElGamal encrypt and decrypt some group elements, using pre-computed encryption values',
- function() {
- var preComputedValues = _elGamalEncrypter.preCompute();
- var encryptedGroupElements = _elGamalEncrypter.encryptGroupElements(
- _zpGroupElements, preComputedValues);
- var decryptedGroupElements =
- _elGamalDecrypter.decrypt(encryptedGroupElements, true);
- expect(decryptedGroupElements.length).toBe(_zpGroupElements.length);
- for (var i = 0; i < decryptedGroupElements.length; i++) {
- expect(decryptedGroupElements[i].equals(_zpGroupElements[i]))
- .toBeTruthy();
- }
- });
- it('and ElGamal encrypt and decrypt some group elements, using encryption values generated with a short exponent',
- function() {
- cryptolib(function(box) {
- var encryptedGroupElements =
- _elGamalEncrypterLarge.encryptGroupElements(
- _zpGroupElementsLarge, true);
- expect(encryptedGroupElements.getR().getValue().bitLength())
- .not.toBeGreaterThan(box.SHORT_EXPONENT_BIT_LENGTH);
- var decryptedGroupElements =
- _elGamalDecrypterLarge.decrypt(encryptedGroupElements, true);
- expect(decryptedGroupElements.length)
- .toBe(_zpGroupElementsLarge.length);
- for (var i = 0; i < decryptedGroupElements.length; i++) {
- expect(decryptedGroupElements[i].equals(_zpGroupElementsLarge[i]))
- .toBeTruthy();
- }
- });
- });
- it('and ElGamal encrypt and decrypt some group elements, using pre-computed encryption values generated with a short exponent',
- function() {
- cryptolib(function(box) {
- var preComputedValues = _elGamalEncrypterLarge.preCompute(true);
- var encryptedGroupElements =
- _elGamalEncrypterLarge.encryptGroupElements(
- _zpGroupElementsLarge, preComputedValues);
- expect(encryptedGroupElements.getR().getValue().bitLength())
- .not.toBeGreaterThan(box.SHORT_EXPONENT_BIT_LENGTH);
- var decryptedGroupElements =
- _elGamalDecrypterLarge.decrypt(encryptedGroupElements, true);
- expect(decryptedGroupElements.length)
- .toBe(_zpGroupElementsLarge.length);
- for (var i = 0; i < decryptedGroupElements.length; i++) {
- expect(decryptedGroupElements[i].equals(_zpGroupElementsLarge[i]))
- .toBeTruthy();
- }
- });
- });
- it('and ElGamal encrypt and decrypt some group elements, using a random seed',
- function() {
- var encryptedGroupElements =
- _elGamalEncrypterUsingSeed.encryptGroupElements(
- _zpGroupElementsLarge);
- var decryptedGroupElements =
- _elGamalRandomDecrypter.decrypt(encryptedGroupElements, true);
- expect(decryptedGroupElements.length)
- .toBe(_zpGroupElementsLarge.length);
- for (var i = 0; i < decryptedGroupElements.length; i++) {
- expect(decryptedGroupElements[i].equals(_zpGroupElementsLarge[i]))
- .toBeTruthy();
- }
- });
- it('and ElGamal encrypt and decrypt some group elements, using a random seed and pre-computed encryption values',
- function() {
- var preComputedValues = _elGamalEncrypterUsingSeed.preCompute();
- var encryptedGroupElements = _elGamalEncrypter.encryptGroupElements(
- _zpGroupElementsLarge, preComputedValues);
- var decryptedGroupElements =
- _elGamalRandomDecrypter.decrypt(encryptedGroupElements, true);
- expect(decryptedGroupElements.length)
- .toBe(_zpGroupElementsLarge.length);
- for (var i = 0; i < decryptedGroupElements.length; i++) {
- expect(decryptedGroupElements[i].equals(_zpGroupElementsLarge[i]))
- .toBeTruthy();
- }
- });
- it('and ElGamal encrypt and decrypt some group elements, using a random seed and encryption values generated with a short exponent',
- function() {
- cryptolib(function(box) {
- var encryptedGroupElements =
- _elGamalEncrypterUsingSeed.encryptGroupElements(
- _zpGroupElementsLarge, true);
- expect(encryptedGroupElements.getR().getValue().bitLength())
- .not.toBeGreaterThan(box.SHORT_EXPONENT_BIT_LENGTH);
- var decryptedGroupElements = _elGamalRandomDecrypter.decrypt(
- encryptedGroupElements, true, true);
- expect(decryptedGroupElements.length)
- .toBe(_zpGroupElementsLarge.length);
- for (var i = 0; i < decryptedGroupElements.length; i++) {
- expect(decryptedGroupElements[i].equals(_zpGroupElementsLarge[i]))
- .toBeTruthy();
- }
- });
- });
- it('and ElGamal encrypt and decrypt some group elements, using a random seed and pre-computed encryption values generated with a short exponent',
- function() {
- cryptolib(function(box) {
- var preComputedValues = _elGamalEncrypterUsingSeed.preCompute(true);
- var encryptedGroupElements =
- _elGamalEncrypterUsingSeed.encryptGroupElements(
- _zpGroupElementsLarge, preComputedValues);
- expect(encryptedGroupElements.getR().getValue().bitLength())
- .not.toBeGreaterThan(box.SHORT_EXPONENT_BIT_LENGTH);
- var decryptedGroupElements = _elGamalRandomDecrypter.decrypt(
- encryptedGroupElements, true, true);
- expect(decryptedGroupElements.length)
- .toBe(_zpGroupElementsLarge.length);
- for (var i = 0; i < decryptedGroupElements.length; i++) {
- expect(decryptedGroupElements[i].equals(_zpGroupElementsLarge[i]))
- .toBeTruthy();
- }
- });
- });
- it('and ElGamal encrypt and decrypt some single group elements, using a random seed',
- function() {
- var encryptedGroupElementArray = [];
- for (var i = 0; i < _singleZpGroupElements.length; i++) {
- var encryptedGroupElement =
- _elGamalEncrypterUsingSeed.encryptGroupElements(
- [_singleZpGroupElements[i]]);
- encryptedGroupElementArray.push(encryptedGroupElement);
- }
- var decryptedGroupElementArray = [];
- for (var j = 0; j < encryptedGroupElementArray.length; j++) {
- var decryptedGroupElement = _elGamalRandomDecrypter.decrypt(
- encryptedGroupElementArray[j], true)[0];
- decryptedGroupElementArray.push(decryptedGroupElement);
- }
- expect(decryptedGroupElementArray.length)
- .toBe(_singleZpGroupElements.length);
- for (var k = 0; k < decryptedGroupElementArray.length; k++) {
- expect(
- decryptedGroupElementArray[k].equals(_singleZpGroupElements[k]))
- .toBeTruthy();
- }
- });
- it('and ElGamal encrypt and decrypt some single group elements, using a random seed and pre-computed encryption values',
- function() {
- var preComputedValuesArray = [];
- for (var i = 0; i < _singleZpGroupElements.length; i++) {
- var preComputedValues = _elGamalEncrypterUsingSeed.preCompute();
- preComputedValuesArray.push(preComputedValues);
- }
- var encryptedGroupElementArray = [];
- for (var j = 0; j < _singleZpGroupElements.length; j++) {
- var encryptedGroupElement =
- _elGamalEncrypterUsingSeed.encryptGroupElements(
- [_singleZpGroupElements[j]], preComputedValuesArray[j]);
- encryptedGroupElementArray.push(encryptedGroupElement);
- }
- var decryptedGroupElementArray = [];
- for (var k = 0; k < encryptedGroupElementArray.length; k++) {
- var decryptedGroupElement = _elGamalRandomDecrypter.decrypt(
- encryptedGroupElementArray[k], true)[0];
- decryptedGroupElementArray.push(decryptedGroupElement);
- }
- expect(decryptedGroupElementArray.length)
- .toBe(_singleZpGroupElements.length);
- for (var l = 0; l < decryptedGroupElementArray.length; l++) {
- expect(
- decryptedGroupElementArray[l].equals(_singleZpGroupElements[l]))
- .toBeTruthy();
- }
- });
- it('and ElGamal encrypt and decrypt some single group elements, using a random seed and encryption values generated with a short exponent',
- function() {
- cryptolib(function(box) {
- var encryptedGroupElementArray = [];
- for (var i = 0; i < _singleZpGroupElements.length; i++) {
- var encryptedGroupElement =
- _elGamalEncrypterUsingSeed.encryptGroupElements(
- [_singleZpGroupElements[i]], true);
- expect(encryptedGroupElement.getR().getValue().bitLength())
- .not.toBeGreaterThan(box.SHORT_EXPONENT_BIT_LENGTH);
- encryptedGroupElementArray.push(encryptedGroupElement);
- }
- var decryptedGroupElementArray = [];
- for (var j = 0; j < encryptedGroupElementArray.length; j++) {
- var decryptedGroupElement = _elGamalRandomDecrypter.decrypt(
- encryptedGroupElementArray[j], true, true)[0];
- decryptedGroupElementArray.push(decryptedGroupElement);
- }
- expect(decryptedGroupElementArray.length)
- .toBe(_singleZpGroupElements.length);
- for (var k = 0; k < decryptedGroupElementArray.length; k++) {
- expect(decryptedGroupElementArray[k].equals(
- _singleZpGroupElements[k]))
- .toBeTruthy();
- }
- });
- });
- it('and ElGamal encrypt and decrypt some single group elements, using a random seed and pre-computed encryption values generated with a short exponent',
- function() {
- cryptolib(function(box) {
- var preComputedValuesArray = [];
- for (var i = 0; i < _singleZpGroupElements.length; i++) {
- var preComputedValues =
- _elGamalEncrypterUsingSeed.preCompute(true);
- preComputedValuesArray.push(preComputedValues);
- }
- var encryptedGroupElementArray = [];
- for (var j = 0; j < _singleZpGroupElements.length; j++) {
- var encryptedGroupElement =
- _elGamalEncrypterUsingSeed.encryptGroupElements(
- [_singleZpGroupElements[j]], preComputedValuesArray[j]);
- expect(encryptedGroupElement.getR().getValue().bitLength())
- .not.toBeGreaterThan(box.SHORT_EXPONENT_BIT_LENGTH);
- encryptedGroupElementArray.push(encryptedGroupElement);
- }
- var decryptedGroupElementArray = [];
- for (var k = 0; k < encryptedGroupElementArray.length; k++) {
- var decryptedGroupElement = _elGamalRandomDecrypter.decrypt(
- encryptedGroupElementArray[k], true, true)[0];
- decryptedGroupElementArray.push(decryptedGroupElement);
- }
- expect(decryptedGroupElementArray.length)
- .toBe(_singleZpGroupElements.length);
- for (var l = 0; l < decryptedGroupElementArray.length; l++) {
- expect(decryptedGroupElementArray[l].equals(
- _singleZpGroupElements[l]))
- .toBeTruthy();
- }
- });
- });
- it('and ElGamal encrypt and decrypt some group elements, using serialized encryption values',
- function() {
- cryptolib('homomorphic.cipher', function(box) {
- var encryptedGroupElements =
- _elGamalEncrypter.encryptGroupElements(_zpGroupElements);
- var encryptedGroupElementsJson =
- encryptedGroupElements.getElGamalComputationValues().stringify();
- var encryptedGroupElementsFromJson =
- box.homomorphic.cipher.deserializeElGamalComputationValues(
- encryptedGroupElementsJson);
- var decryptedGroupElements =
- _elGamalDecrypter.decrypt(encryptedGroupElementsFromJson, true);
- expect(decryptedGroupElements.length).toBe(_zpGroupElements.length);
- for (var i = 0; i < decryptedGroupElements.length; i++) {
- expect(decryptedGroupElements[i].equals(_zpGroupElements[i]))
- .toBeTruthy();
- }
- });
- });
- it('and ElGamal encrypt and decrypt some group elements, using serialized pre-computed encryption values',
- function() {
- cryptolib('homomorphic.cipher', function(box) {
- var preComputedValues = _elGamalEncrypter.preCompute();
- var preComputedValuesJson =
- preComputedValues.getElGamalComputationValues().stringify();
- var preComputedValuesFromJson =
- box.homomorphic.cipher.deserializeElGamalComputationValues(
- preComputedValuesJson);
- var gamma = preComputedValuesFromJson.getGamma();
- var phis = preComputedValuesFromJson.getPhis();
- preComputedValuesFromJson =
- new box.homomorphic.cipher.ElGamalEncrypterValues(
- null, gamma, phis);
- var encryptedGroupElements = _elGamalEncrypter.encryptGroupElements(
- _zpGroupElements, preComputedValuesFromJson);
- var decryptedGroupElements =
- _elGamalDecrypter.decrypt(encryptedGroupElements, true);
- expect(decryptedGroupElements.length).toBe(_zpGroupElements.length);
- for (var i = 0; i < decryptedGroupElements.length; i++) {
- expect(decryptedGroupElements[i].equals(_zpGroupElements[i]))
- .toBeTruthy();
- }
- });
- });
- it('and throw an exception when attempting to ElGamal encrypt, using a short exponent, for a group that is not of type quadratic residue',
- function() {
- expect(function() {
- _elGamalEncrypterLarge.encryptGroupElements(
- _zpGroupElementsLargeNonQR, true);
- }).toThrow();
- });
- it('and throw an exception when attempting to ElGamal encrypt, using a short exponent, for a group whose order is smaller than this exponent',
- function() {
- expect(function() {
- _elGamalEncrypter.encryptGroupElements(_zpGroupElements, true);
- }).toThrow();
- });
- it('and fail to decrypt some encrypted elements when using a random seed but not reinitializing the random generator with the seed',
- function() {
- var encryptedGroupElements =
- _elGamalEncrypterUsingSeed.encryptGroupElements(
- _zpGroupElementsLarge);
- // Decryption should be successful the first time.
- var decryptedGroupElements =
- _elGamalRandomDecrypter.decrypt(encryptedGroupElements, true);
- expect(decryptedGroupElements.length)
- .toBe(_zpGroupElementsLarge.length);
- for (var i = 0; i < decryptedGroupElements.length; i++) {
- expect(decryptedGroupElements[i].equals(_zpGroupElementsLarge[i]))
- .toBeTruthy();
- }
- // Decryption should fail the second time since the random generator
- // was not re-initialized with the seed first.
- decryptedGroupElements =
- _elGamalRandomDecrypter.decrypt(encryptedGroupElements, true);
- expect(decryptedGroupElements.length)
- .toBe(_zpGroupElementsLarge.length);
- for (var j = 0; j < decryptedGroupElements.length; j++) {
- expect(decryptedGroupElements[j].equals(_zpGroupElementsLarge[j]))
- .toBeFalsy();
- }
- });
- });
- function generateRandomExponent(zpSubgroup) {
- var exponent;
- cryptolib('commons.mathematical', function(box) {
- do {
- var randomInt = new box.forge.jsbn.BigInteger(
- box.forge.random.getBytes(MAX_EXPONENT_BYTES));
- exponent =
- new box.commons.mathematical.Exponent(zpSubgroup.getQ(), randomInt);
- } while (exponent.getValue().equals(box.forge.jsbn.BigInteger.ZERO));
- });
- return exponent;
- }
- function generateGroupElements(zpSubgroup, numElements) {
- var element;
- var groupElements = [];
- for (var i = 0; i < numElements; i++) {
- element = zpSubgroup.getGenerator().exponentiate(
- generateRandomExponent(zpSubgroup));
- groupElements.push(element);
- }
- return groupElements;
- }
- function validateElGamalPublicKey(elGamalPublicKey) {
- expect(elGamalPublicKey.getGroup().equals(_zpSubgroup)).toBeTruthy();
- var keyElements = elGamalPublicKey.getGroupElementsArray();
- expect(keyElements.length).toBe(NUM_GROUP_ELEMENTS);
- expect(keyElements[0].getElementValue().toString()).toEqual(ELEMENT_1_STR);
- expect(keyElements[1].getElementValue().toString()).toEqual(ELEMENT_2_STR);
- }
- function validateElGamalPrivateKey(elGamalPrivateKey) {
- expect(elGamalPrivateKey.getGroup().equals(_zpSubgroup)).toBeTruthy();
- var keyExponents = elGamalPrivateKey.getExponentsArray();
- expect(keyExponents.length).toBe(NUM_GROUP_ELEMENTS);
- expect(keyExponents[0].getValue().toString()).toEqual(EXPONENT_1_STR);
- expect(keyExponents[1].getValue().toString()).toEqual(EXPONENT_2_STR);
- }
- });
|