/*
 * 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('Proofs ...', function() {
  'use strict';

  describe('Should be loaded if cryptolib is called with proofs: ', function() {
    it('should be defined a proofs', function() {
      cryptolib('*', function(box) {
        expect(typeof box.proofs.SimplePlaintextEqualityProofGenerator)
            .toBeDefined();
      });
    });
  });

  describe('PhiFunction ...', function() {
    describe('validate inputs ...', function() {
      it('valid inputs', function() {
        cryptolib('proofs', 'commons.mathematical', function(box) {

          // create PhiFunction
          var q = new box.forge.jsbn.BigInteger('11');
          var generator = new box.forge.jsbn.BigInteger('2');
          var p = new box.forge.jsbn.BigInteger('23');
          var zpSubgroup =
              new box.commons.mathematical.ZpSubgroup(generator, p, q);
          var numInputs = new box.forge.jsbn.BigInteger('1');
          var numOutputs = new box.forge.jsbn.BigInteger('1');
          var baseElements = [
            new box.forge.jsbn.BigInteger('1'),
            new box.forge.jsbn.BigInteger('2')
          ];
          var computationsRules = [[0, 1], [1, 1]];

          var createdPhiFunction = new box.proofs.PhiFunction(
              zpSubgroup, numInputs, numOutputs, baseElements,
              computationsRules);

          expect(createdPhiFunction).toBeDefined();
        });
      });

      it('invalid group', function() {
        cryptolib('proofs', 'commons.mathematical', function(box) {

          // create PhiFunction
          var zpSubgroup = new box.forge.jsbn.BigInteger('11');
          var numInputs = new box.forge.jsbn.BigInteger('1');
          var numOutputs = new box.forge.jsbn.BigInteger('1');
          var baseElements = [
            new box.forge.jsbn.BigInteger('1'),
            new box.forge.jsbn.BigInteger('2')
          ];
          var computationsRules = [[0, 1], [1, 1]];

          // Note: Expect exception not to be thrown here but proof verification
          // will fail; See service tests.
          box.proofs.PhiFunction(
              zpSubgroup, numInputs, numOutputs, baseElements,
              computationsRules);
        });
      });

      it('invalid number of inputs', function() {
        cryptolib('proofs', 'commons.mathematical', function(box) {

          // create PhiFunction
          var q = new box.forge.jsbn.BigInteger('11');
          var generator = new box.forge.jsbn.BigInteger('2');
          var p = new box.forge.jsbn.BigInteger('23');
          var zpSubgroup =
              new box.commons.mathematical.ZpSubgroup(generator, p, q);
          var numInputs;
          var numOutputs = new box.forge.jsbn.BigInteger('1');
          var baseElements = [
            new box.forge.jsbn.BigInteger('1'),
            new box.forge.jsbn.BigInteger('2')
          ];
          var computationsRules = [[0, 1], [1, 1]];

          expect(function() {
            box.proofs.PhiFunction(
                zpSubgroup, numInputs, numOutputs, baseElements,
                computationsRules);
          }).toThrow();
        });
      });

      it('invalid number of outputs (null)', function() {
        cryptolib('proofs', 'commons.mathematical', function(box) {

          // create PhiFunction
          var q = new box.forge.jsbn.BigInteger('11');
          var generator = new box.forge.jsbn.BigInteger('2');
          var p = new box.forge.jsbn.BigInteger('23');
          var zpSubgroup =
              new box.commons.mathematical.ZpSubgroup(generator, p, q);
          var numInputs = new box.forge.jsbn.BigInteger('1');
          var numOutputs;
          var baseElements = [
            new box.forge.jsbn.BigInteger('1'),
            new box.forge.jsbn.BigInteger('2')
          ];
          var computationsRules = [[0, 1], [1, 1]];

          expect(function() {
            box.proofs.PhiFunction(
                zpSubgroup, numInputs, numOutputs, baseElements,
                computationsRules);
          }).toThrow();
        });
      });

      it('invalid number of outputs (negative)', function() {
        cryptolib('proofs', 'commons.mathematical', function(box) {

          // create PhiFunction
          var q = new box.forge.jsbn.BigInteger('11');
          var generator = new box.forge.jsbn.BigInteger('2');
          var p = new box.forge.jsbn.BigInteger('23');
          var zpSubgroup =
              new box.commons.mathematical.ZpSubgroup(generator, p, q);
          var numInputs = new box.forge.jsbn.BigInteger('1');
          var numOutputs = -2;
          var baseElements = [
            new box.forge.jsbn.BigInteger('1'),
            new box.forge.jsbn.BigInteger('2')
          ];
          var computationsRules = [[0, 1], [1, 1]];

          expect(function() {
            box.proofs.PhiFunction(
                zpSubgroup, numInputs, numOutputs, baseElements,
                computationsRules);
          }).toThrow();
        });
      });

      it('invalid number of outputs (array)', function() {
        cryptolib('proofs', 'commons.mathematical', function(box) {

          // create PhiFunction
          var q = new box.forge.jsbn.BigInteger('11');
          var generator = new box.forge.jsbn.BigInteger('2');
          var p = new box.forge.jsbn.BigInteger('23');
          var zpSubgroup =
              new box.commons.mathematical.ZpSubgroup(generator, p, q);
          var numInputs = new box.forge.jsbn.BigInteger('1');
          var numOutputs = [[0, 1], [1, 1]];
          var baseElements = [
            new box.forge.jsbn.BigInteger('1'),
            new box.forge.jsbn.BigInteger('2')
          ];
          var computationsRules = [[0, 1], [1, 1]];

          expect(function() {
            box.proofs.PhiFunction(
                zpSubgroup, numInputs, numOutputs, baseElements,
                computationsRules);
          }).toThrow();
        });
      });

      it('invalid base elements (null)', function() {
        cryptolib('proofs', 'commons.mathematical', function(box) {

          // create PhiFunction
          var q = new box.forge.jsbn.BigInteger('11');
          var generator = new box.forge.jsbn.BigInteger('2');
          var p = new box.forge.jsbn.BigInteger('23');
          var zpSubgroup =
              new box.commons.mathematical.ZpSubgroup(generator, p, q);
          var numInputs = new box.forge.jsbn.BigInteger('1');
          var numOutputs = new box.forge.jsbn.BigInteger('1');
          var baseElements;
          var computationsRules = [[0, 1], [1, 1]];

          expect(function() {
            box.proofs.PhiFunction(
                zpSubgroup, numInputs, numOutputs, baseElements,
                computationsRules);
          }).toThrow();
        });
      });

      it('invalid base elements (not array)', function() {
        cryptolib('proofs', 'commons.mathematical', function(box) {

          // create PhiFunction
          var q = new box.forge.jsbn.BigInteger('11');
          var generator = new box.forge.jsbn.BigInteger('2');
          var p = new box.forge.jsbn.BigInteger('23');
          var zpSubgroup =
              new box.commons.mathematical.ZpSubgroup(generator, p, q);
          var numInputs = new box.forge.jsbn.BigInteger('1');
          var numOutputs = new box.forge.jsbn.BigInteger('1');
          var baseElements = new box.forge.jsbn.BigInteger('1');
          var computationsRules = [[0, 1], [1, 1]];

          expect(function() {
            box.proofs.PhiFunction(
                zpSubgroup, numInputs, numOutputs, baseElements,
                computationsRules);
          }).toThrow();
        });
      });

      it('invalid computation rules (null)', function() {
        cryptolib('proofs', 'commons.mathematical', function(box) {

          // create PhiFunction
          var q = new box.forge.jsbn.BigInteger('11');
          var generator = new box.forge.jsbn.BigInteger('2');
          var p = new box.forge.jsbn.BigInteger('23');
          var zpSubgroup =
              new box.commons.mathematical.ZpSubgroup(generator, p, q);
          var numInputs = new box.forge.jsbn.BigInteger('1');
          var numOutputs = new box.forge.jsbn.BigInteger('1');
          var baseElements = new box.forge.jsbn.BigInteger('1');
          var computationsRules;

          expect(function() {
            box.proofs.PhiFunction(
                zpSubgroup, numInputs, numOutputs, baseElements,
                computationsRules);
          }).toThrow();
        });
      });

      it('invalid computation rules (not array)', function() {
        cryptolib('proofs', 'commons.mathematical', function(box) {

          // create PhiFunction
          var q = new box.forge.jsbn.BigInteger('11');
          var generator = new box.forge.jsbn.BigInteger('2');
          var p = new box.forge.jsbn.BigInteger('23');
          var zpSubgroup =
              new box.commons.mathematical.ZpSubgroup(generator, p, q);
          var numInputs = new box.forge.jsbn.BigInteger('1');
          var numOutputs = new box.forge.jsbn.BigInteger('1');
          var baseElements = new box.forge.jsbn.BigInteger('1');
          var computationsRules = new box.forge.jsbn.BigInteger('1');

          expect(function() {
            box.proofs.PhiFunction(
                zpSubgroup, numInputs, numOutputs, baseElements,
                computationsRules);
          }).toThrow();
        });
      });

      it('invalid computation rules: first index value is smaller than 1',
         function() {
           cryptolib('proofs', 'commons.mathematical', function(box) {

             // create PhiFunction
             var q = new box.forge.jsbn.BigInteger('11');
             var generator = new box.forge.jsbn.BigInteger('2');
             var p = new box.forge.jsbn.BigInteger('23');
             var zpSubgroup =
                 new box.commons.mathematical.ZpSubgroup(generator, p, q);
             var numInputs = new box.forge.jsbn.BigInteger('1');
             var numOutputs = new box.forge.jsbn.BigInteger('1');
             var zpGroupElement_p23_v2 =
                 new box.commons.mathematical.ZpGroupElement(
                     new box.forge.jsbn.BigInteger('2'), p, q);
             var baseElements = [zpGroupElement_p23_v2];
             var computationsRules = [[[0, 1]]];

             expect(function() {
               box.proofs.PhiFunction(
                   zpSubgroup, numInputs, numOutputs, baseElements,
                   computationsRules);
             }).toThrow();
           });
         });

      it('invalid computation rules: first index value larger then number of base elements',
         function() {
           cryptolib('proofs', 'commons.mathematical', function(box) {

             // create PhiFunction
             var q = new box.forge.jsbn.BigInteger('11');
             var generator = new box.forge.jsbn.BigInteger('2');
             var p = new box.forge.jsbn.BigInteger('23');
             var zpSubgroup =
                 new box.commons.mathematical.ZpSubgroup(generator, p, q);
             var numInputs = new box.forge.jsbn.BigInteger('1');
             var numOutputs = new box.forge.jsbn.BigInteger('1');
             var zpGroupElement_p23_v2 =
                 new box.commons.mathematical.ZpGroupElement(
                     new box.forge.jsbn.BigInteger('2'), p, q);
             var baseElements = [zpGroupElement_p23_v2, zpGroupElement_p23_v2];
             var computationsRules = [[[3, 1]]];

             expect(function() {
               box.proofs.PhiFunction(
                   zpSubgroup, numInputs, numOutputs, baseElements,
                   computationsRules);
             }).toThrow();
           });
         });

      it('invalid computation rules: second index value smaller than 1',
         function() {
           cryptolib('proofs', 'commons.mathematical', function(box) {

             // create PhiFunction
             var q = new box.forge.jsbn.BigInteger('11');
             var generator = new box.forge.jsbn.BigInteger('2');
             var p = new box.forge.jsbn.BigInteger('23');
             var zpSubgroup =
                 new box.commons.mathematical.ZpSubgroup(generator, p, q);
             var numInputs = new box.forge.jsbn.BigInteger('1');
             var numOutputs = new box.forge.jsbn.BigInteger('1');
             var zpGroupElement_p23_v2 =
                 new box.commons.mathematical.ZpGroupElement(
                     new box.forge.jsbn.BigInteger('2'), p, q);
             var baseElements = [zpGroupElement_p23_v2];
             var computationsRules = [[[1, 0]]];

             expect(function() {
               box.proofs.PhiFunction(
                   zpSubgroup, numInputs, numOutputs, baseElements,
                   computationsRules);
             }).toThrow();
           });
         });

      it('invalid computation rules: second index value bigger than number of inputs',
         function() {
           cryptolib('proofs', 'commons.mathematical', function(box) {

             // create PhiFunction
             var q = new box.forge.jsbn.BigInteger('11');
             var generator = new box.forge.jsbn.BigInteger('2');
             var p = new box.forge.jsbn.BigInteger('23');
             var zpSubgroup =
                 new box.commons.mathematical.ZpSubgroup(generator, p, q);
             var numInputs = new box.forge.jsbn.BigInteger('2');
             var numOutputs = new box.forge.jsbn.BigInteger('1');
             var zpGroupElement_p23_v2 =
                 new box.commons.mathematical.ZpGroupElement(
                     new box.forge.jsbn.BigInteger('2'), p, q);
             var zpGroupElement_p23_v3 =
                 new box.commons.mathematical.ZpGroupElement(
                     new box.forge.jsbn.BigInteger('3'), p, q);
             var baseElements = [zpGroupElement_p23_v2, zpGroupElement_p23_v3];
             var computationsRules = [[[1, 2], [1, 3]]];

             expect(function() {
               box.proofs.PhiFunction(
                   zpSubgroup, numInputs, numOutputs, baseElements,
                   computationsRules);
             }).toThrow();
           });
         });
    });

    describe('calculatePhi ...', function() {

      it('invalid inputs', function() {
        cryptolib('proofs', 'commons.mathematical', function(box) {

          // create group
          var q = new box.forge.jsbn.BigInteger('11');
          var generator = new box.forge.jsbn.BigInteger('2');
          var p = new box.forge.jsbn.BigInteger('23');
          var zpSubgroup =
              new box.commons.mathematical.ZpSubgroup(generator, p, q);

          // create additional needed parameters
          var numInputs = new box.forge.jsbn.BigInteger('1');
          var numOutputs = new box.forge.jsbn.BigInteger('1');
          var baseElements = [zpSubgroup.getGenerator()];
          var computationsRules = [[[1, 1]]];

          // create PhiFunction
          var createdPhiFunction = new box.proofs.PhiFunction(
              zpSubgroup, numInputs, numOutputs, baseElements,
              computationsRules);

          // create array of exponents
          var value1 = new box.forge.jsbn.BigInteger('2');
          var exponent1 =
              new box.commons.mathematical.Exponent(zpSubgroup.getQ(), value1);
          var exponentArray = [exponent1];

          var result = createdPhiFunction.calculatePhi(exponentArray);

          var expectedElement = new box.commons.mathematical.ZpGroupElement(
              new box.forge.jsbn.BigInteger('4'), zpSubgroup.getP(),
              zpSubgroup.getQ());
          var expectedResultArray = [expectedElement];

          expect(expectedResultArray.equals(result)).toBeTruthy();
        });
      });
    });
  });

  describe('Prover ...', function() {
    describe('validate inputs ...', function() {
      it('validate inputs', function() {
        cryptolib('proofs', function() {});
      });

      it('invalid inputs', function() {
        cryptolib('proofs', function() {});
      });
    });

    describe('prove ...', function() {
      describe('validate inputs ...', function() {

      });
    });
  });

  describe('Proof ...', function() {

    it('validate inputs', function() {
      cryptolib('proofs', 'commons.mathematical', function(box) {

        // create proof
        var q = new box.forge.jsbn.BigInteger('11');
        var generator = new box.forge.jsbn.BigInteger('2');
        var p = new box.forge.jsbn.BigInteger('23');
        var zpSubgroup =
            new box.commons.mathematical.ZpSubgroup(generator, p, q);

        var value = new box.forge.jsbn.BigInteger('2');
        var hash =
            new box.commons.mathematical.Exponent(zpSubgroup.getQ(), value);

        var value1 = new box.forge.jsbn.BigInteger('2');
        var exp1 =
            new box.commons.mathematical.Exponent(zpSubgroup.getQ(), value1);
        var value2 = new box.forge.jsbn.BigInteger('3');
        var exp2 =
            new box.commons.mathematical.Exponent(zpSubgroup.getQ(), value2);
        var values = [exp1, exp2];

        var createdProof = new box.proofs.Proof(hash, values);
        expect(createdProof).toBeDefined();
      });
    });

    it('validate equals true', function() {
      cryptolib('proofs', 'commons.mathematical', function(box) {

        // create proof1
        var p1_q = new box.forge.jsbn.BigInteger('11');
        var p1_generator = new box.forge.jsbn.BigInteger('2');
        var p1_p = new box.forge.jsbn.BigInteger('23');
        var p1_zpSubgroup =
            new box.commons.mathematical.ZpSubgroup(p1_generator, p1_p, p1_q);

        var p1_value = new box.forge.jsbn.BigInteger('5');
        var p1_hash = new box.commons.mathematical.Exponent(
            p1_zpSubgroup.getQ(), p1_value);

        var p1_value1 = new box.forge.jsbn.BigInteger('3');
        var p1_exp1 = new box.commons.mathematical.Exponent(
            p1_zpSubgroup.getQ(), p1_value1);
        var p1_value2 = new box.forge.jsbn.BigInteger('4');
        var p1_exp2 = new box.commons.mathematical.Exponent(
            p1_zpSubgroup.getQ(), p1_value2);
        var p1_values = [p1_exp1, p1_exp2];

        var p1_createdProof = new box.proofs.Proof(p1_hash, p1_values);
        expect(p1_createdProof).toBeDefined();

        // create proof2
        var p2_q = new box.forge.jsbn.BigInteger('11');
        var p2_generator = new box.forge.jsbn.BigInteger('2');
        var p2_p = new box.forge.jsbn.BigInteger('23');

        var p2_zpSubgroup =
            new box.commons.mathematical.ZpSubgroup(p2_generator, p2_p, p2_q);

        var p2_value = new box.forge.jsbn.BigInteger('5');
        var p2_hash = new box.commons.mathematical.Exponent(
            p2_zpSubgroup.getQ(), p2_value);

        var p2_value1 = new box.forge.jsbn.BigInteger('3');
        var p2_exp1 = new box.commons.mathematical.Exponent(
            p2_zpSubgroup.getQ(), p2_value1);
        var p2_value2 = new box.forge.jsbn.BigInteger('4');
        var p2_exp2 = new box.commons.mathematical.Exponent(
            p2_zpSubgroup.getQ(), p2_value2);
        var p2_values = [p2_exp1, p2_exp2];

        var p2_createdProof = new box.proofs.Proof(p2_hash, p2_values);
        expect(p2_createdProof).toBeDefined();

        expect(p1_createdProof.equals(p2_createdProof)).toBeTruthy();
      });
    });

    it('validate equals false', function() {
      cryptolib('proofs', 'commons.mathematical', function(box) {

        // create proof1
        var p1_q = new box.forge.jsbn.BigInteger('11');
        var p1_generator = new box.forge.jsbn.BigInteger('2');
        var p1_p = new box.forge.jsbn.BigInteger('23');
        var p1_zpSubgroup =
            new box.commons.mathematical.ZpSubgroup(p1_generator, p1_p, p1_q);

        var p1_value = new box.forge.jsbn.BigInteger('5');
        var p1_hash = new box.commons.mathematical.Exponent(
            p1_zpSubgroup.getQ(), p1_value);

        var p1_value1 = new box.forge.jsbn.BigInteger('3');
        var p1_exp1 = new box.commons.mathematical.Exponent(
            p1_zpSubgroup.getQ(), p1_value1);
        var p1_value2 = new box.forge.jsbn.BigInteger('3');
        var p1_exp2 = new box.commons.mathematical.Exponent(
            p1_zpSubgroup.getQ(), p1_value2);
        var p1_values = [p1_exp1, p1_exp2];

        var p1_createdProof = new box.proofs.Proof(p1_hash, p1_values);
        expect(p1_createdProof).toBeDefined();

        // create proof2
        var p2_q = new box.forge.jsbn.BigInteger('11');
        var p2_generator = new box.forge.jsbn.BigInteger('2');
        var p2_p = new box.forge.jsbn.BigInteger('23');

        var p2_zpSubgroup =
            new box.commons.mathematical.ZpSubgroup(p2_generator, p2_p, p2_q);

        var p2_value = new box.forge.jsbn.BigInteger('5');
        var p2_hash = new box.commons.mathematical.Exponent(
            p2_zpSubgroup.getQ(), p2_value);

        var p2_value1 = new box.forge.jsbn.BigInteger('3');
        var p2_exp1 = new box.commons.mathematical.Exponent(
            p2_zpSubgroup.getQ(), p2_value1);
        var p2_value2 = new box.forge.jsbn.BigInteger('4');
        var p2_exp2 = new box.commons.mathematical.Exponent(
            p2_zpSubgroup.getQ(), p2_value2);
        var p2_values = [p2_exp1, p2_exp2];

        var p2_createdProof = new box.proofs.Proof(p2_hash, p2_values);
        expect(p2_createdProof).toBeDefined();

        expect(p1_createdProof.equals(p2_createdProof)).not.toBeTruthy();
      });
    });

    it('stringify correctly to the JSON string: {"zkProof":{"q":"Cw==","hash":"Ag==","values":["Ag==","Aw=="]}}',
       function() {
         cryptolib('proofs', 'commons.mathematical', function(box) {

           // create proof
           var q = new box.forge.jsbn.BigInteger('11');
           var generator = new box.forge.jsbn.BigInteger('2');
           var p = new box.forge.jsbn.BigInteger('23');
           var zpSubgroup =
               new box.commons.mathematical.ZpSubgroup(generator, p, q);

           var value = new box.forge.jsbn.BigInteger('2');
           var hash =
               new box.commons.mathematical.Exponent(zpSubgroup.getQ(), value);

           var value1 = new box.forge.jsbn.BigInteger('2');
           var exp1 =
               new box.commons.mathematical.Exponent(zpSubgroup.getQ(), value1);
           var value2 = new box.forge.jsbn.BigInteger('3');
           var exp2 =
               new box.commons.mathematical.Exponent(zpSubgroup.getQ(), value2);
           var values = [exp1, exp2];

           var proof = new box.proofs.Proof(hash, values);

           var jsonAsString = proof.stringify();

           expect(jsonAsString).toContain('"zkProof"');
           expect(jsonAsString).toContain('"q":"Cw=="');
           expect(jsonAsString).toContain('"hash":"Ag=="');
           expect(jsonAsString).toContain('"values":');
           expect(jsonAsString.length)
               .toBe(
                   '{"zkProof":{"q":"Cw==","hash":"Ag==","values":["Ag==","Aw=="]}}'
                       .length);
         });
       });

    it('deserialize correctly from the JSON string: {"zkProof":{"q":"Cw==","hash":"Ag==","values":["Ag==","Aw=="]}}',
       function() {
         cryptolib('proofs', 'commons.mathematical', function(box) {
           var proofAsJson =
               '{"zkProof":{"q":"Cw==","hash":"Ag==","values":["Ag==","Aw=="]}}';

           var deserializedProof =
               box.proofs.utils.deserializeProof(proofAsJson);

           var serializedProof = deserializedProof.stringify();

           expect(serializedProof).toEqual(proofAsJson);
         });
       });
  });

  describe('HashBuilder ...', function() {
    describe('When created with ...', function() {
      it('valid inputs', function() {
        cryptolib(
            'proofs', 'commons.mathematical', 'primitives.messagedigest',
            function(box) {

              var hashbuilder = new box.proofs.HashBuilder();

              expect(hashbuilder).toBeDefined();
            });
      });
    });

    describe('When buildHashForProof is called ...', function() {
      describe('passing a one character String ...', function() {
        it('then expected an exception', function() {
          cryptolib(
              'proofs', 'commons.mathematical', 'primitives.messagedigest',
              'commons.utils', function(box) {

                var hashbuilder = new box.proofs.HashBuilder();

                var oneCharacterString = 'a';
                var inputObjectArray = [];
                inputObjectArray.push(oneCharacterString);

                expect(function() {
                  hashbuilder.buildHashForProof(inputObjectArray);
                }).toThrow();
              });
        });
      });

      describe('get hash twice from same objects ...', function() {
        it('then same result both times', function() {
          cryptolib(
              'proofs', 'commons.mathematical', 'primitives.messagedigest',
              'commons.utils', function(box) {

                var converters = new box.commons.utils.Converters();
                var hashbuilder = new box.proofs.HashBuilder();

                // create group and elements
                var q = new box.forge.jsbn.BigInteger('11');
                var generator = new box.forge.jsbn.BigInteger('2');
                var p = new box.forge.jsbn.BigInteger('23');
                var group =
                    new box.commons.mathematical.ZpSubgroup(generator, p, q);
                var ZpGroupElement_p23_v2 =
                    new box.commons.mathematical.ZpGroupElement(
                        new box.forge.jsbn.BigInteger('2'), group.getP(),
                        group.getQ());
                var ZpGroupElement_p23_v3 =
                    new box.commons.mathematical.ZpGroupElement(
                        new box.forge.jsbn.BigInteger('3'), group.getP(),
                        group.getQ());
                var ZpGroupElement_p23_v4 =
                    new box.commons.mathematical.ZpGroupElement(
                        new box.forge.jsbn.BigInteger('4'), group.getP(),
                        group.getQ());

                // Create objects that will be hashed.
                var _simpleList1 = [];
                _simpleList1.push(ZpGroupElement_p23_v2);
                _simpleList1.push(ZpGroupElement_p23_v3);

                var _simpleList2 = [];
                _simpleList2.push(ZpGroupElement_p23_v4);

                var _short_string1 = 'I am a short String';

                var _simpleList3 = [];
                _simpleList3.push(ZpGroupElement_p23_v2);
                _simpleList3.push(ZpGroupElement_p23_v3);

                var _simpleList4 = [];
                _simpleList4.push(ZpGroupElement_p23_v4);

                var _short_string2 = 'I am a short String';

                var bytesB64_1 = hashbuilder.buildHashForProof(
                    _simpleList1, _simpleList2, _short_string1);
                var bytes1 = converters.base64Decode(bytesB64_1);
                var result1 = new box.forge.jsbn.BigInteger(
                    converters.bytesFromString(bytes1));

                var bytesB64_2 = hashbuilder.buildHashForProof(
                    _simpleList3, _simpleList4, _short_string2);
                var bytes2 = converters.base64Decode(bytesB64_2);
                var result2 = new box.forge.jsbn.BigInteger(
                    converters.bytesFromString(bytes2));

                expect(result1.equals(result2)).toBeTruthy();
              });
        });
      });

      describe(
          'passing lists containing Zp subgroup elements and strings ...',
          function() {
            it('then expected output', function() {
              cryptolib(
                  'proofs', 'commons.mathematical', 'primitives.messagedigest',
                  'commons.utils', function(box) {

                    var converters = new box.commons.utils.Converters();
                    var hashbuilder = new box.proofs.HashBuilder();

                    // create group and elements
                    var q = new box.forge.jsbn.BigInteger('11');
                    var generator = new box.forge.jsbn.BigInteger('2');
                    var p = new box.forge.jsbn.BigInteger('23');
                    var group = new box.commons.mathematical.ZpSubgroup(
                        generator, p, q);
                    var ZpGroupElement_p23_v2 =
                        new box.commons.mathematical.ZpGroupElement(
                            new box.forge.jsbn.BigInteger('2'), group.getP(),
                            group.getQ());
                    var ZpGroupElement_p23_v3 =
                        new box.commons.mathematical.ZpGroupElement(
                            new box.forge.jsbn.BigInteger('3'), group.getP(),
                            group.getQ());
                    var ZpGroupElement_p23_v4 =
                        new box.commons.mathematical.ZpGroupElement(
                            new box.forge.jsbn.BigInteger('4'), group.getP(),
                            group.getQ());

                    // Create objects that will be hashed.
                    var _simpleList1 = [];
                    _simpleList1.push(ZpGroupElement_p23_v2);
                    _simpleList1.push(ZpGroupElement_p23_v3);

                    var _simpleList2 = [];
                    _simpleList2.push(ZpGroupElement_p23_v4);

                    var _short_string = 'I am a short String';

                    var bytesB64_1 = hashbuilder.buildHashForProof(
                        _simpleList1, _simpleList2, _short_string);
                    var bytes1 = converters.base64Decode(bytesB64_1);
                    var result = new box.forge.jsbn.BigInteger(
                        converters.bytesFromString(bytes1));
                    var javaResult = new box.forge.jsbn.BigInteger(
                        '-52725384769643723964651772032205801420047176905115581490667997821371105732649');
                    expect(javaResult.equals(result)).toBeTruthy();
                  });
            });
          });

      describe('passing an Exponent ...', function() {
        it('then expected output', function() {
          cryptolib(
              'proofs', 'commons.mathematical', 'primitives.messagedigest',
              function() {});
        });
      });
    });
  });

  describe('Maurer proof ...', function() {
    it('calculatePhi must be defined', function() {
      cryptolib('proofs', 'commons.mathematical', function(box) {
        // create group
        var q = new box.forge.jsbn.BigInteger('11');
        var generator = new box.forge.jsbn.BigInteger('2');
        var p = new box.forge.jsbn.BigInteger('23');
        var zpSubgroup =
            new box.commons.mathematical.ZpSubgroup(generator, p, q);
        // create additional needed parameters
        var numInputs = new box.forge.jsbn.BigInteger('1');
        var numOutputs = new box.forge.jsbn.BigInteger('1');
        var baseElements = [zpSubgroup.getGenerator()];
        var computationsRules = [[[1, 1]]];
        // create PhiFunction
        var createdPhiFunction = new box.proofs.PhiFunction(
            zpSubgroup, numInputs, numOutputs, baseElements, computationsRules);

        expect(createdPhiFunction).toBeDefined();

        // create array of exponents
        var value1 = new box.forge.jsbn.BigInteger('2');
        var exponent1 =
            new box.commons.mathematical.Exponent(zpSubgroup.getQ(), value1);
        var exponentArray = [exponent1];

        var data = 'testdata';

        var prover = new box.proofs.Prover(zpSubgroup, createdPhiFunction);

        var exponentiatedElement =
            zpSubgroup.getGenerator().exponentiate(exponent1);

        var precomputationValues = prover.preCompute(1);
        var proofResult = prover.prove(
            [exponentiatedElement], exponentArray, data, precomputationValues);
        expect(proofResult).toBeTruthy();
      });
    });
  });

  describe('Schnorr proof ...', function() {
    it('should be able to be generate and verify a Schnorr proof', function() {
      cryptolib('proofs', 'commons', 'primitives.messagedigest', function(box) {

        // create group
        var q = new box.forge.jsbn.BigInteger('11');
        var generator = new box.forge.jsbn.BigInteger('2');
        var p = new box.forge.jsbn.BigInteger('23');
        var group = new box.commons.mathematical.ZpSubgroup(generator, p, q);

        var exponent = new box.commons.mathematical.Exponent(
            q, new box.forge.jsbn.BigInteger('8'));
        var exponentiatedElement = group.getGenerator().exponentiate(exponent);

        var proofsFactory = new box.proofs.ProofsFactory();
        var schnorrProof =
            proofsFactory
                .createSchnorrProofGenerator('123456789', '99999999', group)
                .generate(exponentiatedElement, exponent);

        var proofTruth = proofsFactory
                             .createSchnorrProofVerifier(
                                 exponentiatedElement, '123456789', '99999999',
                                 schnorrProof, group)
                             .verify();
        expect(proofTruth).toBeTruthy();
      });
    });

    it('should throw an exception in Schnorr proof generator if voterID is null',
       function() {
         cryptolib(
             'proofs', 'commons', 'primitives.messagedigest', function(box) {

               // create group
               var q = new box.forge.jsbn.BigInteger('11');
               var generator = new box.forge.jsbn.BigInteger('2');
               var p = new box.forge.jsbn.BigInteger('23');
               var group =
                   new box.commons.mathematical.ZpSubgroup(generator, p, q);

               var exponent = new box.commons.mathematical.Exponent(
                   q, new box.forge.jsbn.BigInteger('8'));
               var exponentiatedElement =
                   group.getGenerator().exponentiate(exponent);

               var voterIdGenerator;
               var electionEventIdGenerator = '99999999';

               var proofsFactory = new box.proofs.ProofsFactory();

               expect(function() {
                 createSchnorrProof(
                     proofsFactory, group, exponentiatedElement, exponent,
                     voterIdGenerator, electionEventIdGenerator);
               }).toThrow();
             });
       });

    it('should throw an exception in schnorr proof generator if voterID is empty',
       function() {
         cryptolib(
             'proofs', 'commons', 'primitives.messagedigest', function(box) {

               // create group
               var q = new box.forge.jsbn.BigInteger('11');
               var generator = new box.forge.jsbn.BigInteger('2');
               var p = new box.forge.jsbn.BigInteger('23');
               var group =
                   new box.commons.mathematical.ZpSubgroup(generator, p, q);

               var exponent = new box.commons.mathematical.Exponent(
                   q, new box.forge.jsbn.BigInteger('8'));
               var exponentiatedElement =
                   group.getGenerator().exponentiate(exponent);

               var voterIdGenerator = '';
               var electionEventIdGenerator = '99999999';

               var proofsFactory = new box.proofs.ProofsFactory();

               expect(function() {
                 createSchnorrProof(
                     proofsFactory, group, exponentiatedElement, exponent,
                     voterIdGenerator, electionEventIdGenerator);
               }).toThrow();
             });
       });

    it('should throw an exception in Schnorr proof generator if electionEventId is null',
       function() {
         cryptolib(
             'proofs', 'commons', 'primitives.messagedigest', function(box) {

               // create group
               var q = new box.forge.jsbn.BigInteger('11');
               var generator = new box.forge.jsbn.BigInteger('2');
               var p = new box.forge.jsbn.BigInteger('23');
               var group =
                   new box.commons.mathematical.ZpSubgroup(generator, p, q);

               var exponent = new box.commons.mathematical.Exponent(
                   q, new box.forge.jsbn.BigInteger('8'));
               var exponentiatedElement =
                   group.getGenerator().exponentiate(exponent);

               var voterIdGenerator = '123456789';
               var electionEventIdGenerator;

               var proofsFactory = new box.proofs.ProofsFactory();

               expect(function() {
                 createSchnorrProof(
                     proofsFactory, group, exponentiatedElement, exponent,
                     voterIdGenerator, electionEventIdGenerator);
               }).toThrow();
             });
       });

    it('should throw an exception in schnorr proof generator if electionEventId is empty',
       function() {
         cryptolib(
             'proofs', 'commons', 'primitives.messagedigest', function(box) {

               // create group
               var q = new box.forge.jsbn.BigInteger('11');
               var generator = new box.forge.jsbn.BigInteger('2');
               var p = new box.forge.jsbn.BigInteger('23');
               var group =
                   new box.commons.mathematical.ZpSubgroup(generator, p, q);

               var exponent = new box.commons.mathematical.Exponent(
                   q, new box.forge.jsbn.BigInteger('8'));
               var exponentiatedElement =
                   group.getGenerator().exponentiate(exponent);

               var voterIdGenerator = '123456789';
               var electionEventIdGenerator = '';

               var proofsFactory = new box.proofs.ProofsFactory();

               expect(function() {
                 createSchnorrProof(
                     proofsFactory, group, exponentiatedElement, exponent,
                     voterIdGenerator, electionEventIdGenerator);
               }).toThrow();
             });
       });

    it('should throw an exception in Schnorr proof verifier if voterID is null',
       function() {
         cryptolib(
             'proofs', 'commons', 'primitives.messagedigest', function(box) {

               // create group
               var q = new box.forge.jsbn.BigInteger('11');
               var generator = new box.forge.jsbn.BigInteger('2');
               var p = new box.forge.jsbn.BigInteger('23');
               var group =
                   new box.commons.mathematical.ZpSubgroup(generator, p, q);

               var exponent = new box.commons.mathematical.Exponent(
                   q, new box.forge.jsbn.BigInteger('8'));
               var exponentiatedElement =
                   group.getGenerator().exponentiate(exponent);

               var voterIdGenerator = '123456789';
               var electionEventIdGenerator = '99999999';

               var voterIdVerifier;
               var electionEventIdVerifier = '99999999';

               var proofsFactory = new box.proofs.ProofsFactory();
               var schnorrProof =
                   proofsFactory
                       .createSchnorrProofGenerator(
                           voterIdGenerator, electionEventIdGenerator, group)
                       .generate(exponentiatedElement, exponent);

               expect(function() {
                 proofsFactory
                     .createSchnorrProofVerifier(
                         exponentiatedElement, voterIdVerifier,
                         electionEventIdVerifier, schnorrProof, group)
                     .verify();
               }).toThrow();
             });
       });

    it('should throw an exception in Schnorr proof verifier if voterID is empty',
       function() {
         cryptolib(
             'proofs', 'commons', 'primitives.messagedigest', function(box) {

               // create group
               var q = new box.forge.jsbn.BigInteger('11');
               var generator = new box.forge.jsbn.BigInteger('2');
               var p = new box.forge.jsbn.BigInteger('23');
               var group =
                   new box.commons.mathematical.ZpSubgroup(generator, p, q);

               var exponent = new box.commons.mathematical.Exponent(
                   q, new box.forge.jsbn.BigInteger('8'));
               var exponentiatedElement =
                   group.getGenerator().exponentiate(exponent);

               var voterIdGenerator = '123456789';
               var electionEventIdGenerator = '99999999';

               var voterIdVerifier = '';
               var electionEventIdVerifier = '99999999';

               var proofsFactory = new box.proofs.ProofsFactory();
               var schnorrProof =
                   proofsFactory
                       .createSchnorrProofGenerator(
                           voterIdGenerator, electionEventIdGenerator, group)
                       .generate(exponentiatedElement, exponent);

               expect(function() {
                 proofsFactory
                     .createSchnorrProofVerifier(
                         exponentiatedElement, voterIdVerifier,
                         electionEventIdVerifier, schnorrProof, group)
                     .verify();
               }).toThrow();
             });
       });

    it('should throw an exception in Schnorr proof verifier if electionEventId is null',
       function() {
         cryptolib(
             'proofs', 'commons', 'primitives.messagedigest', function(box) {

               // create group
               var q = new box.forge.jsbn.BigInteger('11');
               var generator = new box.forge.jsbn.BigInteger('2');
               var p = new box.forge.jsbn.BigInteger('23');
               var group =
                   new box.commons.mathematical.ZpSubgroup(generator, p, q);

               var exponent = new box.commons.mathematical.Exponent(
                   q, new box.forge.jsbn.BigInteger('8'));
               var exponentiatedElement =
                   group.getGenerator().exponentiate(exponent);

               var voterIdGenerator = '123456789';
               var electionEventIdGenerator = '99999999';

               var voterIdVerifier = '123456789';
               var electionEventIdVerifier;

               var proofsFactory = new box.proofs.ProofsFactory();
               var schnorrProof =
                   proofsFactory
                       .createSchnorrProofGenerator(
                           voterIdGenerator, electionEventIdGenerator, group)
                       .generate(exponentiatedElement, exponent);

               expect(function() {
                 proofsFactory
                     .createSchnorrProofVerifier(
                         exponentiatedElement, voterIdVerifier,
                         electionEventIdVerifier, schnorrProof, group)
                     .verify();
               }).toThrow();
             });
       });

    it('should throw an exception in Schnorr proof verifier if electionEventId is empty',
       function() {
         cryptolib(
             'proofs', 'commons', 'primitives.messagedigest', function(box) {

               // create group
               var q = new box.forge.jsbn.BigInteger('11');
               var generator = new box.forge.jsbn.BigInteger('2');
               var p = new box.forge.jsbn.BigInteger('23');
               var group =
                   new box.commons.mathematical.ZpSubgroup(generator, p, q);

               var exponent = new box.commons.mathematical.Exponent(
                   q, new box.forge.jsbn.BigInteger('8'));
               var exponentiatedElement =
                   group.getGenerator().exponentiate(exponent);

               var voterIdGenerator = '123456789';
               var electionEventIdGenerator = '99999999';

               var voterIdVerifier = '123456789';
               var electionEventIdVerifier = '';

               var proofsFactory = new box.proofs.ProofsFactory();
               var schnorrProof =
                   proofsFactory
                       .createSchnorrProofGenerator(
                           voterIdGenerator, electionEventIdGenerator, group)
                       .generate(exponentiatedElement, exponent);

               expect(function() {
                 proofsFactory
                     .createSchnorrProofVerifier(
                         exponentiatedElement, voterIdVerifier,
                         electionEventIdVerifier, schnorrProof, group)
                     .verify();
               }).toThrow();
             });
       });

    describe('plaintext proof', function() {
      it('must fail if plaintext and the public key have a different number of arguments',
         function() {
           cryptolib('*', function(box) {
             var elGamalCipherFactory =
                 new box.homomorphic.cipher.factory.ElGamalCipherFactory();
             var keyFactory = new box.homomorphic.keypair.factory.KeyFactory();

             var p = new box.forge.jsbn.BigInteger(
                 '16495768820687182934009927347170440458984298969141051719651115246768228783533993705048522613555003722650163857541125634359204551517133551948222225229585505473854815904204008387572449239572558997742610313328207134588877674958965112510857989409372589489554367815761232020129433262382857561981217475899722020926354221968452402385754809505679432634661210095701454463437258972380072638986797327376359801509825066468445666991457815992978097875265987862649581950696045865510189368336440306143914792406918514769060068547350680676698071521344166677089027364466838527577675388855690260527795812471209293838170074431021658585769');
             var q = new box.forge.jsbn.BigInteger(
                 '96020784172851661018443454307652214686331639842501459760074411037927395553939');
             var generator = new box.forge.jsbn.BigInteger(
                 '15130260694873909459986577784204643986832006548758872568127622990613286376947389953860539257554587993925082794507831758880350292337036239661614300430033670574377146869864951070388980213523097422627922584301566881102629991359716406049006152033115595975218156523898904324261190660093347613804122603060933508651584944555007181780395855126908781477484110624848678463182770318846991956864510428932259181036820923323061517278008748271670358287455340697499004281391354210072366308177032171585041936224750556137265259765883084633653387023221827373593952176436229429968550363326770646572341416840037353790767464212018954641189');
             var plaintextValues =
                 '13001958155330604183283440349326249836910073645746606152086317081542370925085323829577576343220220970830242334422088928335776849693699317596697308070491655988846936544490170854760622263229593132359288598939754030438763377074672036413960553517345827407874240954931856460473275871494952759213809834622191632962928152282758068810785997095964792534886071457598558200037994837193502017861972726981702601645743757363301481452380559572428601079773415878406878889283104921714313573036550932216793644548235628221219857860491590917419188368179146906649074848254341715041556794836535625862564803932425535053708105664756328176096,13231973095563029671832096284884900786942379344314765999736867442501058904676516417925101650742389109597711424534876455182391728375468332757263296899395351639193353410112338073499025899736418030529915324365551044922832874533047175715575665120707774002324384088317703371342441254493502521221058572909498259802514124188958407279318160157200557318801491755304390175475424809222021529440615330205038504228764024791004717836281566455683657139407029417762297815388016430137008344688954594677000059036704922079131336478242363366789868164308084428340745898909076987038168924165852440487400698910077949024596427386762477753127,14962213442437221630882804374502807481065630653554446432724314309377638233420429625929060616149342043360565572219423869257414407292350550499520720685455656488232644853879526758539416856088474668103469469539535531657659096824387210346084505215030036305938457977750754924998601715702575511194945674310421459334341817535064482476480331751171219419177177690275196093512303662432640330876384877571377755052302164787402266089676321850441055346812973279399849013829646051767527082830058880156180804337513629780923908712327566442241827419862207132399832645578550470975229103528239481602587884774035574980636031799832387127824';
             plaintextValues = plaintextValues.split(',');
             var publickey =
                 '2310052637281374826163980155072703478550584783282353794746356503851736624950501110627753937319986533000522391643440057809085228551963268616650076198499939080674555452672248616965754928293235729345758867884335314010776031118255924016690941973710021793693357184670835265674549998079458749041612609723185323556418090275187898731901111571900886838242789201627029788753318822261542649942667275986354422715719555421167864656006766965757148569592487004683308842191788591435697129834559463075935646313837018575516319421503514590374988521988732632646137082482614398122769481744648900076625388202771688539721397175709860657215,10992040365912330212603556159890860989323436780424734140469776597559966083776288793792880271187249577475862540041272265165115141691436552098724587148672885376255101720449710739879257167893375710652999579682329540866493597320896396042034863583144965792072687133983833723367505914551649613644957007736294052065759536432864892568886279889430332858208212502323472429844596803009794879201124168960173108172884523529447057933188670605500761004550561618533233760048349811136008540506656716161194168608193768775892759430117403245548580741988574926317015003026743034307396424854331578214723160905311258827711514036727758661443,2966454546948674594238484453818820495774263494738027649885606698735626946977004754473084281799793802225340057166391055854897568455044693120227990997044954520274944912364134982880734979624278026290300479874061515681112538596438177835791333982353892136013223338695390663410151102503147241467125785231395240349671275198727614663753021483991961941587552003516822754894985284436598456509038426029451562110689110854200741545361500678654576568967692431517292344770939502725349301506972598902856573261152531261931708724855752770349361196880952259389543735606329934472812841863925491905824596299316439858950888740168931063033,16685125032225465591271616129024153088399594055921872535905780296582091131024932497146054111843749963435248897831820496896855297302629640382562118371399923587479991981933850508478973979849045483506501618718824692791050899387832529345913319557326115349466503641556936384534756871248087479236266210661587928787040614097509670326965654744522366069845631192304570814294808544467147342154545110452347943098767091892623807533767816665018437155453169438229244628337513271777636288916880160385420829994354060040651547330045332962210808881666427991175014815542151556166234899209736414331653334634166108740897978989610512241';
             publickey = publickey.split(',');

             var group =
                 new box.commons.mathematical.ZpSubgroup(generator, p, q);

             // create public key
             var value, groupElement;
             var elements = [];
             for (var i = 0; i < publickey.length; i++) {
               value = new box.forge.jsbn.BigInteger('' + publickey[i]);
               groupElement = new box.commons.mathematical.ZpGroupElement(
                   value, group.getP(), group.getQ());
               elements.push(groupElement);
             }

             var elGamalPublicKey = keyFactory.createPublicKey(elements, group);

             // plaintext
             var plaintext = [];
             for (i = 0; i < plaintextValues.length; i++) {
               value = new box.forge.jsbn.BigInteger(plaintextValues[i]);
               groupElement = new box.commons.mathematical.ZpGroupElement(
                   value, group.getP(), group.getQ());
               plaintext.push(groupElement);
             }

             // get encrypters
             var encrypter =
                 elGamalCipherFactory.createEncrypter(elGamalPublicKey);

             var ciphertext = encrypter.encryptGroupElements(plaintext);

             expect(function() {
               box.proofs.service.createPlaintextProof(
                   elGamalPublicKey, ciphertext, plaintext, ciphertext.getR(),
                   group);
             }).toThrow();
           });
         });
    });
  });

  describe('ProofPreComputedValues ... ', function() {
    it('should be serialized correctly to JSON format', function() {
      cryptolib('*', function(box) {
        var p = new box.forge.jsbn.BigInteger('23');
        var q = new box.forge.jsbn.BigInteger('11');

        var exponent0 = new box.commons.mathematical.Exponent(
            q, new box.forge.jsbn.BigInteger('2'));
        var exponent1 = new box.commons.mathematical.Exponent(
            q, new box.forge.jsbn.BigInteger('8'));
        var exponent2 = new box.commons.mathematical.Exponent(
            q, new box.forge.jsbn.BigInteger('9'));
        var exponents = [exponent0, exponent1, exponent2];

        var zpGroupElement_p23_v2 = new box.commons.mathematical.ZpGroupElement(
            new box.forge.jsbn.BigInteger('2'), p, q);
        var zpGroupElement_p23_v3 = new box.commons.mathematical.ZpGroupElement(
            new box.forge.jsbn.BigInteger('3'), p, q);
        var zpGroupElement_p23_v4 = new box.commons.mathematical.ZpGroupElement(
            new box.forge.jsbn.BigInteger('4'), p, q);
        var phiOutputs = [
          zpGroupElement_p23_v2, zpGroupElement_p23_v3, zpGroupElement_p23_v4
        ];

        var precomputationValues =
            new box.proofs.ProofPreComputedValues(exponents, phiOutputs);
        var jsonAsString = precomputationValues.stringify();

        expect(jsonAsString).toContain('"preComputed":');
        expect(jsonAsString).toContain('"p":"Fw=="');
        expect(jsonAsString).toContain('"q":"Cw=="');
        expect(jsonAsString).toContain('"exponents":["Ag==","CA==","CQ=="]');
        expect(jsonAsString).toContain('"phiOutputs":["Ag==","Aw==","BA=="]');
        expect(jsonAsString.length)
            .toBe(
                '{"preComputed":{"p":"Fw==","q":"Cw==","exponents":["Ag==","CA==","CQ=="],"phiOutputs":["Ag==","Aw==","BA=="]}}'
                    .length);
      });
    });

    it('should be deserialized correctly from JSON format', function() {
      cryptolib('*', function(box) {
        var preComputedValues = box.proofs.utils.deserializeProofPreComputedValues(
            '{"preComputed":{"p":"Fw==","q":"Cw==","exponents":["Ag==","CA==","CQ=="],"phiOutputs":["Ag==","Aw==","BA=="]}}');
        expect(preComputedValues).toBeDefined();

        expect(preComputedValues.getExponents().length).toEqual(3);
        expect(preComputedValues.getExponents()[0].getQ().toString())
            .toEqual('11');
        expect(preComputedValues.getExponents()[0].getValue().toString())
            .toEqual('2');
        expect(preComputedValues.getExponents()[1].getValue().toString())
            .toEqual('8');
        expect(preComputedValues.getExponents()[2].getValue().toString())
            .toEqual('9');

        expect(preComputedValues.getPhiOutputs().length).toEqual(3);
        expect(preComputedValues.getPhiOutputs()[0].getP().toString())
            .toEqual('23');
        expect(preComputedValues.getPhiOutputs()[0].getQ().toString())
            .toEqual('11');
        expect(
            preComputedValues.getPhiOutputs()[0].getElementValue().toString())
            .toEqual('2');
        expect(
            preComputedValues.getPhiOutputs()[1].getElementValue().toString())
            .toEqual('3');
        expect(
            preComputedValues.getPhiOutputs()[2].getElementValue().toString())
            .toEqual('4');
      });
    });
  });

  function createSchnorrProof(
      proofsFactory, group, exponentiatedElement, exponent, voterIdGenerator,
      electionEventIdGenerator) {
    return proofsFactory.createSchnorrProofGenerator(group).generate(
        exponentiatedElement, exponent, voterIdGenerator,
        electionEventIdGenerator);
  }
});
