ParamGeneration.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626
  1. // ECOin - Copyright (c) - 2014/2022 - GPLv3 - epsylon@riseup.net (https://03c8.net)
  2. #include <string>
  3. #include "Zerocoin.h"
  4. using namespace std;
  5. namespace libzerocoin {
  6. void
  7. CalculateParams(Params &params, CBigNum N, string aux, uint32_t securityLevel)
  8. {
  9. params.initialized = false;
  10. params.accumulatorParams.initialized = false;
  11. // Verify that |N| is > 1023 bits.
  12. uint32_t NLen = N.bitSize();
  13. if (NLen < 1023) {
  14. throw ZerocoinException("Modulus must be at least 1023 bits");
  15. }
  16. // Verify that "securityLevel" is at least 80 bits (minimum).
  17. if (securityLevel < 80) {
  18. throw ZerocoinException("Security level must be at least 80 bits.");
  19. }
  20. // Set the accumulator modulus to "N".
  21. params.accumulatorParams.accumulatorModulus = N;
  22. // Calculate the required size of the field "F_p" into which
  23. // we're embedding the coin commitment group. This may throw an
  24. // exception if the securityLevel is too large to be supported
  25. // by the current modulus.
  26. uint32_t pLen = 0;
  27. uint32_t qLen = 0;
  28. calculateGroupParamLengths(NLen - 2, securityLevel, &pLen, &qLen);
  29. // Calculate candidate parameters ("p", "q") for the coin commitment group
  30. // using a deterministic process based on "N", the "aux" string, and
  31. // the dedicated string "COMMITMENTGROUP".
  32. params.coinCommitmentGroup = deriveIntegerGroupParams(calculateSeed(N, aux, securityLevel, STRING_COMMIT_GROUP),
  33. pLen, qLen);
  34. // Next, we derive parameters for a second Accumulated Value commitment group.
  35. // This is a Schnorr group with the specific property that the order of the group
  36. // must be exactly equal to "q" from the commitment group. We set
  37. // the modulus of the new group equal to "2q+1" and test to see if this is prime.
  38. params.serialNumberSoKCommitmentGroup = deriveIntegerGroupFromOrder(params.coinCommitmentGroup.modulus);
  39. // Calculate the parameters for the internal commitment
  40. // using the same process.
  41. params.accumulatorParams.accumulatorPoKCommitmentGroup = deriveIntegerGroupParams(calculateSeed(N, aux, securityLevel, STRING_AIC_GROUP),
  42. qLen + 300, qLen + 1);
  43. // Calculate the parameters for the accumulator QRN commitment generators. This isn't really
  44. // a whole group, just a pair of random generators in QR_N.
  45. uint32_t resultCtr;
  46. params.accumulatorParams.accumulatorQRNCommitmentGroup.g = generateIntegerFromSeed(NLen - 1,
  47. calculateSeed(N, aux, securityLevel, STRING_QRNCOMMIT_GROUPG),
  48. &resultCtr).pow_mod(CBigNum(2), N);
  49. params.accumulatorParams.accumulatorQRNCommitmentGroup.h = generateIntegerFromSeed(NLen - 1,
  50. calculateSeed(N, aux, securityLevel, STRING_QRNCOMMIT_GROUPG),
  51. &resultCtr).pow_mod(CBigNum(2), N);
  52. // Calculate the accumulator base, which we calculate as "u = C**2 mod N"
  53. // where C is an arbitrary value. In the unlikely case that "u = 1" we increment
  54. // "C" and repeat.
  55. CBigNum constant(ACCUMULATOR_BASE_CONSTANT);
  56. params.accumulatorParams.accumulatorBase = CBigNum(1);
  57. for (uint32_t count = 0; count < MAX_ACCUMGEN_ATTEMPTS && params.accumulatorParams.accumulatorBase.isOne(); count++) {
  58. params.accumulatorParams.accumulatorBase = constant.pow_mod(CBigNum(2), params.accumulatorParams.accumulatorModulus);
  59. }
  60. // Compute the accumulator range. The upper range is the largest possible coin commitment value.
  61. // The lower range is sqrt(upper range) + 1. Since OpenSSL doesn't have
  62. // a square root function we use a slightly higher approximation.
  63. params.accumulatorParams.maxCoinValue = params.coinCommitmentGroup.modulus;
  64. params.accumulatorParams.minCoinValue = CBigNum(2).pow((params.coinCommitmentGroup.modulus.bitSize() / 2) + 3);
  65. // If all went well, mark params as successfully initialized.
  66. params.accumulatorParams.initialized = true;
  67. // If all went well, mark params as successfully initialized.
  68. params.initialized = true;
  69. }
  70. /// \brief Format a seed string by hashing several values.
  71. /// \param N A CBigNum
  72. /// \param aux An auxiliary string
  73. /// \param securityLevel The security level in bits
  74. /// \param groupName A group description string
  75. /// \throws ZerocoinException if the process fails
  76. ///
  77. /// Returns the hash of the value.
  78. uint256
  79. calculateGeneratorSeed(uint256 seed, uint256 pSeed, uint256 qSeed, string label, uint32_t index, uint32_t count)
  80. {
  81. CHashWriter hasher(0,0);
  82. uint256 hash;
  83. // Compute the hash of:
  84. // <modulus>||<securitylevel>||<auxString>||groupName
  85. hasher << seed;
  86. hasher << string("||");
  87. hasher << pSeed;
  88. hasher << string("||");
  89. hasher << qSeed;
  90. hasher << string("||");
  91. hasher << label;
  92. hasher << string("||");
  93. hasher << index;
  94. hasher << string("||");
  95. hasher << count;
  96. return hasher.GetHash();
  97. }
  98. /// \brief Format a seed string by hashing several values.
  99. /// \param N A CBigNum
  100. /// \param aux An auxiliary string
  101. /// \param securityLevel The security level in bits
  102. /// \param groupName A group description string
  103. /// \throws ZerocoinException if the process fails
  104. ///
  105. /// Returns the hash of the value.
  106. uint256
  107. calculateSeed(CBigNum modulus, string auxString, uint32_t securityLevel, string groupName)
  108. {
  109. CHashWriter hasher(0,0);
  110. uint256 hash;
  111. // Compute the hash of:
  112. // <modulus>||<securitylevel>||<auxString>||groupName
  113. hasher << modulus;
  114. hasher << string("||");
  115. hasher << securityLevel;
  116. hasher << string("||");
  117. hasher << auxString;
  118. hasher << string("||");
  119. hasher << groupName;
  120. return hasher.GetHash();
  121. }
  122. uint256
  123. calculateHash(uint256 input)
  124. {
  125. CHashWriter hasher(0,0);
  126. // Compute the hash of "input"
  127. hasher << input;
  128. return hasher.GetHash();
  129. }
  130. /// \brief Calculate field/group parameter sizes based on a security level.
  131. /// \param maxPLen Maximum size of the field (modulus "p") in bits.
  132. /// \param securityLevel Required security level in bits (at least 80)
  133. /// \param pLen Result: length of "p" in bits
  134. /// \param qLen Result: length of "q" in bits
  135. /// \throws ZerocoinException if the process fails
  136. ///
  137. /// Calculates the appropriate sizes of "p" and "q" for a prime-order
  138. /// subgroup of order "q" embedded within a field "F_p". The sizes
  139. /// are based on a 'securityLevel' provided in symmetric-equivalent
  140. /// bits. Our choices slightly exceed the specs in FIPS 186-3:
  141. ///
  142. /// securityLevel = 80: pLen = 1024, qLen = 256
  143. /// securityLevel = 112: pLen = 2048, qLen = 256
  144. /// securityLevel = 128: qLen = 3072, qLen = 320
  145. ///
  146. /// If the length of "p" exceeds the length provided in "maxPLen", or
  147. /// if "securityLevel < 80" this routine throws an exception.
  148. void
  149. calculateGroupParamLengths(uint32_t maxPLen, uint32_t securityLevel,
  150. uint32_t *pLen, uint32_t *qLen)
  151. {
  152. *pLen = *qLen = 0;
  153. if (securityLevel < 80) {
  154. throw ZerocoinException("Security level must be at least 80 bits.");
  155. } else if (securityLevel == 80) {
  156. *qLen = 256;
  157. *pLen = 1024;
  158. } else if (securityLevel <= 112) {
  159. *qLen = 256;
  160. *pLen = 2048;
  161. } else if (securityLevel <= 128) {
  162. *qLen = 320;
  163. *pLen = 3072;
  164. } else {
  165. throw ZerocoinException("Security level not supported.");
  166. }
  167. if (*pLen > maxPLen) {
  168. throw ZerocoinException("Modulus size is too small for this security level.");
  169. }
  170. }
  171. /// \brief Deterministically compute a set of group parameters using NIST procedures.
  172. /// \param seedStr A byte string seeding the process.
  173. /// \param pLen The desired length of the modulus "p" in bits
  174. /// \param qLen The desired length of the order "q" in bits
  175. /// \return An IntegerGroupParams object
  176. ///
  177. /// Calculates the description of a group G of prime order "q" embedded within
  178. /// a field "F_p". The input to this routine is in arbitrary seed. It uses the
  179. /// algorithms described in FIPS 186-3 Appendix A.1.2 to calculate
  180. /// primes "p" and "q". It uses the procedure in Appendix A.2.3 to
  181. /// derive two generators "g", "h".
  182. IntegerGroupParams
  183. deriveIntegerGroupParams(uint256 seed, uint32_t pLen, uint32_t qLen)
  184. {
  185. IntegerGroupParams result;
  186. CBigNum p;
  187. CBigNum q;
  188. uint256 pSeed, qSeed;
  189. // Calculate "p" and "q" and "domain_parameter_seed" from the
  190. // "seed" buffer above, using the procedure described in NIST
  191. // FIPS 186-3, Appendix A.1.2.
  192. calculateGroupModulusAndOrder(seed, pLen, qLen, result.modulus,
  193. result.groupOrder, &pSeed, &qSeed);
  194. // Calculate the generators "g", "h" using the process described in
  195. // NIST FIPS 186-3, Appendix A.2.3. This algorithm takes ("p", "q",
  196. // "domain_parameter_seed", "index"). We use "index" value 1
  197. // to generate "g" and "index" value 2 to generate "h".
  198. result.g = calculateGroupGenerator(seed, pSeed, qSeed, result.modulus, result.groupOrder, 1);
  199. result.h = calculateGroupGenerator(seed, pSeed, qSeed, result.modulus, result.groupOrder, 2);
  200. // Perform some basic tests to make sure we have good parameters
  201. if ((uint32_t)(result.modulus.bitSize()) < pLen || // modulus is pLen bits long
  202. (uint32_t)(result.groupOrder.bitSize()) < qLen || // order is qLen bits long
  203. !(result.modulus.isPrime()) || // modulus is prime
  204. !(result.groupOrder.isPrime()) || // order is prime
  205. !((result.g.pow_mod(result.groupOrder, result.modulus)).isOne()) || // g^order mod modulus = 1
  206. !((result.h.pow_mod(result.groupOrder, result.modulus)).isOne()) || // h^order mod modulus = 1
  207. ((result.g.pow_mod(CBigNum(100), result.modulus)).isOne()) || // g^100 mod modulus != 1
  208. ((result.h.pow_mod(CBigNum(100), result.modulus)).isOne()) || // h^100 mod modulus != 1
  209. result.g == result.h || // g != h
  210. result.g.isOne()) { // g != 1
  211. // If any of the above tests fail, throw an exception
  212. throw ZerocoinException("Group parameters are not valid");
  213. }
  214. return result;
  215. }
  216. /// \brief Deterministically compute a set of group parameters with a specified order.
  217. /// \param groupOrder The order of the group
  218. /// \return An IntegerGroupParams object
  219. ///
  220. /// Given "q" calculates the description of a group G of prime order "q" embedded within
  221. /// a field "F_p".
  222. IntegerGroupParams
  223. deriveIntegerGroupFromOrder(CBigNum &groupOrder)
  224. {
  225. IntegerGroupParams result;
  226. // Set the order to "groupOrder"
  227. result.groupOrder = groupOrder;
  228. // Try possible values for "modulus" of the form "groupOrder * 2 * i" where
  229. // "p" is prime and i is a counter starting at 1.
  230. for (uint32_t i = 1; i < NUM_SCHNORRGEN_ATTEMPTS; i++) {
  231. // Set modulus equal to "groupOrder * 2 * i"
  232. result.modulus = (result.groupOrder * CBigNum(i*2)) + CBigNum(1);
  233. // Test the result for primality
  234. // TODO: This is a probabilistic routine and thus not the right choice
  235. if (result.modulus.isPrime(256)) {
  236. // Success.
  237. //
  238. // Calculate the generators "g", "h" using the process described in
  239. // NIST FIPS 186-3, Appendix A.2.3. This algorithm takes ("p", "q",
  240. // "domain_parameter_seed", "index"). We use "index" value 1
  241. // to generate "g" and "index" value 2 to generate "h".
  242. uint256 seed = calculateSeed(groupOrder, "", 128, "");
  243. uint256 pSeed = calculateHash(seed);
  244. uint256 qSeed = calculateHash(pSeed);
  245. result.g = calculateGroupGenerator(seed, pSeed, qSeed, result.modulus, result.groupOrder, 1);
  246. result.h = calculateGroupGenerator(seed, pSeed, qSeed, result.modulus, result.groupOrder, 2);
  247. // Perform some basic tests to make sure we have good parameters
  248. if (!(result.modulus.isPrime()) || // modulus is prime
  249. !(result.groupOrder.isPrime()) || // order is prime
  250. !((result.g.pow_mod(result.groupOrder, result.modulus)).isOne()) || // g^order mod modulus = 1
  251. !((result.h.pow_mod(result.groupOrder, result.modulus)).isOne()) || // h^order mod modulus = 1
  252. ((result.g.pow_mod(CBigNum(100), result.modulus)).isOne()) || // g^100 mod modulus != 1
  253. ((result.h.pow_mod(CBigNum(100), result.modulus)).isOne()) || // h^100 mod modulus != 1
  254. result.g == result.h || // g != h
  255. result.g.isOne()) { // g != 1
  256. // If any of the above tests fail, throw an exception
  257. throw ZerocoinException("Group parameters are not valid");
  258. }
  259. return result;
  260. }
  261. }
  262. // If we reached this point group generation has failed. Throw an exception.
  263. throw ZerocoinException("Too many attempts to generate Schnorr group.");
  264. }
  265. /// \brief Deterministically compute a group description using NIST procedures.
  266. /// \param seed A byte string seeding the process.
  267. /// \param pLen The desired length of the modulus "p" in bits
  268. /// \param qLen The desired length of the order "q" in bits
  269. /// \param resultModulus A value "p" describing a finite field "F_p"
  270. /// \param resultGroupOrder A value "q" describing the order of a subgroup
  271. /// \param resultDomainParameterSeed A resulting seed for use in later calculations.
  272. ///
  273. /// Calculates the description of a group G of prime order "q" embedded within
  274. /// a field "F_p". The input to this routine is in arbitrary seed. It uses the
  275. /// algorithms described in FIPS 186-3 Appendix A.1.2 to calculate
  276. /// primes "p" and "q".
  277. void calculateGroupModulusAndOrder(uint256 seed, uint32_t pLen, uint32_t qLen,
  278. CBigNum &resultModulus, CBigNum &resultGroupOrder,
  279. uint256 *resultPseed, uint256 *resultQseed)
  280. {
  281. // Verify that the seed length is >= qLen
  282. if (qLen > (sizeof(seed)) * 8) {
  283. // TODO: The use of 256-bit seeds limits us to 256-bit group orders. We should probably change this.
  284. // throw ZerocoinException("Seed is too short to support the required security level.");
  285. }
  286. #ifdef ZEROCOIN_DEBUG
  287. cout << "calculateGroupModulusAndOrder: pLen = " << pLen << endl;
  288. #endif
  289. // Generate a random prime for the group order.
  290. // This may throw an exception, which we'll pass upwards.
  291. // Result is the value "resultGroupOrder", "qseed" and "qgen_counter".
  292. uint256 qseed;
  293. uint32_t qgen_counter;
  294. resultGroupOrder = generateRandomPrime(qLen, seed, &qseed, &qgen_counter);
  295. // Using ⎡pLen / 2 + 1⎤ as the length and qseed as the input_seed, use the random prime
  296. // routine to obtain p0 , pseed, and pgen_counter. We pass exceptions upward.
  297. uint32_t p0len = ceil((pLen / 2.0) + 1);
  298. uint256 pseed;
  299. uint32_t pgen_counter;
  300. CBigNum p0 = generateRandomPrime(p0len, qseed, &pseed, &pgen_counter);
  301. // Set x = 0, old_counter = pgen_counter
  302. uint32_t old_counter = pgen_counter;
  303. // Generate a random integer "x" of pLen bits
  304. uint32_t iterations;
  305. CBigNum x = generateIntegerFromSeed(pLen, pseed, &iterations);
  306. pseed += (iterations + 1);
  307. // Set x = 2^{pLen−1} + (x mod 2^{pLen–1}).
  308. CBigNum powerOfTwo = CBigNum(2).pow(pLen-1);
  309. x = powerOfTwo + (x % powerOfTwo);
  310. // t = ⎡x / (2 * resultGroupOrder * p0)⎤.
  311. // TODO: we don't have a ceiling function
  312. CBigNum t = x / (CBigNum(2) * resultGroupOrder * p0);
  313. // Now loop until we find a valid prime "p" or we fail due to
  314. // pgen_counter exceeding ((4*pLen) + old_counter).
  315. for ( ; pgen_counter <= ((4*pLen) + old_counter) ; pgen_counter++) {
  316. // If (2 * t * resultGroupOrder * p0 + 1) > 2^{pLen}, then
  317. // t = ⎡2^{pLen−1} / (2 * resultGroupOrder * p0)⎤.
  318. powerOfTwo = CBigNum(2).pow(pLen);
  319. CBigNum prod = (CBigNum(2) * t * resultGroupOrder * p0) + CBigNum(1);
  320. if (prod > powerOfTwo) {
  321. // TODO: implement a ceil function
  322. t = CBigNum(2).pow(pLen-1) / (CBigNum(2) * resultGroupOrder * p0);
  323. }
  324. // Compute a candidate prime resultModulus = 2tqp0 + 1.
  325. resultModulus = (CBigNum(2) * t * resultGroupOrder * p0) + CBigNum(1);
  326. // Verify that resultModulus is prime. First generate a pseudorandom integer "a".
  327. CBigNum a = generateIntegerFromSeed(pLen, pseed, &iterations);
  328. pseed += iterations + 1;
  329. // Set a = 2 + (a mod (resultModulus–3)).
  330. a = CBigNum(2) + (a % (resultModulus - CBigNum(3)));
  331. // Set z = a^{2 * t * resultGroupOrder} mod resultModulus
  332. CBigNum z = a.pow_mod(CBigNum(2) * t * resultGroupOrder, resultModulus);
  333. // If GCD(z–1, resultModulus) == 1 AND (z^{p0} mod resultModulus == 1)
  334. // then we have found our result. Return.
  335. if ((resultModulus.gcd(z - CBigNum(1))).isOne() &&
  336. (z.pow_mod(p0, resultModulus)).isOne()) {
  337. // Success! Return the seeds and primes.
  338. *resultPseed = pseed;
  339. *resultQseed = qseed;
  340. return;
  341. }
  342. // This prime did not work out. Increment "t" and try again.
  343. t = t + CBigNum(1);
  344. } // loop continues until pgen_counter exceeds a limit
  345. // We reach this point only if we exceeded our maximum iteration count.
  346. // Throw an exception.
  347. throw ZerocoinException("Unable to generate a prime modulus for the group");
  348. }
  349. /// \brief Deterministically compute a generator for a given group.
  350. /// \param seed A first seed for the process.
  351. /// \param pSeed A second seed for the process.
  352. /// \param qSeed A third seed for the process.
  353. /// \param modulus Proposed prime modulus for the field.
  354. /// \param groupOrder Proposed order of the group.
  355. /// \param index Index value, selects which generator you're building.
  356. /// \return The resulting generator.
  357. /// \throws A ZerocoinException if error.
  358. ///
  359. /// Generates a random group generator deterministically as a function of (seed,pSeed,qSeed)
  360. /// Uses the algorithm described in FIPS 186-3 Appendix A.2.3.
  361. CBigNum
  362. calculateGroupGenerator(uint256 seed, uint256 pSeed, uint256 qSeed, CBigNum modulus, CBigNum groupOrder, uint32_t index)
  363. {
  364. CBigNum result;
  365. // Verify that 0 <= index < 256
  366. if (index > 255) {
  367. throw ZerocoinException("Invalid index for group generation");
  368. }
  369. // Compute e = (modulus - 1) / groupOrder
  370. CBigNum e = (modulus - CBigNum(1)) / groupOrder;
  371. // Loop until we find a generator
  372. for (uint32_t count = 1; count < MAX_GENERATOR_ATTEMPTS; count++) {
  373. // hash = Hash(seed || pSeed || qSeed || “ggen” || index || count
  374. uint256 hash = calculateGeneratorSeed(seed, pSeed, qSeed, "ggen", index, count);
  375. CBigNum W(hash);
  376. // Compute result = W^e mod p
  377. result = W.pow_mod(e, modulus);
  378. // If result > 1, we have a generator
  379. if (result > 1) {
  380. return result;
  381. }
  382. }
  383. // We only get here if we failed to find a generator
  384. throw ZerocoinException("Unable to find a generator, too many attempts");
  385. }
  386. /// \brief Deterministically compute a random prime number.
  387. /// \param primeBitLen Desired bit length of the prime.
  388. /// \param in_seed Input seed for the process.
  389. /// \param out_seed Result: output seed from the process.
  390. /// \param prime_gen_counter Result: number of iterations required.
  391. /// \return The resulting prime number.
  392. /// \throws A ZerocoinException if error.
  393. ///
  394. /// Generates a random prime number of primeBitLen bits from a given input
  395. /// seed. Uses the Shawe-Taylor algorithm as described in FIPS 186-3
  396. /// Appendix C.6. This is a recursive function.
  397. CBigNum
  398. generateRandomPrime(uint32_t primeBitLen, uint256 in_seed, uint256 *out_seed,
  399. uint32_t *prime_gen_counter)
  400. {
  401. // Verify that primeBitLen is not too small
  402. if (primeBitLen < 2) {
  403. throw ZerocoinException("Prime length is too short");
  404. }
  405. // If primeBitLen < 33 bits, perform the base case.
  406. if (primeBitLen < 33) {
  407. CBigNum result(0);
  408. // Set prime_seed = in_seed, prime_gen_counter = 0.
  409. uint256 prime_seed = in_seed;
  410. (*prime_gen_counter) = 0;
  411. // Loop up to "4 * primeBitLen" iterations.
  412. while ((*prime_gen_counter) < (4 * primeBitLen)) {
  413. // Generate a pseudorandom integer "c" of length primeBitLength bits
  414. uint32_t iteration_count;
  415. CBigNum c = generateIntegerFromSeed(primeBitLen, prime_seed, &iteration_count);
  416. #ifdef ZEROCOIN_DEBUG
  417. cout << "generateRandomPrime: primeBitLen = " << primeBitLen << endl;
  418. cout << "Generated c = " << c << endl;
  419. #endif
  420. prime_seed += (iteration_count + 1);
  421. (*prime_gen_counter)++;
  422. // Set "intc" to be the least odd integer >= "c" we just generated
  423. uint32_t intc = c.getulong();
  424. intc = (2 * floor(intc / 2.0)) + 1;
  425. #ifdef ZEROCOIN_DEBUG
  426. cout << "Should be odd. c = " << intc << endl;
  427. cout << "The big num is: c = " << c << endl;
  428. #endif
  429. // Perform trial division on this (relatively small) integer to determine if "intc"
  430. // is prime. If so, return success.
  431. if (primalityTestByTrialDivision(intc)) {
  432. // Return "intc" converted back into a CBigNum and "prime_seed". We also updated
  433. // the variable "prime_gen_counter" in previous statements.
  434. result = intc;
  435. *out_seed = prime_seed;
  436. // Success
  437. return result;
  438. }
  439. } // while()
  440. // If we reached this point there was an error finding a candidate prime
  441. // so throw an exception.
  442. throw ZerocoinException("Unable to find prime in Shawe-Taylor algorithm");
  443. // END OF BASE CASE
  444. }
  445. // If primeBitLen >= 33 bits, perform the recursive case.
  446. else {
  447. // Recurse to find a new random prime of roughly half the size
  448. uint32_t newLength = ceil((double)primeBitLen / 2.0) + 1;
  449. CBigNum c0 = generateRandomPrime(newLength, in_seed, out_seed, prime_gen_counter);
  450. // Generate a random integer "x" of primeBitLen bits using the output
  451. // of the previous call.
  452. uint32_t numIterations;
  453. CBigNum x = generateIntegerFromSeed(primeBitLen, *out_seed, &numIterations);
  454. (*out_seed) += numIterations + 1;
  455. // Compute "t" = ⎡x / (2 * c0⎤
  456. // TODO no Ceiling call
  457. CBigNum t = x / (CBigNum(2) * c0);
  458. // Repeat the following procedure until we find a prime (or time out)
  459. for (uint32_t testNum = 0; testNum < MAX_PRIMEGEN_ATTEMPTS; testNum++) {
  460. // If ((2 * t * c0) + 1 > 2^{primeBitLen}),
  461. // then t = ⎡2^{primeBitLen} – 1 / (2 * c0)⎤.
  462. if ((CBigNum(2) * t * c0) > (CBigNum(2).pow(CBigNum(primeBitLen)))) {
  463. t = ((CBigNum(2).pow(CBigNum(primeBitLen))) - CBigNum(1)) / (CBigNum(2) * c0);
  464. }
  465. // Set c = (2 * t * c0) + 1
  466. CBigNum c = (CBigNum(2) * t * c0) + CBigNum(1);
  467. // Increment prime_gen_counter
  468. (*prime_gen_counter)++;
  469. // Test "c" for primality as follows:
  470. // 1. First pick an integer "a" in between 2 and (c - 2)
  471. CBigNum a = generateIntegerFromSeed(c.bitSize(), (*out_seed), &numIterations);
  472. a = CBigNum(2) + (a % (c - CBigNum(3)));
  473. (*out_seed) += (numIterations + 1);
  474. // 2. Compute "z" = a^{2*t} mod c
  475. CBigNum z = a.pow_mod(CBigNum(2) * t, c);
  476. // 3. Check if "c" is prime.
  477. // Specifically, verify that gcd((z-1), c) == 1 AND (z^c0 mod c) == 1
  478. // If so we return "c" as our result.
  479. if (c.gcd(z - CBigNum(1)).isOne() && z.pow_mod(c0, c).isOne()) {
  480. // Return "c", out_seed and prime_gen_counter
  481. // (the latter two of which were already updated)
  482. return c;
  483. }
  484. // 4. If the test did not succeed, increment "t" and loop
  485. t = t + CBigNum(1);
  486. } // end of test loop
  487. }
  488. // We only reach this point if the test loop has iterated MAX_PRIMEGEN_ATTEMPTS
  489. // and failed to identify a valid prime. Throw an exception.
  490. throw ZerocoinException("Unable to generate random prime (too many tests)");
  491. }
  492. CBigNum
  493. generateIntegerFromSeed(uint32_t numBits, uint256 seed, uint32_t *numIterations)
  494. {
  495. CBigNum result(0);
  496. uint32_t iterations = ceil((double)numBits / (double)HASH_OUTPUT_BITS);
  497. #ifdef ZEROCOIN_DEBUG
  498. cout << "numBits = " << numBits << endl;
  499. cout << "iterations = " << iterations << endl;
  500. #endif
  501. // Loop "iterations" times filling up the value "result" with random bits
  502. for (uint32_t count = 0; count < iterations; count++) {
  503. // result += ( H(pseed + count) * 2^{count * p0len} )
  504. result += CBigNum(calculateHash(seed + count)) * CBigNum(2).pow(count * HASH_OUTPUT_BITS);
  505. }
  506. result = CBigNum(2).pow(numBits - 1) + (result % (CBigNum(2).pow(numBits - 1)));
  507. // Return the number of iterations and the result
  508. *numIterations = iterations;
  509. return result;
  510. }
  511. /// \brief Determines whether a uint32_t is a prime through trial division.
  512. /// \param candidate Candidate to test.
  513. /// \return true if the value is prime, false otherwise
  514. ///
  515. /// Performs trial division to determine whether a uint32_t is prime.
  516. bool
  517. primalityTestByTrialDivision(uint32_t candidate)
  518. {
  519. CBigNum canBignum(candidate);
  520. return canBignum.isPrime();
  521. }
  522. } // namespace libzerocoin