base.cpp 84 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754
  1. #include <iostream>
  2. #include <fstream>
  3. #include "base.hpp"
  4. extern const scalar_t bn_n;
  5. extern const twistpoint_fp2_t bn_twistgen;
  6. /* These lines need to be here so these static variables are defined,
  7. * but in C++ putting code here doesn't actually execute
  8. * (or at least, with g++, whenever it would execute is not at a useful time)
  9. * so we have an init() function to actually put the correct values in them. */
  10. size_t PrsonaBase::MAX_ALLOWED_VOTE = 2;
  11. Twistpoint PrsonaBase::EL_GAMAL_GENERATOR = Twistpoint();
  12. Scalar PrsonaBase::SCALAR_N = Scalar();
  13. Scalar PrsonaBase::DEFAULT_TALLY = Scalar();
  14. Scalar PrsonaBase::DEFAULT_VOTE = Scalar();
  15. bool PrsonaBase::SERVER_IS_MALICIOUS = false;
  16. bool PrsonaBase::CLIENT_IS_MALICIOUS = false;
  17. size_t PrsonaBase::LAMBDA = 0;
  18. // Quick and dirty function to calculate ceil(log base 2) with mpz_class
  19. mpz_class log2(mpz_class x)
  20. {
  21. mpz_class retval = 0;
  22. while (x > 0)
  23. {
  24. retval++;
  25. x = x >> 1;
  26. }
  27. return retval;
  28. }
  29. mpz_class bit(mpz_class x)
  30. {
  31. return x > 0 ? 1 : 0;
  32. }
  33. /********************
  34. * PUBLIC FUNCTIONS *
  35. ********************/
  36. /*
  37. * SETUP FUNCTIONS
  38. */
  39. // Must be called once before any usage of this class
  40. void PrsonaBase::init()
  41. {
  42. EL_GAMAL_GENERATOR = Twistpoint(bn_twistgen);
  43. SCALAR_N = Scalar(bn_n);
  44. DEFAULT_TALLY = Scalar(1);
  45. DEFAULT_VOTE = Scalar(1);
  46. }
  47. // Call this (once) if using malicious-security servers
  48. void PrsonaBase::set_server_malicious()
  49. {
  50. SERVER_IS_MALICIOUS = true;
  51. }
  52. // Call this (once) if using malicious-security clients
  53. void PrsonaBase::set_client_malicious()
  54. {
  55. CLIENT_IS_MALICIOUS = true;
  56. }
  57. // Call this (once) if using proof batching
  58. void PrsonaBase::set_lambda(size_t lambda)
  59. {
  60. LAMBDA = lambda;
  61. }
  62. /*
  63. * CONST GETTERS
  64. */
  65. size_t PrsonaBase::get_max_allowed_vote()
  66. {
  67. return MAX_ALLOWED_VOTE;
  68. }
  69. Twistpoint PrsonaBase::get_blinding_generator() const
  70. {
  71. return elGamalBlindGenerator;
  72. }
  73. Twistpoint PrsonaBase::get_blinding_generator(
  74. std::vector<Proof>& pi) const
  75. {
  76. pi = elGamalBlindGeneratorProof;
  77. return elGamalBlindGenerator;
  78. }
  79. /***********************
  80. * PROTECTED FUNCTIONS *
  81. ***********************/
  82. /*
  83. * PRIVATE ELEMENT SETTER
  84. */
  85. bool PrsonaBase::set_EG_blind_generator(
  86. const std::vector<Proof>& pi,
  87. const Twistpoint& currGenerator,
  88. size_t numServers)
  89. {
  90. if (!verify_generator_proof(pi, currGenerator, numServers))
  91. {
  92. std::cerr << "Could not set EG blind generator correctly." << std::endl;
  93. return false;
  94. }
  95. elGamalBlindGeneratorProof = pi;
  96. elGamalBlindGenerator = currGenerator;
  97. return true;
  98. }
  99. /*
  100. * BINARY SEARCH
  101. */
  102. /* Completely normal binary search
  103. * There might be a standard function for this in <algorithms>?
  104. * But it returns an iterator, not a size_t, so less useful. */
  105. size_t PrsonaBase::binary_search(
  106. const std::vector<Twistpoint> list,
  107. const Twistpoint& index) const
  108. {
  109. size_t lo, hi;
  110. lo = 0;
  111. hi = list.size() - 1;
  112. while (lo < hi)
  113. {
  114. size_t mid = (lo + hi) / 2;
  115. if (list[mid] < index)
  116. lo = mid + 1;
  117. else if (index == list[mid])
  118. return mid;
  119. else if (mid == lo)
  120. return lo;
  121. else hi = mid - 1;
  122. }
  123. return lo;
  124. }
  125. /*
  126. * SCHNORR PROOFS
  127. */
  128. Proof PrsonaBase::schnorr_generation(
  129. const Twistpoint& generator,
  130. const Twistpoint& commitment,
  131. const Scalar& log) const
  132. {
  133. Proof retval;
  134. std::stringstream oracleInput;
  135. Scalar u;
  136. u.set_random();
  137. Twistpoint U = generator * u;
  138. oracleInput << generator << commitment << U;
  139. Scalar x = oracle(oracleInput.str());
  140. Scalar z = log * x + u;
  141. retval.challengeParts.push_back(x);
  142. retval.responseParts.push_back(z);
  143. return retval;
  144. }
  145. bool PrsonaBase::schnorr_verification(
  146. const Twistpoint& generator,
  147. const Twistpoint& commitment,
  148. const Scalar& x,
  149. const Scalar& z) const
  150. {
  151. Twistpoint U = generator * z - commitment * x;
  152. std::stringstream oracleInput;
  153. oracleInput << generator << commitment << U;
  154. return x == oracle(oracleInput.str());
  155. }
  156. /*
  157. * OWNERSHIP PROOFS
  158. */
  159. // Prove ownership of the short term public key
  160. Proof PrsonaBase::generate_ownership_proof(
  161. const Twistpoint& generator,
  162. const Twistpoint& commitment,
  163. const Scalar& log) const
  164. {
  165. if (!CLIENT_IS_MALICIOUS)
  166. {
  167. Proof retval;
  168. retval.hbc = "PROOF";
  169. return retval;
  170. }
  171. return schnorr_generation(generator, commitment, log);
  172. }
  173. bool PrsonaBase::verify_ownership_proof(
  174. const Proof& pi,
  175. const Twistpoint& generator,
  176. const Twistpoint& commitment) const
  177. {
  178. if (!CLIENT_IS_MALICIOUS)
  179. return pi.hbc == "PROOF";
  180. Scalar c = pi.challengeParts[0];
  181. Scalar z = pi.responseParts[0];
  182. return schnorr_verification(generator, commitment, c, z);
  183. }
  184. /*
  185. * ITERATED SCHNORR PROOFS
  186. */
  187. Proof PrsonaBase::add_to_generator_proof(
  188. const Twistpoint& currGenerator,
  189. const Scalar& seed) const
  190. {
  191. Proof retval;
  192. if (!SERVER_IS_MALICIOUS)
  193. {
  194. retval.hbc = "PROOF";
  195. return retval;
  196. }
  197. Twistpoint nextGenerator = currGenerator * seed;
  198. retval = schnorr_generation(currGenerator, nextGenerator, seed);
  199. retval.curvepointUniversals.push_back(currGenerator);
  200. return retval;
  201. }
  202. bool PrsonaBase::verify_generator_proof(
  203. const std::vector<Proof>& pi,
  204. const Twistpoint& currGenerator,
  205. size_t numServers) const
  206. {
  207. if (pi.size() != numServers || numServers == 0)
  208. return false;
  209. bool retval = true;
  210. if (!SERVER_IS_MALICIOUS)
  211. {
  212. for (size_t i = 0; i < pi.size(); i++)
  213. retval = retval && pi[i].hbc == "PROOF";
  214. return retval;
  215. }
  216. if (pi[0].curvepointUniversals[0] != EL_GAMAL_GENERATOR)
  217. return false;
  218. for (size_t i = 0; i < pi.size(); i++)
  219. {
  220. Twistpoint generator = pi[i].curvepointUniversals[0];
  221. Twistpoint commitment = (i == pi.size() - 1 ? currGenerator : pi[i + 1].curvepointUniversals[0]);
  222. Scalar c = pi[i].challengeParts[0];
  223. Scalar z = pi[i].responseParts[0];
  224. retval = retval && schnorr_verification(generator, commitment, c, z);
  225. if (!retval)
  226. std::cerr << "Error in index " << i+1 << " of " << pi.size() << std::endl;
  227. }
  228. return retval;
  229. }
  230. /*
  231. * REPUTATION PROOFS
  232. */
  233. // A pretty straightforward range proof (generation)
  234. std::vector<Proof> PrsonaBase::generate_reputation_proof(
  235. const Proof& ownershipProof,
  236. const EGCiphertext& commitment,
  237. const Scalar& currentScore,
  238. const Scalar& threshold,
  239. const Scalar& inverseKey,
  240. size_t numClients) const
  241. {
  242. std::vector<Proof> retval;
  243. // Base case
  244. if (!CLIENT_IS_MALICIOUS)
  245. {
  246. retval.push_back(Proof("PROOF"));
  247. return retval;
  248. }
  249. // Don't even try if the user asks to make an illegitimate proof
  250. if (threshold.toInt() > (numClients * MAX_ALLOWED_VOTE))
  251. return retval;
  252. // We really have two consecutive proofs in a junction.
  253. // The first is to prove that we are the stpk we claim we are
  254. retval.push_back(ownershipProof);
  255. // The value we're actually using in our proof
  256. mpz_class proofVal = (currentScore - threshold).toInt();
  257. // Top of the range in our proof determined by what scores are even possible
  258. mpz_class proofBits = log2(numClients * MAX_ALLOWED_VOTE - threshold.toInt());
  259. // Don't risk a situation that would divulge our private key
  260. if (proofBits <= 1)
  261. proofBits = 2;
  262. // This seems weird, but remember our base is A_t^r, not g^t
  263. std::vector<Scalar> masksPerBit;
  264. masksPerBit.push_back(inverseKey);
  265. for (size_t i = 1; i < proofBits; i++)
  266. {
  267. Scalar currMask;
  268. currMask.set_random();
  269. masksPerBit.push_back(currMask);
  270. masksPerBit[0] = masksPerBit[0] - (currMask * Scalar(1 << i));
  271. }
  272. // Taken from Fig. 1 in https://eprint.iacr.org/2014/764.pdf
  273. for (size_t i = 0; i < proofBits; i++)
  274. {
  275. Proof currProof;
  276. Twistpoint g, h, C, C_a, C_b;
  277. g = commitment.mask;
  278. h = elGamalBlindGenerator;
  279. mpz_class currBit = bit(proofVal & (1 << i));
  280. Scalar a, s, t, m, r;
  281. a.set_random();
  282. s.set_random();
  283. t.set_random();
  284. m = Scalar(currBit);
  285. r = masksPerBit[i];
  286. C = g * r + h * m;
  287. currProof.curvepointUniversals.push_back(C);
  288. C_a = g * s + h * a;
  289. C_b = g * t + h * a * m;
  290. std::stringstream oracleInput;
  291. oracleInput << g << h << C << C_a << C_b;
  292. Scalar x = oracle(oracleInput.str());
  293. currProof.challengeParts.push_back(x);
  294. Scalar f, z_a, z_b;
  295. f = m * x + a;
  296. z_a = r * x + s;
  297. z_b = r * (x - f) + t;
  298. currProof.responseParts.push_back(f);
  299. currProof.responseParts.push_back(z_a);
  300. currProof.responseParts.push_back(z_b);
  301. retval.push_back(currProof);
  302. }
  303. return retval;
  304. }
  305. // A pretty straightforward range proof (verification)
  306. bool PrsonaBase::verify_reputation_proof(
  307. const std::vector<Proof>& pi,
  308. const Twistpoint& generator,
  309. const Twistpoint& owner,
  310. const EGCiphertext& commitment,
  311. const Scalar& threshold) const
  312. {
  313. // Reject outright if there's no proof to check
  314. if (pi.empty())
  315. {
  316. std::cerr << "Proof was empty, aborting." << std::endl;
  317. return false;
  318. }
  319. // If the range is so big that it wraps around mod n,
  320. // there's a chance the user actually made a proof for a very low reputation
  321. if (pi.size() > 256)
  322. {
  323. std::cerr << "Proof was too big, prover could have cheated." << std::endl;
  324. return false;
  325. }
  326. if (!CLIENT_IS_MALICIOUS)
  327. return pi[0].hbc == "PROOF";
  328. Scalar ownerChallenge, ownerResponse;
  329. ownerChallenge = pi[0].challengeParts[0];
  330. ownerResponse = pi[0].responseParts[0];
  331. // User should be able to prove they are who they say they are
  332. if (!schnorr_verification(generator, owner, ownerChallenge, ownerResponse))
  333. {
  334. std::cerr << "Schnorr proof failed, aborting." << std::endl;
  335. return false;
  336. }
  337. // X is the thing we're going to be checking in on throughout
  338. // to try to get our score commitment back in the end.
  339. Twistpoint X;
  340. for (size_t i = 1; i < pi.size(); i++)
  341. {
  342. Twistpoint C, g, h;
  343. C = pi[i].curvepointUniversals[0];
  344. g = commitment.mask;
  345. h = elGamalBlindGenerator;
  346. X = X + C * Scalar(1 << (i - 1));
  347. Scalar x, f, z_a, z_b;
  348. x = pi[i].challengeParts[0];
  349. f = pi[i].responseParts[0];
  350. z_a = pi[i].responseParts[1];
  351. z_b = pi[i].responseParts[2];
  352. // Taken from Fig. 1 in https://eprint.iacr.org/2014/764.pdf
  353. Twistpoint C_a, C_b;
  354. C_a = g * z_a + h * f - C * x;
  355. C_b = g * z_b - C * (x - f);
  356. std::stringstream oracleInput;
  357. oracleInput << g << h << C << C_a << C_b;
  358. if (oracle(oracleInput.str()) != x)
  359. {
  360. std::cerr << "0 or 1 proof failed at index " << i << " of " << pi.size() - 1 << ", aborting." << std::endl;
  361. return false;
  362. }
  363. }
  364. Twistpoint scoreCommitment = commitment.encryptedMessage + elGamalBlindGenerator * -threshold;
  365. return X == scoreCommitment;
  366. }
  367. /*
  368. * VALID VOTE PROOFS
  369. */
  370. std::vector<Proof> PrsonaBase::generate_vote_proof(
  371. const Proof& ownershipProof,
  372. const TwistBipoint& g,
  373. const TwistBipoint& h,
  374. const std::vector<bool>& replaces,
  375. const std::vector<TwistBipoint>& oldEncryptedVotes,
  376. const std::vector<TwistBipoint>& newEncryptedVotes,
  377. const std::vector<Scalar>& seeds,
  378. const std::vector<Scalar>& votes) const
  379. {
  380. std::vector<Proof> retval;
  381. // Base case
  382. if (!CLIENT_IS_MALICIOUS)
  383. {
  384. retval.push_back(Proof("PROOF"));
  385. return retval;
  386. }
  387. // The first need is to prove that we are the stpk we claim we are
  388. retval.push_back(ownershipProof);
  389. // Then, we iterate over all votes for the proofs that they are correct
  390. for (size_t i = 0; i < replaces.size(); i++)
  391. {
  392. std::stringstream oracleInput;
  393. oracleInput << g << h << oldEncryptedVotes[i] << newEncryptedVotes[i];
  394. Scalar m = votes[i];
  395. Scalar r = seeds[i];
  396. /* This proof structure is documented in my notes.
  397. * It's inspired by the proof in Fig. 1 at
  398. * https://eprint.iacr.org/2014/764.pdf, but adapted so that you prove
  399. * m(m-1)(m-2) = 0 instead of m(m-1) = 0.
  400. *
  401. * The rerandomization part is just a slight variation on an
  402. * ordinary Schnorr proof, so that part's less scary. */
  403. if (replaces[i]) // CASE: Make new vote
  404. {
  405. Proof currProof;
  406. Scalar x_r, z_r, a, s, t_1, t_2;
  407. x_r.set_random();
  408. z_r.set_random();
  409. a.set_random();
  410. s.set_random();
  411. t_1.set_random();
  412. t_2.set_random();
  413. TwistBipoint U = h * z_r +
  414. oldEncryptedVotes[i] * x_r -
  415. newEncryptedVotes[i] * x_r;
  416. TwistBipoint C_a = g * a + h * s;
  417. Scalar power = ((a + a) * m * m - (a + a + a) * m);
  418. TwistBipoint C_b = g * power + h * t_1;
  419. currProof.curveBipointUniversals.push_back(C_b);
  420. TwistBipoint C_c = g * (a * a * m) + h * t_2;
  421. oracleInput << U << C_a << C_b << C_c;
  422. Scalar x = oracle(oracleInput.str());
  423. Scalar x_n = x - x_r;
  424. currProof.challengeParts.push_back(x_r);
  425. currProof.challengeParts.push_back(x_n);
  426. Scalar f = m * x_n + a;
  427. Scalar z_na = r * x_n + s;
  428. Scalar z_nb = r * (f - x_n) * (x_n + x_n - f) + t_1 * x_n + t_2;
  429. currProof.responseParts.push_back(z_r);
  430. currProof.responseParts.push_back(f);
  431. currProof.responseParts.push_back(z_na);
  432. currProof.responseParts.push_back(z_nb);
  433. retval.push_back(currProof);
  434. }
  435. else // CASE: Rerandomize existing vote
  436. {
  437. Proof currProof;
  438. Scalar u, commitmentLambda_1, commitmentLambda_2, x_n, z_na, z_nb, f;
  439. u.set_random();
  440. commitmentLambda_1.set_random();
  441. commitmentLambda_2.set_random();
  442. x_n.set_random();
  443. z_na.set_random();
  444. z_nb.set_random();
  445. f.set_random();
  446. TwistBipoint U = h * u;
  447. TwistBipoint C_a = g * f +
  448. h * z_na -
  449. newEncryptedVotes[i] * x_n;
  450. TwistBipoint C_b = g * commitmentLambda_1 + h * commitmentLambda_2;
  451. currProof.curveBipointUniversals.push_back(C_b);
  452. TwistBipoint C_c = h * z_nb -
  453. newEncryptedVotes[i] * ((f - x_n) * (x_n + x_n - f)) -
  454. C_b * x_n;
  455. oracleInput << U << C_a << C_b << C_c;
  456. Scalar x = oracle(oracleInput.str());
  457. Scalar x_r = x - x_n;
  458. currProof.challengeParts.push_back(x_r);
  459. currProof.challengeParts.push_back(x_n);
  460. Scalar z_r = r * x_r + u;
  461. currProof.responseParts.push_back(z_r);
  462. currProof.responseParts.push_back(f);
  463. currProof.responseParts.push_back(z_na);
  464. currProof.responseParts.push_back(z_nb);
  465. retval.push_back(currProof);
  466. }
  467. }
  468. return retval;
  469. }
  470. bool PrsonaBase::verify_vote_proof(
  471. const TwistBipoint& g,
  472. const TwistBipoint& h,
  473. const std::vector<Proof>& pi,
  474. const std::vector<TwistBipoint>& oldEncryptedVotes,
  475. const std::vector<TwistBipoint>& newEncryptedVotes,
  476. const Twistpoint& freshGenerator,
  477. const Twistpoint& owner) const
  478. {
  479. // Reject outright if there's no proof to check
  480. if (pi.empty())
  481. {
  482. std::cerr << "Proof was empty, aborting." << std::endl;
  483. return false;
  484. }
  485. // Base case
  486. if (!CLIENT_IS_MALICIOUS)
  487. return pi[0].hbc == "PROOF";
  488. // User should be able to prove they are who they say they are
  489. if (!verify_ownership_proof(pi[0], freshGenerator, owner))
  490. {
  491. std::cerr << "Schnorr proof failed, aborting." << std::endl;
  492. return false;
  493. }
  494. /* This proof structure is documented in my notes.
  495. * It's inspired by the proof in Fig. 1 at
  496. * https://eprint.iacr.org/2014/764.pdf, but adapted so that you prove
  497. * m(m-1)(m-2) = 0 instead of m(m-1) = 0.
  498. *
  499. * The rerandomization part is just a slight variation on an
  500. * ordinary Schnorr proof, so that part's less scary. */
  501. for (size_t i = 1; i < pi.size(); i++)
  502. {
  503. size_t voteIndex = i - 1;
  504. TwistBipoint C_b;
  505. C_b = pi[i].curveBipointUniversals[0];
  506. Scalar x_r, x_n, z_r, f, z_na, z_nb;
  507. x_r = pi[i].challengeParts[0];
  508. x_n = pi[i].challengeParts[1];
  509. z_r = pi[i].responseParts[0];
  510. f = pi[i].responseParts[1];
  511. z_na = pi[i].responseParts[2];
  512. z_nb = pi[i].responseParts[3];
  513. TwistBipoint U, C_a, C_c;
  514. U = h * z_r +
  515. oldEncryptedVotes[voteIndex] * x_r -
  516. newEncryptedVotes[voteIndex] * x_r;
  517. C_a = g * f + h * z_na - newEncryptedVotes[voteIndex] * x_n;
  518. C_c = h * z_nb -
  519. newEncryptedVotes[voteIndex] * ((f - x_n) * (x_n + x_n - f)) -
  520. C_b * x_n;
  521. std::stringstream oracleInput;
  522. oracleInput << g << h << oldEncryptedVotes[voteIndex] << newEncryptedVotes[voteIndex] << U << C_a << C_b << C_c;
  523. if (oracle(oracleInput.str()) != x_r + x_n)
  524. return false;
  525. }
  526. return true;
  527. }
  528. /*
  529. * NEW USER PROOFS
  530. */
  531. std::vector<Proof> PrsonaBase::generate_proof_of_added_user(
  532. const Scalar& twistBipointSeed,
  533. const Scalar& EGCiphertextSeed,
  534. const std::vector<Scalar>& curveBipointSelfSeeds,
  535. const std::vector<Scalar>& curveBipointOtherSeeds) const
  536. {
  537. std::vector<Proof> retval;
  538. if (!SERVER_IS_MALICIOUS)
  539. {
  540. retval.push_back(Proof("PROOF"));
  541. return retval;
  542. }
  543. Proof currProof;
  544. currProof.responseParts.push_back(twistBipointSeed);
  545. retval.push_back(currProof);
  546. currProof.responseParts.clear();
  547. currProof.responseParts.push_back(EGCiphertextSeed);
  548. retval.push_back(currProof);
  549. currProof.responseParts.clear();
  550. for (size_t i = 0; i < curveBipointSelfSeeds.size(); i++)
  551. currProof.responseParts.push_back(curveBipointSelfSeeds[i]);
  552. retval.push_back(currProof);
  553. currProof.responseParts.clear();
  554. for (size_t i = 0; i < curveBipointOtherSeeds.size(); i++)
  555. currProof.responseParts.push_back(curveBipointOtherSeeds[i]);
  556. retval.push_back(currProof);
  557. return retval;
  558. }
  559. bool PrsonaBase::verify_proof_of_added_user(
  560. const std::vector<Proof>& pi,
  561. const Twistpoint& currentFreshGenerator,
  562. const Twistpoint& shortTermPublicKey,
  563. const TwistBipoint& curveG,
  564. const TwistBipoint& curveH,
  565. const CurveBipoint& twistG,
  566. const CurveBipoint& twistH,
  567. size_t selfIndex,
  568. const EGCiphertext& userEncryptedScore,
  569. const CurveBipoint& serverEncryptedScore,
  570. const std::vector<std::vector<TwistBipoint>> encryptedVoteMatrix) const
  571. {
  572. if (pi.empty())
  573. {
  574. std::cerr << "Proof empty." << std::endl;
  575. return false;
  576. }
  577. if (!SERVER_IS_MALICIOUS)
  578. return true;
  579. Scalar currSeed = pi[0].responseParts[0];
  580. if (serverEncryptedScore !=
  581. twistG * DEFAULT_TALLY + twistH * currSeed)
  582. {
  583. std::cerr << "Issue in server encrypted score." << std::endl;
  584. return false;
  585. }
  586. currSeed = pi[1].responseParts[0];
  587. if (userEncryptedScore.mask != shortTermPublicKey * currSeed)
  588. {
  589. std::cerr << "Issue in user encrypted score: mask." << std::endl;
  590. return false;
  591. }
  592. if (userEncryptedScore.encryptedMessage !=
  593. currentFreshGenerator * currSeed + elGamalBlindGenerator * DEFAULT_TALLY)
  594. {
  595. std::cerr << "Issue in user encrypted score: value." << std::endl;
  596. return false;
  597. }
  598. for (size_t i = 0; i < pi[2].responseParts.size(); i++)
  599. {
  600. TwistBipoint currVote = encryptedVoteMatrix[selfIndex][i];
  601. currSeed = pi[2].responseParts[i];
  602. if (i == selfIndex)
  603. {
  604. if (currVote !=
  605. curveG * Scalar(MAX_ALLOWED_VOTE) + curveH * currSeed)
  606. {
  607. std::cerr << "Issue in self vote." << std::endl;
  608. return false;
  609. }
  610. }
  611. else
  612. {
  613. if (currVote !=
  614. curveG * DEFAULT_VOTE + curveH * currSeed)
  615. {
  616. std::cerr << "Issue in vote by verifier for user " << i + 1 << " of " << pi[2].responseParts.size() << "." << std::endl;
  617. return false;
  618. }
  619. }
  620. }
  621. for (size_t i = 0; i < pi[3].responseParts.size(); i++)
  622. {
  623. TwistBipoint currVote = encryptedVoteMatrix[i][selfIndex];
  624. currSeed = pi[3].responseParts[i];
  625. if (i != selfIndex)
  626. {
  627. if (currVote !=
  628. curveG * DEFAULT_VOTE + curveH * currSeed)
  629. {
  630. std::cerr << "Issue in vote for verifier by user " << i + 1 << " of " << pi[3].responseParts.size() << "." << std::endl;
  631. return false;
  632. }
  633. }
  634. }
  635. return true;
  636. }
  637. /*
  638. * EPOCH PROOFS
  639. */
  640. std::vector<Proof> PrsonaBase::generate_valid_permutation_proof(
  641. const std::vector<std::vector<Scalar>>& permutations,
  642. const std::vector<std::vector<Scalar>>& seeds,
  643. const std::vector<std::vector<Twistpoint>>& commits) const
  644. {
  645. std::vector<Proof> retval;
  646. if (!SERVER_IS_MALICIOUS)
  647. {
  648. retval.push_back(Proof("PROOF"));
  649. return retval;
  650. }
  651. Twistpoint g, h;
  652. g = EL_GAMAL_GENERATOR;
  653. h = elGamalBlindGenerator;
  654. std::stringstream oracleInput;
  655. oracleInput << g << h;
  656. retval.push_back(Proof());
  657. std::vector<std::vector<Scalar>> a, s, t;
  658. for (size_t i = 0; i < commits.size(); i++)
  659. {
  660. std::vector<Scalar> currA, currS, currT;
  661. for (size_t j = 0; j < commits[i].size(); j++)
  662. {
  663. oracleInput << commits[i][j];
  664. currA.push_back(Scalar());
  665. currS.push_back(Scalar());
  666. currT.push_back(Scalar());
  667. retval.push_back(Proof());
  668. }
  669. a.push_back(currA);
  670. s.push_back(currS);
  671. t.push_back(currT);
  672. }
  673. // Taken from Fig. 1 in https://eprint.iacr.org/2014/764.pdf
  674. for (size_t i = 0; i < permutations.size(); i++)
  675. {
  676. for (size_t j = 0; j < permutations[i].size(); j++)
  677. {
  678. Twistpoint C, C_a, C_b;
  679. Scalar p, r;
  680. a[i][j].set_random();
  681. s[i][j].set_random();
  682. t[i][j].set_random();
  683. p = permutations[i][j];
  684. r = seeds[i][j];
  685. C = commits[i][j];
  686. C_a = g * a[i][j] + h * s[i][j];
  687. C_b = g * a[i][j] * p + h * t[i][j];
  688. oracleInput << C << C_a << C_b;
  689. }
  690. }
  691. Scalar x = oracle(oracleInput.str());
  692. retval[0].challengeParts.push_back(x);
  693. for (size_t i = 0; i < permutations.size(); i++)
  694. {
  695. for (size_t j = 0; j < permutations[i].size(); j++)
  696. {
  697. size_t piIndex = i * permutations.size() + j + 1;
  698. Scalar f, z_a, z_b, p, r;
  699. p = permutations[i][j];
  700. r = seeds[i][j];
  701. f = p * x + a[i][j];
  702. z_a = r * x + s[i][j];
  703. z_b = r * (x - f) + t[i][j];
  704. retval[piIndex].responseParts.push_back(f);
  705. retval[piIndex].responseParts.push_back(z_a);
  706. retval[piIndex].responseParts.push_back(z_b);
  707. }
  708. }
  709. return retval;
  710. }
  711. bool PrsonaBase::verify_valid_permutation_proof(
  712. const std::vector<Proof>& pi,
  713. const std::vector<std::vector<Twistpoint>>& commits) const
  714. {
  715. // Reject outright if there's no proof to check
  716. if (pi.empty())
  717. {
  718. std::cerr << "Proof was empty, aborting." << std::endl;
  719. return false;
  720. }
  721. if (!SERVER_IS_MALICIOUS)
  722. return true;
  723. Twistpoint g, h;
  724. g = EL_GAMAL_GENERATOR;
  725. h = elGamalBlindGenerator;
  726. std::stringstream oracleInput;
  727. oracleInput << g << h;
  728. for (size_t i = 0; i < commits.size(); i++)
  729. for (size_t j = 0; j < commits[i].size(); j++)
  730. oracleInput << commits[i][j];
  731. Scalar x = pi[0].challengeParts[0];
  732. for (size_t i = 0; i < commits.size(); i++)
  733. {
  734. for (size_t j = 0; j < commits[i].size(); j++)
  735. {
  736. size_t piIndex = i * commits.size() + j + 1;
  737. Twistpoint C, C_a, C_b;
  738. C = commits[i][j];
  739. Scalar f, z_a, z_b;
  740. f = pi[piIndex].responseParts[0];
  741. z_a = pi[piIndex].responseParts[1];
  742. z_b = pi[piIndex].responseParts[2];
  743. // Taken from Fig. 1 in https://eprint.iacr.org/2014/764.pdf
  744. C_a = g * f + h * z_a - C * x;
  745. C_b = h * z_b - C * (x - f);
  746. oracleInput << C << C_a << C_b;
  747. }
  748. }
  749. if (oracle(oracleInput.str()) != x)
  750. {
  751. std::cerr << "0 or 1 proof failed, aborting." << std::endl;
  752. return false;
  753. }
  754. for (size_t i = 0; i < commits.size(); i++)
  755. {
  756. Twistpoint sum = commits[i][0];
  757. for (size_t j = 1; j < commits[i].size(); j++)
  758. sum = sum + commits[i][j];
  759. if (sum != g)
  760. {
  761. std::cerr << "Commits did not sum to g, aborting." << std::endl;
  762. return false;
  763. }
  764. }
  765. return true;
  766. }
  767. template <typename T>
  768. std::vector<Proof> PrsonaBase::generate_proof_of_reordering(
  769. const std::vector<std::vector<Scalar>>& permutations,
  770. const std::vector<std::vector<Scalar>>& permutationSeeds,
  771. const std::vector<std::vector<Scalar>>& productSeeds,
  772. const std::vector<T>& oldValues,
  773. const std::vector<std::vector<Twistpoint>>& permutationCommits,
  774. const std::vector<std::vector<T>>& productCommits,
  775. const T& otherG,
  776. const T& otherH) const
  777. {
  778. if (LAMBDA > 0)
  779. return generate_batched_proof_of_reordering<T>(permutations, permutationSeeds, productSeeds, oldValues, permutationCommits, productCommits, otherG, otherH);
  780. else
  781. return generate_unbatched_proof_of_reordering<T>(permutations, permutationSeeds, productSeeds, oldValues, permutationCommits, productCommits, otherG, otherH);
  782. }
  783. template <typename T>
  784. bool PrsonaBase::verify_proof_of_reordering(
  785. const std::vector<Proof>& pi,
  786. const std::vector<T>& oldValues,
  787. const std::vector<std::vector<Twistpoint>>& permutationCommits,
  788. const std::vector<std::vector<T>>& productCommits,
  789. const T& otherG,
  790. const T& otherH) const
  791. {
  792. if (LAMBDA > 0)
  793. return verify_batched_proof_of_reordering<T>(pi, oldValues, permutationCommits, productCommits, otherG, otherH);
  794. else
  795. return verify_unbatched_proof_of_reordering<T>(pi, oldValues, permutationCommits, productCommits, otherG, otherH);
  796. }
  797. template <typename T>
  798. std::vector<Proof> PrsonaBase::generate_unbatched_proof_of_reordering(
  799. const std::vector<std::vector<Scalar>>& permutations,
  800. const std::vector<std::vector<Scalar>>& permutationSeeds,
  801. const std::vector<std::vector<Scalar>>& productSeeds,
  802. const std::vector<T>& oldValues,
  803. const std::vector<std::vector<Twistpoint>>& permutationCommits,
  804. const std::vector<std::vector<T>>& productCommits,
  805. const T& otherG,
  806. const T& otherH) const
  807. {
  808. std::vector<Proof> retval;
  809. if (!SERVER_IS_MALICIOUS)
  810. {
  811. retval.push_back(Proof("PROOF"));
  812. return retval;
  813. }
  814. Proof first;
  815. retval.push_back(first);
  816. Twistpoint g = EL_GAMAL_GENERATOR;
  817. Twistpoint h = elGamalBlindGenerator;
  818. std::stringstream oracleInput;
  819. oracleInput << g << h << otherG << otherH;
  820. for (size_t i = 0; i < oldValues.size(); i++)
  821. oracleInput << oldValues[i];
  822. for (size_t i = 0; i < permutationCommits.size(); i++)
  823. for (size_t j = 0; j < permutationCommits[i].size(); j++)
  824. oracleInput << permutationCommits[i][j];
  825. for (size_t i = 0; i < productCommits.size(); i++)
  826. for (size_t j = 0; j < productCommits[i].size(); j++)
  827. oracleInput << productCommits[i][j];
  828. std::vector<std::vector<Scalar>> a;
  829. std::vector<std::vector<Scalar>> t1;
  830. std::vector<std::vector<Scalar>> t2;
  831. for (size_t i = 0; i < permutationCommits.size(); i++)
  832. {
  833. std::vector<Scalar> curraRow;
  834. std::vector<Scalar> currt1Row;
  835. std::vector<Scalar> currt2Row;
  836. for (size_t j = 0; j < permutationCommits[i].size(); j++)
  837. {
  838. Proof currProof;
  839. Scalar curra;
  840. Scalar currt1;
  841. Scalar currt2;
  842. Twistpoint U1;
  843. T U2;
  844. curra.set_random();
  845. currt1.set_random();
  846. currt2.set_random();
  847. U1 = g * curra + h * currt1;
  848. U2 = oldValues[j] * curra + otherH * currt2;
  849. oracleInput << U1 << U2;
  850. curraRow.push_back(curra);
  851. currt1Row.push_back(currt1);
  852. currt2Row.push_back(currt2);
  853. retval.push_back(currProof);
  854. }
  855. a.push_back(curraRow);
  856. t1.push_back(currt1Row);
  857. t2.push_back(currt2Row);
  858. }
  859. Scalar x = oracle(oracleInput.str());
  860. retval[0].challengeParts.push_back(x);
  861. for (size_t i = 0; i < permutationCommits.size(); i++)
  862. {
  863. for (size_t j = 0; j < permutationCommits[i].size(); j++)
  864. {
  865. size_t piIndex = i * permutationCommits.size() + j + 1;
  866. Scalar f = permutations[j][i] * x + a[i][j];
  867. Scalar z1 = permutationSeeds[j][i] * x + t1[i][j];
  868. Scalar z2 = productSeeds[i][j] * x + t2[i][j];
  869. retval[piIndex].responseParts.push_back(f);
  870. retval[piIndex].responseParts.push_back(z1);
  871. retval[piIndex].responseParts.push_back(z2);
  872. }
  873. }
  874. return retval;
  875. }
  876. template <typename T>
  877. bool PrsonaBase::verify_unbatched_proof_of_reordering(
  878. const std::vector<Proof>& pi,
  879. const std::vector<T>& oldValues,
  880. const std::vector<std::vector<Twistpoint>>& permutationCommits,
  881. const std::vector<std::vector<T>>& productCommits,
  882. const T& otherG,
  883. const T& otherH) const
  884. {
  885. if (pi.empty())
  886. return false;
  887. if (!SERVER_IS_MALICIOUS)
  888. return true;
  889. Twistpoint g = EL_GAMAL_GENERATOR;
  890. Twistpoint h = elGamalBlindGenerator;
  891. std::stringstream oracleInput;
  892. oracleInput << g << h << otherG << otherH;
  893. for (size_t i = 0; i < oldValues.size(); i++)
  894. oracleInput << oldValues[i];
  895. for (size_t i = 0; i < permutationCommits.size(); i++)
  896. for (size_t j = 0; j < permutationCommits[i].size(); j++)
  897. oracleInput << permutationCommits[i][j];
  898. for (size_t i = 0; i < productCommits.size(); i++)
  899. for (size_t j = 0; j < productCommits[i].size(); j++)
  900. oracleInput << productCommits[i][j];
  901. Scalar x = pi[0].challengeParts[0];
  902. for (size_t i = 0; i < permutationCommits.size(); i++)
  903. {
  904. for (size_t j = 0; j < permutationCommits[i].size(); j++)
  905. {
  906. size_t piIndex = i * permutationCommits.size() + j + 1;
  907. Twistpoint U1;
  908. T U2;
  909. Scalar f = pi[piIndex].responseParts[0];
  910. Scalar z1 = pi[piIndex].responseParts[1];
  911. Scalar z2 = pi[piIndex].responseParts[2];
  912. U1 = g * f +
  913. h * z1 -
  914. permutationCommits[j][i] * x;
  915. U2 = oldValues[j] * f +
  916. otherH * z2 -
  917. productCommits[i][j] * x;
  918. oracleInput << U1 << U2;
  919. }
  920. }
  921. if (x != oracle(oracleInput.str()))
  922. {
  923. std::cerr << "Reordered things not generated by permutation matrix." << std::endl;
  924. return false;
  925. }
  926. return true;
  927. }
  928. template <typename T>
  929. std::vector<Proof> PrsonaBase::generate_batched_proof_of_reordering(
  930. const std::vector<std::vector<Scalar>>& permutations,
  931. const std::vector<std::vector<Scalar>>& permutationSeeds,
  932. const std::vector<std::vector<Scalar>>& productSeeds,
  933. const std::vector<T>& oldValues,
  934. const std::vector<std::vector<Twistpoint>>& permutationCommits,
  935. const std::vector<std::vector<T>>& productCommits,
  936. const T& otherG,
  937. const T& otherH) const
  938. {
  939. std::vector<Proof> retval;
  940. if (!SERVER_IS_MALICIOUS)
  941. {
  942. retval.push_back(Proof("PROOF"));
  943. return retval;
  944. }
  945. Proof first;
  946. retval.push_back(first);
  947. Twistpoint g = EL_GAMAL_GENERATOR;
  948. Twistpoint h = elGamalBlindGenerator;
  949. std::stringstream oracleInput;
  950. oracleInput << g << h << otherG << otherH;
  951. for (size_t i = 0; i < oldValues.size(); i++)
  952. oracleInput << oldValues[i];
  953. for (size_t i = 0; i < permutationCommits.size(); i++)
  954. for (size_t j = 0; j < permutationCommits[i].size(); j++)
  955. oracleInput << permutationCommits[i][j];
  956. for (size_t i = 0; i < productCommits.size(); i++)
  957. for (size_t j = 0; j < productCommits[i].size(); j++)
  958. oracleInput << productCommits[i][j];
  959. std::vector<Scalar> a;
  960. std::vector<Scalar> t1;
  961. std::vector<Scalar> t2;
  962. for (size_t i = 0; i < permutationCommits.size(); i++)
  963. {
  964. Proof currProof;
  965. Scalar curra;
  966. Scalar currt1;
  967. Scalar currt2;
  968. Twistpoint U1;
  969. T U2;
  970. curra.set_random();
  971. currt1.set_random();
  972. currt2.set_random();
  973. U1 = g * curra + h * currt1;
  974. U2 = oldValues[i] * curra + otherH * currt2;
  975. oracleInput << U1 << U2;
  976. a.push_back(curra);
  977. t1.push_back(currt1);
  978. t2.push_back(currt2);
  979. retval.push_back(currProof);
  980. }
  981. Scalar x = oracle(oracleInput.str());
  982. retval[0].challengeParts.push_back(x);
  983. for (size_t i = 0; i < permutationCommits.size(); i++)
  984. {
  985. size_t piIndex = i + 1;
  986. Scalar f = a[i];
  987. Scalar z1 = t1[i];
  988. Scalar z2 = t2[i];
  989. for (size_t j = 0; j < permutationCommits[i].size(); j++)
  990. {
  991. std::stringstream currOracle;
  992. currOracle << permutationCommits[i][j] << productCommits[j][i];
  993. Scalar currx = oracle(currOracle.str(), LAMBDA);
  994. f = f + permutations[i][j] * currx;
  995. z1 = z1 + permutationSeeds[i][j] * currx;
  996. z2 = z2 + productSeeds[j][i] * currx;
  997. }
  998. retval[piIndex].responseParts.push_back(f);
  999. retval[piIndex].responseParts.push_back(z1);
  1000. retval[piIndex].responseParts.push_back(z2);
  1001. }
  1002. return retval;
  1003. }
  1004. template <typename T>
  1005. bool PrsonaBase::verify_batched_proof_of_reordering(
  1006. const std::vector<Proof>& pi,
  1007. const std::vector<T>& oldValues,
  1008. const std::vector<std::vector<Twistpoint>>& permutationCommits,
  1009. const std::vector<std::vector<T>>& productCommits,
  1010. const T& otherG,
  1011. const T& otherH) const
  1012. {
  1013. if (pi.empty())
  1014. return false;
  1015. if (!SERVER_IS_MALICIOUS)
  1016. return true;
  1017. Twistpoint g = EL_GAMAL_GENERATOR;
  1018. Twistpoint h = elGamalBlindGenerator;
  1019. std::stringstream oracleInput;
  1020. oracleInput << g << h << otherG << otherH;
  1021. for (size_t i = 0; i < oldValues.size(); i++)
  1022. oracleInput << oldValues[i];
  1023. for (size_t i = 0; i < permutationCommits.size(); i++)
  1024. for (size_t j = 0; j < permutationCommits[i].size(); j++)
  1025. oracleInput << permutationCommits[i][j];
  1026. for (size_t i = 0; i < productCommits.size(); i++)
  1027. for (size_t j = 0; j < productCommits[i].size(); j++)
  1028. oracleInput << productCommits[i][j];
  1029. Scalar x = pi[0].challengeParts[0];
  1030. for (size_t i = 0; i < permutationCommits.size(); i++)
  1031. {
  1032. size_t piIndex = i + 1;
  1033. Scalar f = pi[piIndex].responseParts[0];
  1034. Scalar z1 = pi[piIndex].responseParts[1];
  1035. Scalar z2 = pi[piIndex].responseParts[2];
  1036. Twistpoint U1 = g * f + h * z1;
  1037. T U2 = oldValues[i] * f + otherH * z2;
  1038. for (size_t j = 0; j < permutationCommits[i].size(); j++)
  1039. {
  1040. std::stringstream currOracle;
  1041. currOracle << permutationCommits[i][j] << productCommits[j][i];
  1042. Scalar currx = oracle(currOracle.str(), LAMBDA);
  1043. U1 = U1 - permutationCommits[i][j] * currx;
  1044. U2 = U2 - productCommits[j][i] * currx;
  1045. }
  1046. oracleInput << U1 << U2;
  1047. }
  1048. if (x != oracle(oracleInput.str()))
  1049. {
  1050. std::cerr << "Reordered things not generated by permutation matrix." << std::endl;
  1051. return false;
  1052. }
  1053. return true;
  1054. }
  1055. std::vector<Proof> PrsonaBase::generate_proof_of_reordering_plus_power(
  1056. const std::vector<std::vector<Scalar>>& permutations,
  1057. const Scalar& power,
  1058. const std::vector<std::vector<Scalar>>& permutationSeeds,
  1059. const std::vector<std::vector<Scalar>>& productSeeds,
  1060. const std::vector<Twistpoint>& oldValues,
  1061. const std::vector<std::vector<Twistpoint>>& permutationCommits,
  1062. const std::vector<std::vector<Twistpoint>>& productCommits,
  1063. const std::vector<std::vector<Twistpoint>>& seedCommits) const
  1064. {
  1065. if (LAMBDA > 0)
  1066. return generate_batched_proof_of_reordering_plus_power(permutations, power, permutationSeeds, productSeeds, oldValues, permutationCommits, productCommits, seedCommits);
  1067. else
  1068. return generate_unbatched_proof_of_reordering_plus_power(permutations, power, permutationSeeds, productSeeds, oldValues, permutationCommits, productCommits, seedCommits);
  1069. }
  1070. bool PrsonaBase::verify_proof_of_reordering_plus_power(
  1071. const std::vector<Proof>& pi,
  1072. const std::vector<Twistpoint>& oldValues,
  1073. const std::vector<std::vector<Twistpoint>>& permutationCommits,
  1074. const std::vector<std::vector<Twistpoint>>& productCommits,
  1075. const std::vector<std::vector<Twistpoint>>& seedCommits) const
  1076. {
  1077. if (LAMBDA > 0)
  1078. return verify_batched_proof_of_reordering_plus_power(pi, oldValues, permutationCommits, productCommits, seedCommits);
  1079. else
  1080. return verify_unbatched_proof_of_reordering_plus_power(pi, oldValues, permutationCommits, productCommits, seedCommits);
  1081. }
  1082. std::vector<Proof> PrsonaBase::generate_unbatched_proof_of_reordering_plus_power(
  1083. const std::vector<std::vector<Scalar>>& permutations,
  1084. const Scalar& power,
  1085. const std::vector<std::vector<Scalar>>& permutationSeeds,
  1086. const std::vector<std::vector<Scalar>>& productSeeds,
  1087. const std::vector<Twistpoint>& oldValues,
  1088. const std::vector<std::vector<Twistpoint>>& permutationCommits,
  1089. const std::vector<std::vector<Twistpoint>>& productCommits,
  1090. const std::vector<std::vector<Twistpoint>>& seedCommits) const
  1091. {
  1092. std::vector<Proof> retval;
  1093. if (!SERVER_IS_MALICIOUS)
  1094. {
  1095. retval.push_back(Proof("PROOF"));
  1096. return retval;
  1097. }
  1098. Proof first;
  1099. retval.push_back(first);
  1100. Twistpoint g = EL_GAMAL_GENERATOR;
  1101. Twistpoint h = elGamalBlindGenerator;
  1102. std::stringstream oracleInput;
  1103. oracleInput << g << h;
  1104. for (size_t i = 0; i < oldValues.size(); i++)
  1105. oracleInput << oldValues[i];
  1106. for (size_t i = 0; i < permutationCommits.size(); i++)
  1107. for (size_t j = 0; j < permutationCommits[i].size(); j++)
  1108. oracleInput << permutationCommits[i][j];
  1109. for (size_t i = 0; i < productCommits.size(); i++)
  1110. for (size_t j = 0; j < productCommits[i].size(); j++)
  1111. oracleInput << productCommits[i][j];
  1112. for (size_t i = 0; i < seedCommits.size(); i++)
  1113. for (size_t j = 0; j < seedCommits[i].size(); j++)
  1114. oracleInput << seedCommits[i][j];
  1115. Scalar b1;
  1116. b1.set_random();
  1117. std::vector<std::vector<Scalar>> b2;
  1118. std::vector<std::vector<Scalar>> t1;
  1119. std::vector<std::vector<Scalar>> t2;
  1120. for (size_t i = 0; i < permutationCommits.size(); i++)
  1121. {
  1122. std::vector<Scalar> currb2Row;
  1123. std::vector<Scalar> currt1Row;
  1124. std::vector<Scalar> currt2Row;
  1125. for (size_t j = 0; j < permutationCommits[i].size(); j++)
  1126. {
  1127. Proof currProof;
  1128. Scalar currb2;
  1129. Scalar currt1;
  1130. Scalar currt2;
  1131. Twistpoint U1, U2, U3, U4;
  1132. currb2.set_random();
  1133. currt1.set_random();
  1134. currt2.set_random();
  1135. U1 = g * currb2 + h * currt1;
  1136. U2 = oldValues[j] *
  1137. (b1 * permutations[j][i] + currb2 * power);
  1138. U3 = oldValues[j] * b1 * currb2 + h * currt2;
  1139. U4 = g * currt2;
  1140. currProof.curvepointUniversals.push_back(U2);
  1141. oracleInput << U1 << U2 << U3 << U4;
  1142. currb2Row.push_back(currb2);
  1143. currt1Row.push_back(currt1);
  1144. currt2Row.push_back(currt2);
  1145. retval.push_back(currProof);
  1146. }
  1147. b2.push_back(currb2Row);
  1148. t1.push_back(currt1Row);
  1149. t2.push_back(currt2Row);
  1150. }
  1151. Scalar x = oracle(oracleInput.str());
  1152. retval[0].challengeParts.push_back(x);
  1153. Scalar f1 = power * x + b1;
  1154. retval[0].responseParts.push_back(f1);
  1155. for (size_t i = 0; i < permutationCommits.size(); i++)
  1156. {
  1157. for (size_t j = 0; j < permutationCommits[i].size(); j++)
  1158. {
  1159. size_t piIndex = i * permutationCommits.size() + j + 1;
  1160. Scalar f2 = permutations[j][i] * x + b2[i][j];
  1161. Scalar z1 = permutationSeeds[j][i] * x + t1[i][j];
  1162. Scalar z2 = productSeeds[i][j] * x * x + t2[i][j];
  1163. retval[piIndex].responseParts.push_back(f2);
  1164. retval[piIndex].responseParts.push_back(z1);
  1165. retval[piIndex].responseParts.push_back(z2);
  1166. }
  1167. }
  1168. return retval;
  1169. }
  1170. bool PrsonaBase::verify_unbatched_proof_of_reordering_plus_power(
  1171. const std::vector<Proof>& pi,
  1172. const std::vector<Twistpoint>& oldValues,
  1173. const std::vector<std::vector<Twistpoint>>& permutationCommits,
  1174. const std::vector<std::vector<Twistpoint>>& productCommits,
  1175. const std::vector<std::vector<Twistpoint>>& seedCommits) const
  1176. {
  1177. if (pi.empty())
  1178. return false;
  1179. if (!SERVER_IS_MALICIOUS)
  1180. return true;
  1181. Twistpoint g = EL_GAMAL_GENERATOR;
  1182. Twistpoint h = elGamalBlindGenerator;
  1183. std::stringstream oracleInput;
  1184. oracleInput << g << h;
  1185. for (size_t i = 0; i < oldValues.size(); i++)
  1186. oracleInput << oldValues[i];
  1187. for (size_t i = 0; i < permutationCommits.size(); i++)
  1188. for (size_t j = 0; j < permutationCommits[i].size(); j++)
  1189. oracleInput << permutationCommits[i][j];
  1190. for (size_t i = 0; i < productCommits.size(); i++)
  1191. for (size_t j = 0; j < productCommits[i].size(); j++)
  1192. oracleInput << productCommits[i][j];
  1193. for (size_t i = 0; i < seedCommits.size(); i++)
  1194. for (size_t j = 0; j < seedCommits[i].size(); j++)
  1195. oracleInput << seedCommits[i][j];
  1196. Scalar x = pi[0].challengeParts[0];
  1197. Scalar f1 = pi[0].responseParts[0];
  1198. for (size_t i = 0; i < permutationCommits.size(); i++)
  1199. {
  1200. for (size_t j = 0; j < permutationCommits[i].size(); j++)
  1201. {
  1202. size_t piIndex = i * permutationCommits.size() + j + 1;
  1203. Twistpoint U1, U2, U3, U4;
  1204. U2 = pi[piIndex].curvepointUniversals[0];
  1205. Scalar f2 = pi[piIndex].responseParts[0];
  1206. Scalar z1 = pi[piIndex].responseParts[1];
  1207. Scalar z2 = pi[piIndex].responseParts[2];
  1208. U1 = g * f2 + h * z1 - permutationCommits[j][i] * x;
  1209. U3 = oldValues[j] * f1 * f2 +
  1210. h * z2 -
  1211. productCommits[i][j] * x * x -
  1212. U2 * x;
  1213. U4 = g * z2 - seedCommits[i][j] * x * x;
  1214. oracleInput << U1 << U2 << U3 << U4;
  1215. }
  1216. }
  1217. if (x != oracle(oracleInput.str()))
  1218. {
  1219. std::cerr << "Reordered + power things not generated by permutation matrix." << std::endl;
  1220. return false;
  1221. }
  1222. for (size_t i = 0; i < seedCommits.size(); i++)
  1223. {
  1224. Twistpoint sum = seedCommits[i][0];
  1225. for (size_t j = 1; j < seedCommits[i].size(); j++)
  1226. sum = sum + seedCommits[i][j];
  1227. if (sum != Twistpoint())
  1228. {
  1229. std::cerr << "seed commits did not sum to 0, aborting." << std::endl;
  1230. return false;
  1231. }
  1232. }
  1233. return true;
  1234. }
  1235. std::vector<Proof> PrsonaBase::generate_batched_proof_of_reordering_plus_power(
  1236. const std::vector<std::vector<Scalar>>& permutations,
  1237. const Scalar& power,
  1238. const std::vector<std::vector<Scalar>>& permutationSeeds,
  1239. const std::vector<std::vector<Scalar>>& productSeeds,
  1240. const std::vector<Twistpoint>& oldValues,
  1241. const std::vector<std::vector<Twistpoint>>& permutationCommits,
  1242. const std::vector<std::vector<Twistpoint>>& productCommits,
  1243. const std::vector<std::vector<Twistpoint>>& seedCommits) const
  1244. {
  1245. std::vector<Proof> retval;
  1246. if (!SERVER_IS_MALICIOUS)
  1247. {
  1248. retval.push_back(Proof("PROOF"));
  1249. return retval;
  1250. }
  1251. Proof first;
  1252. retval.push_back(first);
  1253. Twistpoint g = EL_GAMAL_GENERATOR;
  1254. Twistpoint h = elGamalBlindGenerator;
  1255. std::stringstream oracleInput;
  1256. oracleInput << g << h;
  1257. for (size_t i = 0; i < oldValues.size(); i++)
  1258. oracleInput << oldValues[i];
  1259. for (size_t i = 0; i < permutationCommits.size(); i++)
  1260. for (size_t j = 0; j < permutationCommits[i].size(); j++)
  1261. oracleInput << permutationCommits[i][j];
  1262. for (size_t i = 0; i < productCommits.size(); i++)
  1263. for (size_t j = 0; j < productCommits[i].size(); j++)
  1264. oracleInput << productCommits[i][j];
  1265. for (size_t i = 0; i < seedCommits.size(); i++)
  1266. for (size_t j = 0; j < seedCommits[i].size(); j++)
  1267. oracleInput << seedCommits[i][j];
  1268. std::vector<Scalar> b1;
  1269. std::vector<Scalar> b2;
  1270. std::vector<std::vector<Scalar>> b3;
  1271. std::vector<Scalar> t1;
  1272. std::vector<Scalar> t2;
  1273. std::vector<Scalar> t3;
  1274. for (size_t i = 0; i < permutationCommits.size(); i++)
  1275. {
  1276. Proof currProof;
  1277. Scalar currb1;
  1278. Scalar currb2;
  1279. std::vector<Scalar> currb3Row;
  1280. Scalar currt1;
  1281. Scalar currt2;
  1282. Scalar currt3;
  1283. Twistpoint U1, U3, U4;
  1284. std::vector<Twistpoint> U2;
  1285. currb1.set_random();
  1286. currb2.set_random();
  1287. currt1.set_random();
  1288. currt2.set_random();
  1289. currt3.set_random();
  1290. U1 = g * currb2 + h * currt1;
  1291. U3 = oldValues[i] * (currb1 * currb2 + currt3) + h * currt2;
  1292. U4 = g * currt2;
  1293. oracleInput << U1;
  1294. for (size_t j = 0; j < permutationCommits[i].size(); j++)
  1295. {
  1296. Twistpoint U2;
  1297. Scalar currb3;
  1298. currb3.set_random();
  1299. Scalar U2mult = (currb1 * permutations[i][j] + currb2 * power + currb3);
  1300. for (size_t k = 0; k < permutationCommits[i].size(); k++)
  1301. {
  1302. if (k == j)
  1303. continue;
  1304. std::stringstream currOracle;
  1305. currOracle << permutationCommits[i][k] << productCommits[k][i] << seedCommits[k][i];
  1306. Scalar currx = oracle(currOracle.str(), LAMBDA);
  1307. U2mult = U2mult + power * permutations[i][j] * currx;
  1308. }
  1309. U2 = oldValues[i] * U2mult;
  1310. currProof.curvepointUniversals.push_back(U2);
  1311. oracleInput << U2;
  1312. currb3Row.push_back(currb3);
  1313. }
  1314. oracleInput << U3 << U4;
  1315. b1.push_back(currb1);
  1316. b2.push_back(currb2);
  1317. b3.push_back(currb3Row);
  1318. t1.push_back(currt1);
  1319. t2.push_back(currt2);
  1320. t3.push_back(currt3);
  1321. retval.push_back(currProof);
  1322. }
  1323. Scalar x = oracle(oracleInput.str());
  1324. retval[0].challengeParts.push_back(x);
  1325. for (size_t i = 0; i < permutationCommits.size(); i++)
  1326. {
  1327. size_t piIndex = i + 1;
  1328. Scalar f1 = b1[i];
  1329. Scalar f2 = b2[i];
  1330. Scalar z1 = t1[i];
  1331. Scalar z2 = t2[i];
  1332. Scalar z3 = t3[i];
  1333. for (size_t j = 0; j < permutationCommits[i].size(); j++)
  1334. {
  1335. std::stringstream currOracle;
  1336. currOracle << permutationCommits[i][j] << productCommits[j][i] << seedCommits[j][i];
  1337. Scalar currx = oracle(currOracle.str(), LAMBDA);
  1338. f1 = f1 + power * currx;
  1339. f2 = f2 + permutations[i][j] * currx;
  1340. z1 = z1 + permutationSeeds[i][j] * currx;
  1341. z2 = z2 + productSeeds[j][i] * currx * currx;
  1342. z3 = z3 + b3[i][j] * currx;
  1343. }
  1344. retval[piIndex].responseParts.push_back(f1);
  1345. retval[piIndex].responseParts.push_back(f2);
  1346. retval[piIndex].responseParts.push_back(z1);
  1347. retval[piIndex].responseParts.push_back(z2);
  1348. retval[piIndex].responseParts.push_back(z3);
  1349. }
  1350. return retval;
  1351. }
  1352. bool PrsonaBase::verify_batched_proof_of_reordering_plus_power(
  1353. const std::vector<Proof>& pi,
  1354. const std::vector<Twistpoint>& oldValues,
  1355. const std::vector<std::vector<Twistpoint>>& permutationCommits,
  1356. const std::vector<std::vector<Twistpoint>>& productCommits,
  1357. const std::vector<std::vector<Twistpoint>>& seedCommits) const
  1358. {
  1359. if (pi.empty())
  1360. return false;
  1361. if (!SERVER_IS_MALICIOUS)
  1362. return true;
  1363. Twistpoint g = EL_GAMAL_GENERATOR;
  1364. Twistpoint h = elGamalBlindGenerator;
  1365. std::stringstream oracleInput;
  1366. oracleInput << g << h;
  1367. for (size_t i = 0; i < oldValues.size(); i++)
  1368. oracleInput << oldValues[i];
  1369. for (size_t i = 0; i < permutationCommits.size(); i++)
  1370. for (size_t j = 0; j < permutationCommits[i].size(); j++)
  1371. oracleInput << permutationCommits[i][j];
  1372. for (size_t i = 0; i < productCommits.size(); i++)
  1373. for (size_t j = 0; j < productCommits[i].size(); j++)
  1374. oracleInput << productCommits[i][j];
  1375. for (size_t i = 0; i < seedCommits.size(); i++)
  1376. for (size_t j = 0; j < seedCommits[i].size(); j++)
  1377. oracleInput << seedCommits[i][j];
  1378. Scalar x = pi[0].challengeParts[0];
  1379. for (size_t i = 0; i < permutationCommits.size(); i++)
  1380. {
  1381. size_t piIndex = i + 1;
  1382. Scalar f1 = pi[piIndex].responseParts[0];
  1383. Scalar f2 = pi[piIndex].responseParts[1];
  1384. Scalar z1 = pi[piIndex].responseParts[2];
  1385. Scalar z2 = pi[piIndex].responseParts[3];
  1386. Scalar z3 = pi[piIndex].responseParts[4];
  1387. Twistpoint U1 = g * f2 + h * z1;
  1388. std::vector<Twistpoint> U2 = pi[piIndex].curvepointUniversals;
  1389. Twistpoint U3 = oldValues[i] * (f1 * f2 + z3) + h * z2;
  1390. Twistpoint U4 = g * z2;
  1391. for (size_t j = 0; j < permutationCommits[i].size(); j++)
  1392. {
  1393. std::stringstream currOracle;
  1394. currOracle << permutationCommits[i][j] << productCommits[j][i] << seedCommits[j][i];
  1395. Scalar currx = oracle(currOracle.str(), LAMBDA);
  1396. U1 = U1 - permutationCommits[i][j] * currx;
  1397. U3 = U3 -
  1398. productCommits[j][i] * currx * currx -
  1399. U2[j] * currx;
  1400. U4 = U4 - seedCommits[j][i] * currx * currx;
  1401. }
  1402. oracleInput << U1;
  1403. for (size_t j = 0; j < permutationCommits[i].size(); j++)
  1404. oracleInput << U2[j];
  1405. oracleInput << U3 << U4;
  1406. }
  1407. if (x != oracle(oracleInput.str()))
  1408. {
  1409. std::cerr << "Reordered + power things not generated by permutation matrix." << std::endl;
  1410. return false;
  1411. }
  1412. for (size_t i = 0; i < seedCommits.size(); i++)
  1413. {
  1414. Twistpoint sum = seedCommits[i][0];
  1415. for (size_t j = 1; j < seedCommits[i].size(); j++)
  1416. sum = sum + seedCommits[i][j];
  1417. if (sum != Twistpoint())
  1418. {
  1419. std::cerr << "seed commits did not sum to 0, aborting." << std::endl;
  1420. return false;
  1421. }
  1422. }
  1423. return true;
  1424. }
  1425. std::vector<Proof> PrsonaBase::generate_user_tally_proofs(
  1426. const std::vector<std::vector<Scalar>>& permutations,
  1427. const Scalar& power,
  1428. const Twistpoint& nextGenerator,
  1429. const std::vector<std::vector<Scalar>>& permutationSeeds,
  1430. const std::vector<std::vector<Scalar>>& userTallySeeds,
  1431. const std::vector<Twistpoint>& currPseudonyms,
  1432. const std::vector<Twistpoint>& userTallyMasks,
  1433. const std::vector<Twistpoint>& userTallyMessages,
  1434. const std::vector<std::vector<Twistpoint>>& permutationCommits,
  1435. const std::vector<std::vector<Twistpoint>>& userTallyMaskCommits,
  1436. const std::vector<std::vector<Twistpoint>>& userTallyMessageCommits,
  1437. const std::vector<std::vector<Twistpoint>>& userTallySeedCommits) const
  1438. {
  1439. if (LAMBDA > 0)
  1440. return generate_batched_user_tally_proofs(permutations, power, nextGenerator, permutationSeeds, userTallySeeds, currPseudonyms, userTallyMasks, userTallyMessages, permutationCommits, userTallyMaskCommits, userTallyMessageCommits, userTallySeedCommits);
  1441. else
  1442. return generate_unbatched_user_tally_proofs(permutations, power, nextGenerator, permutationSeeds, userTallySeeds, currPseudonyms, userTallyMasks, userTallyMessages, permutationCommits, userTallyMaskCommits, userTallyMessageCommits, userTallySeedCommits);
  1443. }
  1444. bool PrsonaBase::verify_user_tally_proofs(
  1445. const std::vector<Proof>& pi,
  1446. const Twistpoint& nextGenerator,
  1447. const std::vector<Twistpoint>& currPseudonyms,
  1448. const std::vector<Twistpoint>& userTallyMasks,
  1449. const std::vector<Twistpoint>& userTallyMessages,
  1450. const std::vector<std::vector<Twistpoint>>& permutationCommits,
  1451. const std::vector<std::vector<Twistpoint>>& userTallyMaskCommits,
  1452. const std::vector<std::vector<Twistpoint>>& userTallyMessageCommits,
  1453. const std::vector<std::vector<Twistpoint>>& userTallySeedCommits) const
  1454. {
  1455. if (LAMBDA > 0)
  1456. return verify_batched_user_tally_proofs(pi, nextGenerator, currPseudonyms, userTallyMasks, userTallyMessages, permutationCommits, userTallyMaskCommits, userTallyMessageCommits, userTallySeedCommits);
  1457. else
  1458. return verify_unbatched_user_tally_proofs(pi, nextGenerator, currPseudonyms, userTallyMasks, userTallyMessages, permutationCommits, userTallyMaskCommits, userTallyMessageCommits, userTallySeedCommits);
  1459. }
  1460. std::vector<Proof> PrsonaBase::generate_unbatched_user_tally_proofs(
  1461. const std::vector<std::vector<Scalar>>& permutations,
  1462. const Scalar& power,
  1463. const Twistpoint& nextGenerator,
  1464. const std::vector<std::vector<Scalar>>& permutationSeeds,
  1465. const std::vector<std::vector<Scalar>>& userTallySeeds,
  1466. const std::vector<Twistpoint>& currPseudonyms,
  1467. const std::vector<Twistpoint>& userTallyMasks,
  1468. const std::vector<Twistpoint>& userTallyMessages,
  1469. const std::vector<std::vector<Twistpoint>>& permutationCommits,
  1470. const std::vector<std::vector<Twistpoint>>& userTallyMaskCommits,
  1471. const std::vector<std::vector<Twistpoint>>& userTallyMessageCommits,
  1472. const std::vector<std::vector<Twistpoint>>& userTallySeedCommits) const
  1473. {
  1474. std::vector<Proof> retval;
  1475. if (!SERVER_IS_MALICIOUS)
  1476. {
  1477. retval.push_back(Proof("PROOF"));
  1478. return retval;
  1479. }
  1480. Proof first;
  1481. retval.push_back(first);
  1482. Twistpoint g = EL_GAMAL_GENERATOR;
  1483. Twistpoint h = elGamalBlindGenerator;
  1484. std::stringstream oracleInput;
  1485. oracleInput << g << h << nextGenerator;
  1486. for (size_t i = 0; i < currPseudonyms.size(); i++)
  1487. oracleInput << currPseudonyms[i];
  1488. for (size_t i = 0; i < userTallyMasks.size(); i++)
  1489. oracleInput << userTallyMasks[i];
  1490. for (size_t i = 0; i < userTallyMessages.size(); i++)
  1491. oracleInput << userTallyMessages[i];
  1492. for (size_t i = 0; i < permutationCommits.size(); i++)
  1493. for (size_t j = 0; j < permutationCommits[i].size(); j++)
  1494. oracleInput << permutationCommits[i][j];
  1495. for (size_t i = 0; i < userTallyMaskCommits.size(); i++)
  1496. for (size_t j = 0; j < userTallyMaskCommits[i].size(); j++)
  1497. oracleInput << userTallyMaskCommits[i][j];
  1498. for (size_t i = 0; i < userTallyMessageCommits.size(); i++)
  1499. for (size_t j = 0; j < userTallyMessageCommits[i].size(); j++)
  1500. oracleInput << userTallyMessageCommits[i][j];
  1501. for (size_t i = 0; i < userTallySeedCommits.size(); i++)
  1502. for (size_t j = 0; j < userTallySeedCommits[i].size(); j++)
  1503. oracleInput << userTallySeedCommits[i][j];
  1504. Scalar b1;
  1505. b1.set_random();
  1506. std::vector<std::vector<Scalar>> b2;
  1507. std::vector<std::vector<Scalar>> t1;
  1508. std::vector<std::vector<Scalar>> t2;
  1509. for (size_t i = 0; i < permutationCommits.size(); i++)
  1510. {
  1511. std::vector<Scalar> currb2Row;
  1512. std::vector<Scalar> currt1Row;
  1513. std::vector<Scalar> currt2Row;
  1514. for (size_t j = 0; j < permutationCommits[i].size(); j++)
  1515. {
  1516. Proof currProof;
  1517. Scalar currb2;
  1518. Scalar currt1;
  1519. Scalar currt2;
  1520. Twistpoint U1, U2, U3, U4, U5, U6, U7;
  1521. currb2.set_random();
  1522. currt1.set_random();
  1523. currt2.set_random();
  1524. U1 = g * currb2 + h * currt1;
  1525. U2 = userTallyMasks[j] * (b1 * permutations[j][i] + currb2 * power) +
  1526. currPseudonyms[j] * (permutations[j][i] * b1 * userTallySeeds[i][j] + power * currb2 * userTallySeeds[i][j] + permutations[j][i] * power * currt2) +
  1527. h * currt2;
  1528. U3 = userTallyMasks[j] * (b1 * currb2) +
  1529. currPseudonyms[j] * (b1 * currb2 * userTallySeeds[i][j] + permutations[j][i] * b1 * currt2 + power * currb2 * currt2);
  1530. U4 = currPseudonyms[j] * (b1 * currb2 * currt2);
  1531. U5 = userTallyMessages[j] * currb2 +
  1532. nextGenerator * (permutations[j][i] * currt2 + userTallySeeds[i][j] * currb2) +
  1533. h * currt2;
  1534. U6 = nextGenerator * (currb2 * currt2);
  1535. U7 = g * currt2;
  1536. currProof.curvepointUniversals.push_back(U2);
  1537. currProof.curvepointUniversals.push_back(U3);
  1538. currProof.curvepointUniversals.push_back(U5);
  1539. oracleInput << U1 << U2 << U3 << U4 << U5 << U6 << U7;
  1540. currb2Row.push_back(currb2);
  1541. currt1Row.push_back(currt1);
  1542. currt2Row.push_back(currt2);
  1543. retval.push_back(currProof);
  1544. }
  1545. b2.push_back(currb2Row);
  1546. t1.push_back(currt1Row);
  1547. t2.push_back(currt2Row);
  1548. }
  1549. Scalar x = oracle(oracleInput.str());
  1550. retval[0].challengeParts.push_back(x);
  1551. Scalar f1 = power * x + b1;
  1552. retval[0].responseParts.push_back(f1);
  1553. for (size_t i = 0; i < permutationCommits.size(); i++)
  1554. {
  1555. for (size_t j = 0; j < permutationCommits[i].size(); j++)
  1556. {
  1557. size_t piIndex = i * permutationCommits.size() + j + 1;
  1558. Scalar f2 = permutations[j][i] * x + b2[i][j];
  1559. Scalar z1 = permutationSeeds[j][i] * x + t1[i][j];
  1560. Scalar z2 = userTallySeeds[i][j] * x + t2[i][j];
  1561. retval[piIndex].responseParts.push_back(f2);
  1562. retval[piIndex].responseParts.push_back(z1);
  1563. retval[piIndex].responseParts.push_back(z2);
  1564. }
  1565. }
  1566. return retval;
  1567. }
  1568. bool PrsonaBase::verify_unbatched_user_tally_proofs(
  1569. const std::vector<Proof>& pi,
  1570. const Twistpoint& nextGenerator,
  1571. const std::vector<Twistpoint>& currPseudonyms,
  1572. const std::vector<Twistpoint>& userTallyMasks,
  1573. const std::vector<Twistpoint>& userTallyMessages,
  1574. const std::vector<std::vector<Twistpoint>>& permutationCommits,
  1575. const std::vector<std::vector<Twistpoint>>& userTallyMaskCommits,
  1576. const std::vector<std::vector<Twistpoint>>& userTallyMessageCommits,
  1577. const std::vector<std::vector<Twistpoint>>& userTallySeedCommits) const
  1578. {
  1579. if (pi.empty())
  1580. return false;
  1581. if (!SERVER_IS_MALICIOUS)
  1582. return true;
  1583. Twistpoint g = EL_GAMAL_GENERATOR;
  1584. Twistpoint h = elGamalBlindGenerator;
  1585. std::stringstream oracleInput;
  1586. oracleInput << g << h << nextGenerator;
  1587. for (size_t i = 0; i < currPseudonyms.size(); i++)
  1588. oracleInput << currPseudonyms[i];
  1589. for (size_t i = 0; i < userTallyMasks.size(); i++)
  1590. oracleInput << userTallyMasks[i];
  1591. for (size_t i = 0; i < userTallyMessages.size(); i++)
  1592. oracleInput << userTallyMessages[i];
  1593. for (size_t i = 0; i < permutationCommits.size(); i++)
  1594. for (size_t j = 0; j < permutationCommits[i].size(); j++)
  1595. oracleInput << permutationCommits[i][j];
  1596. for (size_t i = 0; i < userTallyMaskCommits.size(); i++)
  1597. for (size_t j = 0; j < userTallyMaskCommits[i].size(); j++)
  1598. oracleInput << userTallyMaskCommits[i][j];
  1599. for (size_t i = 0; i < userTallyMessageCommits.size(); i++)
  1600. for (size_t j = 0; j < userTallyMessageCommits[i].size(); j++)
  1601. oracleInput << userTallyMessageCommits[i][j];
  1602. for (size_t i = 0; i < userTallySeedCommits.size(); i++)
  1603. for (size_t j = 0; j < userTallySeedCommits[i].size(); j++)
  1604. oracleInput << userTallySeedCommits[i][j];
  1605. Scalar x = pi[0].challengeParts[0];
  1606. Scalar f1 = pi[0].responseParts[0];
  1607. for (size_t i = 0; i < permutationCommits.size(); i++)
  1608. {
  1609. for (size_t j = 0; j < permutationCommits[i].size(); j++)
  1610. {
  1611. size_t piIndex = i * permutationCommits.size() + j + 1;
  1612. Twistpoint U1, U2, U3, U4, U5, U6, U7;
  1613. U2 = pi[piIndex].curvepointUniversals[0];
  1614. U3 = pi[piIndex].curvepointUniversals[1];
  1615. U5 = pi[piIndex].curvepointUniversals[2];
  1616. Scalar f2 = pi[piIndex].responseParts[0];
  1617. Scalar z1 = pi[piIndex].responseParts[1];
  1618. Scalar z2 = pi[piIndex].responseParts[2];
  1619. U1 = g * f2 + h * z1 - permutationCommits[j][i] * x;
  1620. U4 = userTallyMasks[j] * (f1 * f2 * x) +
  1621. currPseudonyms[j] * (f1 * f2 * z2) +
  1622. h * (z2 * x * x) -
  1623. userTallyMaskCommits[i][j] * (x * x * x) -
  1624. U2 * (x * x) -
  1625. U3 * x;
  1626. U6 = userTallyMessages[j] * (f2 * x) +
  1627. nextGenerator * (f2 * z2) +
  1628. h * (z2 * x) -
  1629. userTallyMessageCommits[i][j] * (x * x) -
  1630. U5 * x;
  1631. U7 = g * z2 - userTallySeedCommits[i][j] * x;
  1632. oracleInput << U1 << U2 << U3 << U4 << U5 << U6 << U7;
  1633. }
  1634. }
  1635. if (x != oracle(oracleInput.str()))
  1636. {
  1637. std::cerr << "User tallies not generated by permutation matrix." << std::endl;
  1638. return false;
  1639. }
  1640. for (size_t i = 0; i < userTallySeedCommits.size(); i++)
  1641. {
  1642. Twistpoint sum = userTallySeedCommits[i][0];
  1643. for (size_t j = 1; j < userTallySeedCommits[i].size(); j++)
  1644. sum = sum + userTallySeedCommits[i][j];
  1645. if (sum != Twistpoint())
  1646. {
  1647. std::cerr << "seed commits did not sum to 0, aborting." << std::endl;
  1648. return false;
  1649. }
  1650. }
  1651. return true;
  1652. }
  1653. std::vector<Proof> PrsonaBase::generate_batched_user_tally_proofs(
  1654. const std::vector<std::vector<Scalar>>& permutations,
  1655. const Scalar& power,
  1656. const Twistpoint& nextGenerator,
  1657. const std::vector<std::vector<Scalar>>& permutationSeeds,
  1658. const std::vector<std::vector<Scalar>>& userTallySeeds,
  1659. const std::vector<Twistpoint>& currPseudonyms,
  1660. const std::vector<Twistpoint>& userTallyMasks,
  1661. const std::vector<Twistpoint>& userTallyMessages,
  1662. const std::vector<std::vector<Twistpoint>>& permutationCommits,
  1663. const std::vector<std::vector<Twistpoint>>& userTallyMaskCommits,
  1664. const std::vector<std::vector<Twistpoint>>& userTallyMessageCommits,
  1665. const std::vector<std::vector<Twistpoint>>& userTallySeedCommits) const
  1666. {
  1667. std::vector<Proof> retval;
  1668. if (!SERVER_IS_MALICIOUS)
  1669. {
  1670. retval.push_back(Proof("PROOF"));
  1671. return retval;
  1672. }
  1673. Proof first;
  1674. retval.push_back(first);
  1675. Twistpoint g = EL_GAMAL_GENERATOR;
  1676. Twistpoint h = elGamalBlindGenerator;
  1677. std::stringstream oracleInput;
  1678. oracleInput << g << h << nextGenerator;
  1679. for (size_t i = 0; i < currPseudonyms.size(); i++)
  1680. oracleInput << currPseudonyms[i];
  1681. for (size_t i = 0; i < userTallyMasks.size(); i++)
  1682. oracleInput << userTallyMasks[i];
  1683. for (size_t i = 0; i < userTallyMessages.size(); i++)
  1684. oracleInput << userTallyMessages[i];
  1685. for (size_t i = 0; i < permutationCommits.size(); i++)
  1686. for (size_t j = 0; j < permutationCommits[i].size(); j++)
  1687. oracleInput << permutationCommits[i][j];
  1688. for (size_t i = 0; i < userTallyMaskCommits.size(); i++)
  1689. for (size_t j = 0; j < userTallyMaskCommits[i].size(); j++)
  1690. oracleInput << userTallyMaskCommits[i][j];
  1691. for (size_t i = 0; i < userTallyMessageCommits.size(); i++)
  1692. for (size_t j = 0; j < userTallyMessageCommits[i].size(); j++)
  1693. oracleInput << userTallyMessageCommits[i][j];
  1694. for (size_t i = 0; i < userTallySeedCommits.size(); i++)
  1695. for (size_t j = 0; j < userTallySeedCommits[i].size(); j++)
  1696. oracleInput << userTallySeedCommits[i][j];
  1697. std::vector<Scalar> b1;
  1698. std::vector<Scalar> b2;
  1699. std::vector<Scalar> t1;
  1700. std::vector<Scalar> t2;
  1701. for (size_t i = 0; i < permutationCommits.size(); i++)
  1702. {
  1703. Proof currProof;
  1704. Scalar currb1;
  1705. Scalar currb2;
  1706. Scalar currt1;
  1707. Scalar currt2;
  1708. Twistpoint U1, U4, U6, U7;
  1709. std::vector<Twistpoint> U2, U3, U5;
  1710. currb1.set_random();
  1711. currb2.set_random();
  1712. currt1.set_random();
  1713. currt2.set_random();
  1714. U1 = g * currb2 + h * currt1;
  1715. U4 = currPseudonyms[i] * (currb1 * currb2 * currt2);
  1716. U6 = nextGenerator * (currb2 * currt2);
  1717. U7 = g * currt2;
  1718. for (size_t j = 0; j < permutationCommits[i].size(); j++)
  1719. {
  1720. Twistpoint currU2, currU3, currU5;
  1721. Scalar U2MaskMult = power * currb2 + currb1 * permutations[i][j];
  1722. Scalar U2PseudMult =
  1723. power * currt2 * permutations[i][j] +
  1724. power * currb2 * userTallySeeds[j][i] +
  1725. currb1 * permutations[i][j] * userTallySeeds[j][i];
  1726. Scalar U2hMult = currt2;
  1727. Scalar U3MaskMult = currb1 * currb2;
  1728. Scalar U3PseudMult = power * currb2 * currt2 +
  1729. currb1 * currt2 * permutations[i][j] +
  1730. currb1 * currb2 * userTallySeeds[j][i];
  1731. Scalar U3hMult = Scalar(0);
  1732. Scalar U5MessageMult = currb2;
  1733. Scalar U5GenMult = currb2 * userTallySeeds[j][i] + currt2 * permutations[i][j];
  1734. Scalar U5hMult = currt2;
  1735. for (size_t k = 0; k < permutationCommits[i].size(); k++)
  1736. {
  1737. if (k == j)
  1738. continue;
  1739. std::stringstream xkOracle;
  1740. xkOracle << permutationCommits[i][k] << userTallyMaskCommits[k][i] << userTallyMessageCommits[k][i] << userTallySeedCommits[k][i];
  1741. Scalar x_k = oracle(xkOracle.str(), LAMBDA);
  1742. for (size_t l = 0; l < permutationCommits[i].size(); l++)
  1743. {
  1744. if (l == j)
  1745. continue;
  1746. if (l == k)
  1747. continue;
  1748. std::stringstream xlOracle;
  1749. xlOracle << permutationCommits[i][l] << userTallyMaskCommits[l][i] << userTallyMessageCommits[l][i] << userTallySeedCommits[l][i];
  1750. Scalar x_l = oracle(xlOracle.str(), LAMBDA);
  1751. U3MaskMult = U3MaskMult +
  1752. power * permutations[i][j] * x_k * x_l;
  1753. U3PseudMult = U3PseudMult +
  1754. power * permutations[i][j] * userTallySeeds[k][i] * x_k * x_l;
  1755. U3hMult = U3hMult +
  1756. userTallySeeds[j][i] * x_k * x_l;
  1757. }
  1758. U2MaskMult = U2MaskMult +
  1759. Scalar(2) * power * permutations[i][j] * x_k +
  1760. power * permutations[i][k] * x_k;
  1761. U2PseudMult = U2PseudMult +
  1762. power * permutations[i][j] * userTallySeeds[j][i] * x_k +
  1763. power * permutations[i][k] * userTallySeeds[j][i] * x_k +
  1764. power * permutations[i][j] * userTallySeeds[k][i] * x_k;
  1765. U2hMult = U2hMult +
  1766. Scalar(2) * userTallySeeds[j][i] * x_k +
  1767. userTallySeeds[k][i] * x_k;
  1768. U3MaskMult = U3MaskMult +
  1769. power * currb2 * x_k +
  1770. currb1 * permutations[i][j] * x_k;
  1771. U3PseudMult = U3PseudMult +
  1772. power * currt2 * permutations[i][j] * x_k +
  1773. power * currb2 * userTallySeeds[j][i] * x_k +
  1774. currb1 * permutations[i][j] * userTallySeeds[k][i] * x_k;
  1775. U3hMult = U3hMult +
  1776. currt2 * x_k;
  1777. U5MessageMult = U5MessageMult +
  1778. permutations[i][j] * x_k;
  1779. U5GenMult = U5GenMult +
  1780. permutations[i][j] * userTallySeeds[k][i] * x_k;
  1781. U5hMult = U5hMult +
  1782. userTallySeeds[j][i] * x_k;
  1783. }
  1784. currU2 = userTallyMasks[i] * U2MaskMult +
  1785. currPseudonyms[i] * U2PseudMult +
  1786. h * U2hMult;
  1787. currU3 = userTallyMasks[i] * U3MaskMult +
  1788. currPseudonyms[i] * U3PseudMult +
  1789. h * U3hMult;
  1790. currU5 = userTallyMessages[i] * U5MessageMult +
  1791. nextGenerator * U5GenMult +
  1792. h * U5hMult;
  1793. U2.push_back(currU2);
  1794. U3.push_back(currU3);
  1795. U5.push_back(currU5);
  1796. }
  1797. oracleInput << U1;
  1798. for (size_t j = 0; j < permutationCommits[i].size(); j++)
  1799. {
  1800. oracleInput << U2[j];
  1801. currProof.curvepointUniversals.push_back(U2[j]);
  1802. }
  1803. for (size_t j = 0; j < permutationCommits[i].size(); j++)
  1804. {
  1805. oracleInput << U3[j];
  1806. currProof.curvepointUniversals.push_back(U3[j]);
  1807. }
  1808. oracleInput << U4;
  1809. for (size_t j = 0; j < permutationCommits[i].size(); j++)
  1810. {
  1811. oracleInput << U5[j];
  1812. currProof.curvepointUniversals.push_back(U5[j]);
  1813. }
  1814. oracleInput << U6 << U7;
  1815. b1.push_back(currb1);
  1816. b2.push_back(currb2);
  1817. t1.push_back(currt1);
  1818. t2.push_back(currt2);
  1819. retval.push_back(currProof);
  1820. }
  1821. Scalar x = oracle(oracleInput.str());
  1822. retval[0].challengeParts.push_back(x);
  1823. for (size_t i = 0; i < permutationCommits.size(); i++)
  1824. {
  1825. size_t piIndex = i + 1;
  1826. Scalar f1 = b1[i];
  1827. Scalar f2 = b2[i];
  1828. Scalar z1 = t1[i];
  1829. Scalar z2 = t2[i];
  1830. for (size_t j = 0; j < permutationCommits[i].size(); j++)
  1831. {
  1832. std::stringstream currOracle;
  1833. currOracle << permutationCommits[i][j] << userTallyMaskCommits[j][i] << userTallyMessageCommits[j][i] << userTallySeedCommits[j][i];
  1834. Scalar currx = oracle(currOracle.str(), LAMBDA);
  1835. f1 = f1 + power * currx;
  1836. f2 = f2 + permutations[i][j] * currx;
  1837. z1 = z1 + permutationSeeds[i][j] * currx;
  1838. z2 = z2 + userTallySeeds[j][i] * currx;
  1839. }
  1840. retval[piIndex].responseParts.push_back(f1);
  1841. retval[piIndex].responseParts.push_back(f2);
  1842. retval[piIndex].responseParts.push_back(z1);
  1843. retval[piIndex].responseParts.push_back(z2);
  1844. }
  1845. return retval;
  1846. }
  1847. bool PrsonaBase::verify_batched_user_tally_proofs(
  1848. const std::vector<Proof>& pi,
  1849. const Twistpoint& nextGenerator,
  1850. const std::vector<Twistpoint>& currPseudonyms,
  1851. const std::vector<Twistpoint>& userTallyMasks,
  1852. const std::vector<Twistpoint>& userTallyMessages,
  1853. const std::vector<std::vector<Twistpoint>>& permutationCommits,
  1854. const std::vector<std::vector<Twistpoint>>& userTallyMaskCommits,
  1855. const std::vector<std::vector<Twistpoint>>& userTallyMessageCommits,
  1856. const std::vector<std::vector<Twistpoint>>& userTallySeedCommits) const
  1857. {
  1858. if (pi.empty())
  1859. return false;
  1860. if (!SERVER_IS_MALICIOUS)
  1861. return true;
  1862. Twistpoint g = EL_GAMAL_GENERATOR;
  1863. Twistpoint h = elGamalBlindGenerator;
  1864. std::stringstream oracleInput;
  1865. oracleInput << g << h << nextGenerator;
  1866. for (size_t i = 0; i < currPseudonyms.size(); i++)
  1867. oracleInput << currPseudonyms[i];
  1868. for (size_t i = 0; i < userTallyMasks.size(); i++)
  1869. oracleInput << userTallyMasks[i];
  1870. for (size_t i = 0; i < userTallyMessages.size(); i++)
  1871. oracleInput << userTallyMessages[i];
  1872. for (size_t i = 0; i < permutationCommits.size(); i++)
  1873. for (size_t j = 0; j < permutationCommits[i].size(); j++)
  1874. oracleInput << permutationCommits[i][j];
  1875. for (size_t i = 0; i < userTallyMaskCommits.size(); i++)
  1876. for (size_t j = 0; j < userTallyMaskCommits[i].size(); j++)
  1877. oracleInput << userTallyMaskCommits[i][j];
  1878. for (size_t i = 0; i < userTallyMessageCommits.size(); i++)
  1879. for (size_t j = 0; j < userTallyMessageCommits[i].size(); j++)
  1880. oracleInput << userTallyMessageCommits[i][j];
  1881. for (size_t i = 0; i < userTallySeedCommits.size(); i++)
  1882. for (size_t j = 0; j < userTallySeedCommits[i].size(); j++)
  1883. oracleInput << userTallySeedCommits[i][j];
  1884. Scalar x = pi[0].challengeParts[0];
  1885. for (size_t i = 0; i < permutationCommits.size(); i++)
  1886. {
  1887. Scalar sum_of_sub_xs = Scalar(0);
  1888. std::vector<Scalar> sub_xs;
  1889. for (size_t j = 0; j < permutationCommits[i].size(); j++)
  1890. {
  1891. std::stringstream currOracle;
  1892. currOracle << permutationCommits[i][j] << userTallyMaskCommits[j][i] << userTallyMessageCommits[j][i] << userTallySeedCommits[j][i];
  1893. sub_xs.push_back(oracle(currOracle.str(), LAMBDA));
  1894. sum_of_sub_xs = sum_of_sub_xs + sub_xs[j];
  1895. }
  1896. size_t piIndex = i + 1;
  1897. std::vector<Twistpoint> U2(pi[piIndex].curvepointUniversals.begin(), pi[piIndex].curvepointUniversals.begin() + permutationCommits.size());
  1898. std::vector<Twistpoint> U3(pi[piIndex].curvepointUniversals.begin() + permutationCommits.size(), pi[piIndex].curvepointUniversals.begin() + (2 * permutationCommits.size()));
  1899. std::vector<Twistpoint> U5(pi[piIndex].curvepointUniversals.begin() + (2 * permutationCommits.size()), pi[piIndex].curvepointUniversals.end());
  1900. Scalar f1 = pi[piIndex].responseParts[0];
  1901. Scalar f2 = pi[piIndex].responseParts[1];
  1902. Scalar z1 = pi[piIndex].responseParts[2];
  1903. Scalar z2 = pi[piIndex].responseParts[3];
  1904. Twistpoint U1 = g * f2 + h * z1;
  1905. Twistpoint U4 = userTallyMasks[i] * (f1 * f2 * sum_of_sub_xs) +
  1906. currPseudonyms[i] * (f1 * f2 * z2) +
  1907. h * (z2 * sum_of_sub_xs * sum_of_sub_xs);
  1908. Twistpoint U6 = userTallyMessages[i] * (f2 * sum_of_sub_xs) +
  1909. nextGenerator * (f2 * z2) +
  1910. h * (z2 * sum_of_sub_xs);
  1911. Twistpoint U7 = g * z2;
  1912. for (size_t j = 0; j < permutationCommits[i].size(); j++)
  1913. {
  1914. U1 = U1 - permutationCommits[i][j] * sub_xs[j];
  1915. U4 = U4 -
  1916. userTallyMaskCommits[j][i] * (sub_xs[j] * sub_xs[j] * sub_xs[j]) -
  1917. U2[j] * (sub_xs[j] * sub_xs[j]) -
  1918. U3[j] * sub_xs[j];
  1919. U6 = U6 -
  1920. userTallyMessageCommits[j][i] * (sub_xs[j] * sub_xs[j]) -
  1921. U5[j] * sub_xs[j];
  1922. U7 = U7 - userTallySeedCommits[j][i] * sub_xs[j];
  1923. }
  1924. oracleInput << U1;
  1925. for (size_t j = 0; j < permutationCommits[i].size(); j++)
  1926. oracleInput << U2[j];
  1927. for (size_t j = 0; j < permutationCommits[i].size(); j++)
  1928. oracleInput << U3[j];
  1929. oracleInput << U4;
  1930. for (size_t j = 0; j < permutationCommits[i].size(); j++)
  1931. oracleInput << U5[j];
  1932. oracleInput << U6 << U7;
  1933. }
  1934. if (x != oracle(oracleInput.str()))
  1935. {
  1936. std::cerr << "User tallies not generated by permutation matrix." << std::endl;
  1937. return false;
  1938. }
  1939. for (size_t i = 0; i < userTallySeedCommits.size(); i++)
  1940. {
  1941. Twistpoint sum = userTallySeedCommits[i][0];
  1942. for (size_t j = 1; j < userTallySeedCommits[i].size(); j++)
  1943. sum = sum + userTallySeedCommits[i][j];
  1944. if (sum != Twistpoint())
  1945. {
  1946. std::cerr << "seed commits did not sum to 0, aborting." << std::endl;
  1947. return false;
  1948. }
  1949. }
  1950. return true;
  1951. }
  1952. /*
  1953. * SERVER AGREEMENT PROOFS
  1954. */
  1955. Proof PrsonaBase::generate_valid_vote_row_proof(
  1956. const std::vector<TwistBipoint>& commitment) const
  1957. {
  1958. Proof retval;
  1959. if (!SERVER_IS_MALICIOUS)
  1960. {
  1961. retval.hbc = "PROOF";
  1962. return retval;
  1963. }
  1964. std::stringstream oracleInput;
  1965. for (size_t i = 0; i < commitment.size(); i++)
  1966. oracleInput << commitment[i];
  1967. Scalar val = oracle(oracleInput.str());
  1968. retval.responseParts.push_back(val);
  1969. return retval;
  1970. }
  1971. Proof PrsonaBase::generate_valid_vote_matrix_proof(
  1972. const std::vector<std::vector<TwistBipoint>>& commitment) const
  1973. {
  1974. Proof retval;
  1975. if (!SERVER_IS_MALICIOUS)
  1976. {
  1977. retval.hbc = "PROOF";
  1978. return retval;
  1979. }
  1980. std::stringstream oracleInput;
  1981. for (size_t i = 0; i < commitment.size(); i++)
  1982. for (size_t j = 0; j < commitment[i].size(); j++)
  1983. oracleInput << commitment[i][j];
  1984. Scalar val = oracle(oracleInput.str());
  1985. retval.responseParts.push_back(val);
  1986. return retval;
  1987. }
  1988. Proof PrsonaBase::generate_valid_user_tally_proof(
  1989. const EGCiphertext& commitment) const
  1990. {
  1991. Proof retval;
  1992. if (!SERVER_IS_MALICIOUS)
  1993. {
  1994. retval.hbc = "PROOF";
  1995. return retval;
  1996. }
  1997. std::stringstream oracleInput;
  1998. oracleInput << commitment;
  1999. Scalar val = oracle(oracleInput.str());
  2000. retval.responseParts.push_back(val);
  2001. return retval;
  2002. }
  2003. Proof PrsonaBase::generate_valid_server_tally_proof(
  2004. const CurveBipoint& commitment) const
  2005. {
  2006. Proof retval;
  2007. if (!SERVER_IS_MALICIOUS)
  2008. {
  2009. retval.hbc = "PROOF";
  2010. return retval;
  2011. }
  2012. std::stringstream oracleInput;
  2013. oracleInput << commitment;
  2014. Scalar val = oracle(oracleInput.str());
  2015. retval.responseParts.push_back(val);
  2016. return retval;
  2017. }
  2018. Proof PrsonaBase::generate_valid_pseudonyms_proof(
  2019. const std::vector<Twistpoint>& commitment) const
  2020. {
  2021. Proof retval;
  2022. if (!SERVER_IS_MALICIOUS)
  2023. {
  2024. retval.hbc = "PROOF";
  2025. return retval;
  2026. }
  2027. std::stringstream oracleInput;
  2028. for (size_t i = 0; i < commitment.size(); i++)
  2029. oracleInput << commitment[i];
  2030. Scalar val = oracle(oracleInput.str());
  2031. retval.responseParts.push_back(val);
  2032. return retval;
  2033. }
  2034. bool PrsonaBase::verify_valid_vote_row_proof(
  2035. const std::vector<Proof>& pi,
  2036. const std::vector<TwistBipoint>& commitment) const
  2037. {
  2038. if (pi.empty())
  2039. return false;
  2040. if (!SERVER_IS_MALICIOUS)
  2041. return true;
  2042. Scalar comparison = pi[0].responseParts[0];
  2043. std::stringstream oracleInput;
  2044. for (size_t i = 0; i < commitment.size(); i++)
  2045. oracleInput << commitment[i];
  2046. if (oracle(oracleInput.str()) != comparison)
  2047. {
  2048. std::cerr << "Server's claimed value doesn't match their own commitment." << std::endl;
  2049. return false;
  2050. }
  2051. size_t agreement = 1;
  2052. for (size_t i = 1; i < pi.size(); i++)
  2053. if (comparison == pi[i].responseParts[0])
  2054. agreement++;
  2055. return agreement * 2 > pi.size();
  2056. }
  2057. bool PrsonaBase::verify_valid_vote_matrix_proof(
  2058. const std::vector<Proof>& pi,
  2059. const std::vector<std::vector<TwistBipoint>>& commitment) const
  2060. {
  2061. if (pi.empty())
  2062. return false;
  2063. if (!SERVER_IS_MALICIOUS)
  2064. return true;
  2065. Scalar comparison = pi[0].responseParts[0];
  2066. std::stringstream oracleInput;
  2067. for (size_t i = 0; i < commitment.size(); i++)
  2068. for (size_t j = 0; j < commitment[i].size(); j++)
  2069. oracleInput << commitment[i][j];
  2070. if (oracle(oracleInput.str()) != comparison)
  2071. {
  2072. std::cerr << "Server's claimed value doesn't match their own commitment." << std::endl;
  2073. return false;
  2074. }
  2075. size_t agreement = 1;
  2076. for (size_t i = 1; i < pi.size(); i++)
  2077. if (comparison == pi[i].responseParts[0])
  2078. agreement++;
  2079. return agreement * 2 > pi.size();
  2080. }
  2081. bool PrsonaBase::verify_valid_user_tally_proof(
  2082. const std::vector<Proof>& pi,
  2083. const EGCiphertext& commitment) const
  2084. {
  2085. if (pi.empty())
  2086. return false;
  2087. if (!SERVER_IS_MALICIOUS)
  2088. return true;
  2089. Scalar comparison = pi[0].responseParts[0];
  2090. std::stringstream oracleInput;
  2091. oracleInput << commitment;
  2092. if (oracle(oracleInput.str()) != comparison)
  2093. {
  2094. std::cerr << "Server's claimed value doesn't match their own commitment." << std::endl;
  2095. return false;
  2096. }
  2097. size_t agreement = 1;
  2098. for (size_t i = 1; i < pi.size(); i++)
  2099. if (comparison == pi[i].responseParts[0])
  2100. agreement++;
  2101. return agreement * 2 > pi.size();
  2102. }
  2103. bool PrsonaBase::verify_valid_server_tally_proof(
  2104. const std::vector<Proof>& pi,
  2105. const CurveBipoint& commitment) const
  2106. {
  2107. if (pi.empty())
  2108. return false;
  2109. if (!SERVER_IS_MALICIOUS)
  2110. return true;
  2111. Scalar comparison = pi[0].responseParts[0];
  2112. std::stringstream oracleInput;
  2113. oracleInput << commitment;
  2114. if (oracle(oracleInput.str()) != comparison)
  2115. {
  2116. std::cerr << "Server's claimed value doesn't match their own commitment." << std::endl;
  2117. return false;
  2118. }
  2119. size_t agreement = 1;
  2120. for (size_t i = 1; i < pi.size(); i++)
  2121. if (comparison == pi[i].responseParts[0])
  2122. agreement++;
  2123. return agreement * 2 > pi.size();
  2124. }
  2125. bool PrsonaBase::verify_valid_pseudonyms_proof(
  2126. const std::vector<Proof>& pi,
  2127. const std::vector<Twistpoint>& commitment) const
  2128. {
  2129. if (pi.empty())
  2130. return false;
  2131. if (!SERVER_IS_MALICIOUS)
  2132. return true;
  2133. Scalar comparison = pi[0].responseParts[0];
  2134. std::stringstream oracleInput;
  2135. for (size_t i = 0; i < commitment.size(); i++)
  2136. oracleInput << commitment[i];
  2137. if (oracle(oracleInput.str()) != comparison)
  2138. {
  2139. std::cerr << "Server's claimed value doesn't match their own commitment." << std::endl;
  2140. return false;
  2141. }
  2142. size_t agreement = 1;
  2143. for (size_t i = 1; i < pi.size(); i++)
  2144. if (comparison == pi[i].responseParts[0])
  2145. agreement++;
  2146. return agreement * 2 > pi.size();
  2147. }
  2148. template std::vector<Proof> PrsonaBase::generate_proof_of_reordering<Twistpoint>(
  2149. const std::vector<std::vector<Scalar>>& permutations,
  2150. const std::vector<std::vector<Scalar>>& permutationSeeds,
  2151. const std::vector<std::vector<Scalar>>& productSeeds,
  2152. const std::vector<Twistpoint>& oldValues,
  2153. const std::vector<std::vector<Twistpoint>>& permutationCommits,
  2154. const std::vector<std::vector<Twistpoint>>& productCommits,
  2155. const Twistpoint& otherG,
  2156. const Twistpoint& otherH) const;
  2157. template std::vector<Proof> PrsonaBase::generate_proof_of_reordering<TwistBipoint>(
  2158. const std::vector<std::vector<Scalar>>& permutations,
  2159. const std::vector<std::vector<Scalar>>& permutationSeeds,
  2160. const std::vector<std::vector<Scalar>>& productSeeds,
  2161. const std::vector<TwistBipoint>& oldValues,
  2162. const std::vector<std::vector<Twistpoint>>& permutationCommits,
  2163. const std::vector<std::vector<TwistBipoint>>& productCommits,
  2164. const TwistBipoint& otherG,
  2165. const TwistBipoint& otherH) const;
  2166. template std::vector<Proof> PrsonaBase::generate_proof_of_reordering<CurveBipoint>(
  2167. const std::vector<std::vector<Scalar>>& permutations,
  2168. const std::vector<std::vector<Scalar>>& permutationSeeds,
  2169. const std::vector<std::vector<Scalar>>& productSeeds,
  2170. const std::vector<CurveBipoint>& oldValues,
  2171. const std::vector<std::vector<Twistpoint>>& permutationCommits,
  2172. const std::vector<std::vector<CurveBipoint>>& productCommits,
  2173. const CurveBipoint& otherG,
  2174. const CurveBipoint& otherH) const;
  2175. template bool PrsonaBase::verify_proof_of_reordering<Twistpoint>(
  2176. const std::vector<Proof>& pi,
  2177. const std::vector<Twistpoint>& oldValues,
  2178. const std::vector<std::vector<Twistpoint>>& permutationCommits,
  2179. const std::vector<std::vector<Twistpoint>>& productCommits,
  2180. const Twistpoint& otherG,
  2181. const Twistpoint& otherH) const;
  2182. template bool PrsonaBase::verify_proof_of_reordering<TwistBipoint>(
  2183. const std::vector<Proof>& pi,
  2184. const std::vector<TwistBipoint>& oldValues,
  2185. const std::vector<std::vector<Twistpoint>>& permutationCommits,
  2186. const std::vector<std::vector<TwistBipoint>>& productCommits,
  2187. const TwistBipoint& otherG,
  2188. const TwistBipoint& otherH) const;
  2189. template bool PrsonaBase::verify_proof_of_reordering<CurveBipoint>(
  2190. const std::vector<Proof>& pi,
  2191. const std::vector<CurveBipoint>& oldValues,
  2192. const std::vector<std::vector<Twistpoint>>& permutationCommits,
  2193. const std::vector<std::vector<CurveBipoint>>& productCommits,
  2194. const CurveBipoint& otherG,
  2195. const CurveBipoint& otherH) const;