main.cpp File Reference

Contains the main function of the c++ verificatum verifier. More...

#include <cstring>
#include <cstdlib>
#include <cstdint>
#include <string>
#include <vector>
#include <iostream>
#include <iomanip>
#include "cryptotools/cryptotools.hpp"
#include "verifierutils/verifierutils.hpp"
#include "arithm/arithm.hpp"
#include "elgamal/elgamal.hpp"
#include "xmlconfig/xmlconfig.hpp"
#include "proofs/proofs.hpp"

Go to the source code of this file.

Functions

void displayHelp ()
 Displays the help for the command line use of this program.
std::string concatenation (std::string str1, char separator, std::string str2)
 Returns the concatenation of the two strings separated by the separator.
std::string getPath (std::string dir, std::string type, unsigned int l)
 Returns the path of the file of name <dir/typell.bt> where "ll" are the two decimals of l.
void preprocessArgs (int argc, char **argv, std::string &configFile, std::string &path2roDir)
 Parses the command-line arguments to see that the program was called correctly and initialises the variables accordingly.
int main (int argc, char **argv)
 Runs the core verification described in the verificatum verifier specification.

Detailed Description

Contains the main function of the c++ verificatum verifier.

Author
Léo Perrin
Date
Time-stamp: <2012-09-09 17:25:18 leo>

Definition in file main.cpp.

Function Documentation

std::string concatenation ( std::string  str1,
char  separator,
std::string  str2 
)

Returns the concatenation of the two strings separated by the separator.

Parameters
str1The first string.
separatorA char to put between the strings
str2The second one.
Returns
str1||separator||str2

Definition at line 51 of file main.cpp.

{
std::string res = str1;
res.push_back(separator);
res.insert(res.end(),str2.begin(),str2.end());
return res;
}
void displayHelp ( )

Displays the help for the command line use of this program.

Definition at line 29 of file main.cpp.

{
std::cout<<"\n c++ verificatum verifier\n\n"
<<"To use this software, use the following line:\n\n"
<<"./cppverifier <protInfo.xml> <roProof>\n\n"
<<"Where <protInfo.xml> is an xml file desciring the "
<<"protocol info and <roProof> is the path to the "
<<"proof directory.\n"
<<std::endl;
}
std::string getPath ( std::string  dir,
std::string  type,
unsigned int  l 
)

Returns the path of the file of name <dir/typell.bt> where "ll" are the two decimals of l.

Parameters
dirThe name of the directory.
typeThe name of the file.
lIts index.
Returns
dir || / || type || ll || .bt

Definition at line 71 of file main.cpp.

{
std::string res;
res = concatenation(dir,'/',type);
res.push_back('0' + l/10);
res.push_back('0' + l%10);
res = concatenation(res,'.',"bt");
return res;
}
int main ( int  argc,
char **  argv 
)

Runs the core verification described in the verificatum verifier specification.

Parameters
argcThe number of arguments given in the CLI
argvThe arguments given in the CLI
Returns
0 if the computation of the mix-servers were valid, 1 if they are to be rejected.

Definition at line 127 of file main.cpp.

