Bignum generateRandomPrime(uint32_t primeBitLen, uint256 in_seed, uint256 *out_seed, uint32_t *prime_gen_counter) { // Verify that primeBitLen is not too small if (primeBitLen < 2) { throw ZerocoinException("Prime length is too short"); } // If primeBitLen < 33 bits, perform the base case. if (primeBitLen < 33) { Bignum result(0); // Set prime_seed = in_seed, prime_gen_counter = 0. uint256 prime_seed = in_seed; (*prime_gen_counter) = 0; // Loop up to "4 * primeBitLen" iterations. while ((*prime_gen_counter) < (4 * primeBitLen)) { // Generate a pseudorandom integer "c" of length primeBitLength bits uint32_t iteration_count; Bignum c = generateIntegerFromSeed(primeBitLen, prime_seed, &iteration_count); #ifdef ZEROCOIN_DEBUG cout << "generateRandomPrime: primeBitLen = " << primeBitLen << endl; cout << "Generated c = " << c << endl; #endif prime_seed += (iteration_count + 1); (*prime_gen_counter)++; // Set "intc" to be the least odd integer >= "c" we just generated uint32_t intc = c.getulong(); intc = (2 * floor(intc / 2.0)) + 1; #ifdef ZEROCOIN_DEBUG cout << "Should be odd. c = " << intc << endl; cout << "The big num is: c = " << c << endl; #endif // Perform trial division on this (relatively small) integer to determine if "intc" // is prime. If so, return success. if (primalityTestByTrialDivision(intc)) { // Return "intc" converted back into a Bignum and "prime_seed". We also updated // the variable "prime_gen_counter" in previous statements. result = intc; *out_seed = prime_seed; // Success return result; } } // while() // If we reached this point there was an error finding a candidate prime // so throw an exception. throw ZerocoinException("Unable to find prime in Shawe-Taylor algorithm"); // END OF BASE CASE } // If primeBitLen >= 33 bits, perform the recursive case. else { // Recurse to find a new random prime of roughly half the size uint32_t newLength = ceil((double)primeBitLen / 2.0) + 1; Bignum c0 = generateRandomPrime(newLength, in_seed, out_seed, prime_gen_counter); // Generate a random integer "x" of primeBitLen bits using the output // of the previous call. uint32_t numIterations; Bignum x = generateIntegerFromSeed(primeBitLen, *out_seed, &numIterations); (*out_seed) += numIterations + 1; // Compute "t" = ⎡x / (2 * c0⎤ // TODO no Ceiling call Bignum t = x / (Bignum(2) * c0); // Repeat the following procedure until we find a prime (or time out) for (uint32_t testNum = 0; testNum < MAX_PRIMEGEN_ATTEMPTS; testNum++) { // If ((2 * t * c0) + 1 > 2^{primeBitLen}), // then t = ⎡2^{primeBitLen} – 1 / (2 * c0)⎤. if ((Bignum(2) * t * c0) > (Bignum(2).pow(Bignum(primeBitLen)))) { t = ((Bignum(2).pow(Bignum(primeBitLen))) - Bignum(1)) / (Bignum(2) * c0); } // Set c = (2 * t * c0) + 1 Bignum c = (Bignum(2) * t * c0) + Bignum(1); // Increment prime_gen_counter (*prime_gen_counter)++; // Test "c" for primality as follows: // 1. First pick an integer "a" in between 2 and (c - 2) Bignum a = generateIntegerFromSeed(c.bitSize(), (*out_seed), &numIterations); a = Bignum(2) + (a % (c - Bignum(3))); (*out_seed) += (numIterations + 1); // 2. Compute "z" = a^{2*t} mod c Bignum z = a.pow_mod(Bignum(2) * t, c); // 3. Check if "c" is prime. // Specifically, verify that gcd((z-1), c) == 1 AND (z^c0 mod c) == 1 // If so we return "c" as our result. if (c.gcd(z - Bignum(1)).isOne() && z.pow_mod(c0, c).isOne()) { // Return "c", out_seed and prime_gen_counter // (the latter two of which were already updated) return c; } // 4. If the test did not succeed, increment "t" and loop t = t + Bignum(1); } // end of test loop } // We only reach this point if the test loop has iterated MAX_PRIMEGEN_ATTEMPTS // and failed to identify a valid prime. Throw an exception. throw ZerocoinException("Unable to generate random prime (too many tests)"); }