/* * 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 */ /* jshint node:true */ 'use strict'; var OrProofTestData = require('./data/or-proof-data'); var cryptoPolicy = require('scytl-cryptopolicy'); var zkProof = require('../lib/index'); var messageDigest = require('scytl-messagedigest'); var mathematical = require('scytl-mathematical'); var secureRandom = require('scytl-securerandom'); var elGamal = require('scytl-elgamal'); var codec = require('scytl-codec'); describe('The zero-knowledge proof module should be able to ...', function() { var proofService_; var group_; var anotherGroup_; var secret_; var ciphertext_; var anotherSecret_; var anotherCiphertext_; var publicKey_; var anotherPublicKey_; var index_; var elements_; var elementsWithDifferentIndexElement_; var numElements_; var data_; var otherData_; var proofHandler_; var proof_; var preComputation_; beforeAll(function() { proofService_ = zkProof.newService(); var testData = new OrProofTestData(); var elGamalService = elGamal.newService(); group_ = testData.getGroup(); anotherGroup_ = testData.getAnotherGroup(); var encryptedElements = testData.getEncryptedElements(); secret_ = encryptedElements.secret; ciphertext_ = elGamalService.newEncryptedElements( encryptedElements.gamma, encryptedElements.phis); var otherEncryptedElements = testData.getOtherEncryptedElements(); anotherSecret_ = otherEncryptedElements.secret; anotherCiphertext_ = elGamalService.newEncryptedElements( otherEncryptedElements.gamma, otherEncryptedElements.phis); publicKey_ = testData.getPublicKey(); anotherPublicKey_ = testData.getAnotherPublicKey(); index_ = testData.getIndex(); elements_ = testData.getElements(); elementsWithDifferentIndexElement_ = testData.getElementsWithDifferentIndexElement(); numElements_ = elements_.length; data_ = testData.getStringData(); otherData_ = testData.getOtherStringData(); proofHandler_ = proofService_.newOrProofHandler(group_).init(publicKey_); proof_ = proofHandler_.generate(secret_, elements_, index_, ciphertext_); preComputation_ = proofHandler_.preCompute(numElements_); }); beforeEach(function() { proofHandler_ = proofService_.newOrProofHandler(group_).init(publicKey_); }); describe('create a zero-knowledge proof service that should be able to ..', function() { describe('create an OR proof handler that should be able to', function() { it('generate and verify an OR proof', function() { var verified = proofHandler_.verify(proof_, elements_, ciphertext_); expect(verified).toBeTruthy(); }); it('generate and verify an OR proof using, a specified cryptographic policy', function() { var policy = cryptoPolicy.newInstance(); policy.proofs.messageDigest.algorithm = cryptoPolicy.options.proofs.messageDigest.algorithm.SHA512_224; var proofService = zkProof.newService({policy: policy}); var proofHandler = proofService.newOrProofHandler(group_).init(publicKey_); proof_ = proofHandler.generate(secret_, elements_, index_, ciphertext_); var verified = proofHandler.verify(proof_, elements_, ciphertext_); expect(verified).toBeTruthy(); }); it('generate and verify an OR proof using, a specified message digest service object', function() { var policy = cryptoPolicy.newInstance(); policy.proofs.messageDigest.algorithm = cryptoPolicy.options.proofs.messageDigest.algorithm.SHA512_224; var messageDigestService = messageDigest.newService({policy: policy}); var proofService = zkProof.newService({messageDigestService: messageDigestService}); var proofHandler = proofService.newOrProofHandler(group_).init(publicKey_); proof_ = proofHandler.generate(secret_, elements_, index_, ciphertext_); var verified = proofHandler.verify(proof_, elements_, ciphertext_); expect(verified).toBeTruthy(); }); it('generate and verify an OR proof using, a specified secure random service object', function() { var proofService = zkProof.newService( {secureRandomService: secureRandom.newService()}); var proofHandler = proofService.newOrProofHandler(group_).init(publicKey_); proof_ = proofHandler.generate(secret_, elements_, index_, ciphertext_); var verified = proofHandler.verify(proof_, elements_, ciphertext_); expect(verified).toBeTruthy(); }); it('generate and verify an OR proof using, a specified mathematical service object', function() { var proofService = zkProof.newService( {mathematicalService: mathematical.newService()}); var proofHandler = proofService.newOrProofHandler(group_).init(publicKey_); proof_ = proofHandler.generate(secret_, elements_, index_, ciphertext_); var verified = proofHandler.verify(proof_, elements_, ciphertext_); expect(verified).toBeTruthy(); }); it('generate and verify an OR proof, using provided auxiliary data', function() { // Data as string. var proof = proofHandler_.generate( secret_, elements_, index_, ciphertext_, {data: data_}); var verified = proofHandler_.verify( proof, elements_, ciphertext_, {data: data_}); expect(verified).toBeTruthy(); // Data as bytes. proof = proofHandler_.generate( secret_, elements_, index_, ciphertext_, {data: codec.utf8Encode(data_)}); verified = proofHandler_.verify( proof, elements_, ciphertext_, {data: codec.utf8Encode(data_)}); expect(verified).toBeTruthy(); }); it('generate and verify an OR proof, using a pre-computation', function() { var proof = proofHandler_.generate( secret_, elements_, index_, ciphertext_, {preComputation: preComputation_}); var verified = proofHandler_.verify(proof, elements_, ciphertext_); expect(verified).toBeTruthy(); }); it('generate and verify an OR proof, using empty string auxiliary data', function() { var proof = proofHandler_.generate( secret_, elements_, index_, ciphertext_, {data: ''}); var verified = proofHandler_.verify(proof, elements_, ciphertext_, {data: ''}); expect(verified).toBeTruthy(); }); it('pre-compute, generate and verify a OR proof, using method chaining', function() { var preComputation = proofService_.newOrProofHandler(group_) .init(publicKey_) .preCompute(numElements_); var proof = proofService_.newOrProofHandler(group_) .init(publicKey_) .generate( secret_, elements_, index_, ciphertext_, {data: data_, preComputation: preComputation}); var verified = proofService_.newOrProofHandler(group_) .init(publicKey_) .verify(proof, elements_, ciphertext_, {data: data_}); expect(verified).toBeTruthy(); }); it('create a new plaintext exponent equality ZeroKnowledgeProof object', function() { var hash = proof_.hash; var values = proof_.values; var proof = proofService_.newProof(hash, values); var verified = proofHandler_.verify(proof, elements_, ciphertext_); expect(verified).toBeTruthy(); }); it('create a new plaintext exponent equality ZeroKnowledgeProofPreComputation object', function() { var exponents = preComputation_.exponents; var phiOutputs = preComputation_.phiOutputs; var preComputation = proofService_.newPreComputation(exponents, phiOutputs); var proof = proofHandler_.generate( secret_, elements_, index_, ciphertext_, {preComputation: preComputation}); var verified = proofHandler_.verify(proof, elements_, ciphertext_); expect(verified).toBeTruthy(); }); it('serialize and deserialize an OR proof', function() { var proofJson = proof_.toJson(); var proof = proofService_.newProof(proofJson); var verified = proofHandler_.verify(proof, elements_, ciphertext_); expect(verified).toBeTruthy(); }); it('serialize and deserialize an OR proof pre-computation', function() { var preComputationJson = preComputation_.toJson(); var preComputation = proofService_.newPreComputation(preComputationJson); var proof = proofHandler_.generate( secret_, elements_, index_, ciphertext_, {preComputation: preComputation}); var verified = proofHandler_.verify(proof, elements_, ciphertext_); expect(verified).toBeTruthy(); }); it('fail to verify an OR proof that was generated with a secret not used to generate the ciphertext', function() { var proof = proofHandler_.generate( anotherSecret_, elements_, index_, ciphertext_); var verified = proofHandler_.verify(proof, elements_, ciphertext_); expect(verified).toBeFalsy(); }); it('fail to verify an OR proof that was generated with a publicKey not used to generate the ciphertext', function() { proofHandler_.init(anotherPublicKey_, numElements_); var proof = proofHandler_.generate(secret_, elements_, index_, ciphertext_); var verified = proofHandler_.verify(proof, elements_, ciphertext_); expect(verified).toBeFalsy(); }); it('fail to verify an OR proof that was generated with elements with index element not used to generate the ciphertext', function() { var proof = proofHandler_.generate( secret_, elementsWithDifferentIndexElement_, index_, ciphertext_, data_); var verified = proofHandler_.verify( proof, elementsWithDifferentIndexElement_, ciphertext_); expect(verified).toBeFalsy(); }); it('fail to verify an OR proof that was generated with a ciphertext not generated with the public key', function() { var proof = proofHandler_.generate( secret_, elements_, index_, anotherCiphertext_); var verified = proofHandler_.verify(proof, elements_, anotherCiphertext_); expect(verified).toBeFalsy(); }); it('fail to verify an OR proof when using a public key not used to generate the proof', function() { var verified = proofHandler_.init(anotherPublicKey_, numElements_) .verify(proof_, elements_, ciphertext_); expect(verified).toBeFalsy(); }); it('fail to verify an OR proof when using elements with index element not used to generate the proof', function() { var verified = proofHandler_.verify( proof_, elementsWithDifferentIndexElement_, ciphertext_); expect(verified).toBeFalsy(); }); it('fail to verify an OR proof when using a ciphertext not used to generate the proof', function() { var verified = proofHandler_.verify(proof_, elements_, anotherCiphertext_); expect(verified).toBeFalsy(); }); it('fail to verify an OR proof when using auxiliary data not used to generate the proof', function() { var proof = proofHandler_.generate( secret_, elements_, index_, ciphertext_, {data: data_}); var verified = proofHandler_.verify( proof, elements_, ciphertext_, {data: otherData_}); expect(verified).toBeFalsy(); }); it('throw an error when generating a proof before the handler has been initialized with a public key', function() { var proofHandler = proofService_.newOrProofHandler(group_); expect(function() { proofHandler.generate(secret_, elements_, index_, ciphertext_); }).toThrow(); }); it('throw an error when pre-computing a proof before the handler has been initialized with a public key', function() { var proofHandler = proofService_.newOrProofHandler(group_); expect(function() { proofHandler.preCompute(numElements_); }).toThrow(); }); it('throw an error when verifying a proof before the handler has been initialized with with a public key', function() { var proofHandler = proofService_.newOrProofHandler(group_); expect(function() { proofHandler.verify(proof_, elements_, ciphertext_); }).toThrow(); }); }); }); });