{
bool readingWasOK; // to know if proofs are well initialized
// 1- done by hand
/* NOTHING */
std::cout<<"1. Must be done by hand."<<std::endl;
// 2- Public parameters
std::cout<<"2. Initialising public parameters"<<std::endl;
std::string protInfo, roProof;
preprocessArgs(argc,argv,protInfo,roProof);
XmlConfig * config = new XmlConfig(protInfo);
arithm::Group * gq = config->getPgroup();
arithm::Group * M = gq;
// 3- prefix to random oracles
std::cout<<"3. Setting up the prefix for the RO"<<std::endl;
std::vector<uint8_t> content, rho;
content = verifierUtils::file2bytes(protInfo);
H->hash(content);
rho = H->getHash();
// 4- joint public key
std::cout<<"4. Reading the joint public key"<<std::endl;
verifierUtils::ByteTree * btPublicKey = verifierUtils::ByteTree::parseFile(concatenation(roProof,'/',"FullPublicKey.bt"));
arithm::Elmt pk = gq->getElmt(btPublicKey->getChild(1)->getChild(1));
// 5- individual public keys
std::cout<<"5. Reading individual public keys"<<std::endl;
unsigned int k = config->getNopart();
for (unsigned int l=1; l<=k; l++)
{
std::cout<<" reading key #"<<l<<std::endl;
y.addElmt(gq->getElmt(btIndKey));
}
arithm::Elmt prod = gq->product(y);
if (!gq->compare(prod,pk))
{
std::cout<<"\nREJECT: $\\prod_{l=1}^{k} y_l \\noteq pk$"<<std::endl;
return 1;
}
else
std::cout<<" We do have $\\prod_{l=1}^{k} y_l \\eq pk$"<<std::endl;
// 6- Array of Input Ciphertexts
std::cout<<"6. Reading the 0th array of input ciphertexts"<<std::endl;
std::cout<<" reading cipher text #0"<<std::endl;
verifierUtils::ByteTree * btArrayCipherText = verifierUtils::ByteTree::parseFile(getPath(roProof,"CiphertextList",0));
elGamal::ArrayOfCiphers LlMinus1(btArrayCipherText,C);
unsigned int N = LlMinus1.size();
unsigned int N0 = (config->getMaxciph() != 0)? config->getMaxciph() : N;
std::cout<<" N="<<N<<", N_0="<<N0<<std::endl;
// 7- Proofs of shuffle
unsigned int lambda = config->getThres();
std::cout<<"7. PROOFS OF SHUFFLE for l=1.."<<lambda<<std::endl;
for (unsigned int l=1; l<=lambda; l++)
{
std::cout<<" l="<<l<<std::endl;
// a) Verify Proof of Shuffle of Commitments
verifierUtils::ByteTree * btUl = verifierUtils::ByteTree::parseFile(getPath(roProof,"PermutationCommitment",l));
verifierUtils::ByteTree * tauPos = verifierUtils::ByteTree::parseFile(getPath(roProof,"PoSCommitment",l));
readingWasOK, config, rho, N0, ul, tauPos, sigmaPos);
if (!readingWasOK)
{
std::cout<<" a) Proof of shuffle of commitments could not be initialized."<<std::endl;
ul = shuffleOfCommitments.getGenerators();
}
else if (!shuffleOfCommitments.isEverythingOK())
{
std::cout<<" a) Proof of shuffle of commitments went wrong so ul=h"<<std::endl;
ul = shuffleOfCommitments.getGenerators();
}
else
std::cout<<" a) Proof of shuffle of commitments passed."<<std::endl;
// b) Shrink Permutation Commitment
std::vector<bool> tl = keepList->toBoolArray();
if (tl.size() != N0)
{
tl.assign(N0, false);
for (unsigned int i=0; i<N; i++)
tl[i] = true;
}
else
{
unsigned int hammingWeight = 0;
for (unsigned int i=0; i<N0; i++)
if (tl[i])
hammingWeight++;
if (hammingWeight != N)
{
tl.assign(N0, false);
for (unsigned int i=0; i<N; i++)
tl[i] = true;
}
}
ul = ul.subArray(tl);
std::cout<<" b) Keep list parsed."<<std::endl;
// c) Array of CipherTexts
btArrayCipherText = verifierUtils::ByteTree::parseFile(getPath(roProof,"CiphertextList",l));
elGamal::ArrayOfCiphers Ll(btArrayCipherText,C);
std::cout<<" c) array of ciphertext L_"<<l<<" read."<<std::endl;
// d) Verify Commitment-Consistent Proof of Shuffle
verifierUtils::ByteTree * tauCCPos = verifierUtils::ByteTree::parseFile(getPath(roProof,"CCPoSCommitment",l));
verifierUtils::ByteTree * sigmaCCPos = verifierUtils::ByteTree::parseFile(getPath(roProof,"CCPoSReply",l));
proofs::ProofOfShuffleOfCiphers commitmentConsistent(
readingWasOK, config, rho, ul, N, R, C, pk, LlMinus1, Ll, tauCCPos, sigmaCCPos);
if ( (!readingWasOK) || (!commitmentConsistent.isEverythingOK()) )
{
std::cout<<" d) Proof of commitment consistent shuffle went wrong..."<<std::endl;
if ( !C.compare(LlMinus1,Ll) )
{
std::cout<<"\nREJECT: Algorithm 18 rejected and $L_{l-1} \\neq L_l$ "<<std::endl;
return 1;
}
std::cout<<" ... but L_{l-1} \\eq L_l$"<<std::endl;
}
else
{
std::cout<<" d) Proof of commitment consistent shuffle passed."<<std::endl;
}
LlMinus1 = Ll;
}
// 8- Proof of decryption
std::cout<<"8. PROOF OF DECRYPTION for l=1.."<<k<<std::endl;
for (unsigned int l=1; l<=k; l++)
{
// 0) trying to read x_l
if (
(secretKey != NULL)
&& (gq->compare(
gq->exponentiation(gq->getGenerator(),arithm::Elmt (secretKey->getChild(1),NULL)),
y.getElmt(l)))
)
{
// a) x_l can be read and y_l == g^{x_l}
std::cout<<" a-case) x_l could be read and $y_l \\eq g^{x_l}$"<<std::endl;
arithm::Elmt xl(secretKey->getChild(1),NULL);
fl = C.pdec(xl,LlMinus1);
std::cout<<" f_l set to $PDec_{x_l}(L_{l-1})"<<std::endl;
}
else
{
// b) x_l can NOT be read
std::cout<<" b-case) x_l could not be read or $y_l \\noteq g^{x_l}$"<<std::endl;
verifierUtils::ByteTree * decFactor = verifierUtils::ByteTree::parseFile(getPath(roProof,"DecryptionFactors",l));
fl = gq->getArray(decFactor->getChild(1));
// running the proof of correct decryption
verifierUtils::ByteTree * taul = verifierUtils::ByteTree::parseFile(getPath(roProof,"DecrFactCommitment",l));
verifierUtils::ByteTree * sigmal = verifierUtils::ByteTree::parseFile(getPath(roProof,"DecrFactReply",l));
btArrayCipherText = verifierUtils::ByteTree::parseFile(getPath(roProof,"CiphertextList",lambda));
elGamal::ArrayOfCiphers Llambda(btArrayCipherText,C);
readingWasOK, config, rho, N, y.getElmt(l-1), C, M, Llambda, fl, taul, sigmal);
if (!readingWasOK)
{
std::cout<<"\nREJECT: Algorithm 18 rejected because it could not read the data it needed."
<<std::endl;
return 1;
}
else if (!correctDecryption.isEverythingOK())
{
std::cout<<"\nREJECT: Algorithm 18 rejected because $y^v y' \\noteq g^{k_x}$ or $PDec_{k_x}(A) \\noteq B^v B'."
<<std::endl;
return 1;
}
else
std::cout<<" Proof of correct decryption was OK for l="<<l<<std::endl;
}
f = gq->multiplication(f,fl);
}
// 9- verify output
std::cout<<"9. Verifying output"<<std::endl;
verifierUtils::ByteTree * btPlaintext = verifierUtils::ByteTree::parseFile(concatenation(roProof,'/',"PlaintextElements.bt"));
arithm::ArrayOfElmts m = M->getArray(btPlaintext);
verifierUtils::ByteTree * btArrayCipherTextLambda = verifierUtils::ByteTree::parseFile(getPath(roProof,"CiphertextList",lambda));
elGamal::ArrayOfCiphers Llambda(btArrayCipherTextLambda,C);
if ( !gq->compare(m,C.tdec(Llambda,f)) )
{
std::cout<<"\nREJECT: $m \\noteq TDec(L_{\\lambda}), \\prod_{l=1}^k f_l$"<<std::endl;
return 1;
}
else
std::cout<<" ... Output correct!"<<std::endl;
// If we reached this point then nothing was wrong. So it's great (\o/) and we return 0
std::cout<<"\nACCEPT"<<std::endl;
return 0;
}
void preprocessArgs ( int  argc,
char **  argv,
std::string &  configFile,
std::string &  path2roDir 
)

Parses the command-line arguments to see that the program was called correctly and initialises the variables accordingly.

It is assumed that the path lead to the correct files.

It is assumed that the option activating verbosity, namely "-v", is put in the first position if it is present.

Parameters
[in]argcThe number of command line arguments.
[in]argvThe command line arguments.
[out]configFileThe path to the configuration file.
[out]path2roDirThe path to the proof directory.

Definition at line 96 of file main.cpp.

{
if (argc < 3)
// Too few cli arguments
{
exit(1);
}
else
{
configFile.assign(argv[1]);
path2roDir.assign(argv[2]);
}
}