|
@@ -1,14 +1,4 @@
|
|
-// ECOin - Copyright (c) - 2014/2021 - GPLv3 - epsylon@riseup.net (https://03c8.net)
|
|
|
|
-/// \file ParamGeneration.cpp
|
|
|
|
-///
|
|
|
|
-/// \brief Parameter manipulation routines for the Zerocoin cryptographic
|
|
|
|
-/// components.
|
|
|
|
-///
|
|
|
|
-/// \author Ian Miers, Christina Garman and Matthew Green
|
|
|
|
-/// \date June 2013
|
|
|
|
-///
|
|
|
|
-/// \copyright Copyright 2013 Ian Miers, Christina Garman and Matthew Green
|
|
|
|
-/// \license This project is released under the MIT license.
|
|
|
|
|
|
+// ECOin - Copyright (c) - 2014/2022 - GPLv3 - epsylon@riseup.net (https://03c8.net)
|
|
|
|
|
|
#include <string>
|
|
#include <string>
|
|
#include "Zerocoin.h"
|
|
#include "Zerocoin.h"
|
|
@@ -17,26 +7,8 @@ using namespace std;
|
|
|
|
|
|
namespace libzerocoin {
|
|
namespace libzerocoin {
|
|
|
|
|
|
-/// \brief Fill in a set of Zerocoin parameters from a modulus "N".
|
|
|
|
-/// \param N A trusted RSA modulus
|
|
|
|
-/// \param aux An optional auxiliary string used in derivation
|
|
|
|
-/// \param securityLevel A security level
|
|
|
|
-///
|
|
|
|
-/// \throws ZerocoinException if the process fails
|
|
|
|
-///
|
|
|
|
-/// Fills in a ZC_Params data structure deterministically from
|
|
|
|
-/// a trustworthy RSA modulus "N", which is provided as a Bignum.
|
|
|
|
-///
|
|
|
|
-/// Note: this routine makes the fundamental assumption that "N"
|
|
|
|
-/// encodes a valid RSA-style modulus of the form "e1*e2" for some
|
|
|
|
-/// unknown safe primes "e1" and "e2". These factors must not
|
|
|
|
-/// be known to any party, or the security of Zerocoin is
|
|
|
|
-/// compromised. The integer "N" must be a MINIMUM of 1023
|
|
|
|
-/// in length, and 3072 bits is strongly recommended.
|
|
|
|
-///
|
|
|
|
-
|
|
|
|
void
|
|
void
|
|
-CalculateParams(Params ¶ms, Bignum N, string aux, uint32_t securityLevel)
|
|
|
|
|
|
+CalculateParams(Params ¶ms, CBigNum N, string aux, uint32_t securityLevel)
|
|
{
|
|
{
|
|
params.initialized = false;
|
|
params.initialized = false;
|
|
params.accumulatorParams.initialized = false;
|
|
params.accumulatorParams.initialized = false;
|
|
@@ -85,25 +57,25 @@ CalculateParams(Params ¶ms, Bignum N, string aux, uint32_t securityLevel)
|
|
uint32_t resultCtr;
|
|
uint32_t resultCtr;
|
|
params.accumulatorParams.accumulatorQRNCommitmentGroup.g = generateIntegerFromSeed(NLen - 1,
|
|
params.accumulatorParams.accumulatorQRNCommitmentGroup.g = generateIntegerFromSeed(NLen - 1,
|
|
calculateSeed(N, aux, securityLevel, STRING_QRNCOMMIT_GROUPG),
|
|
calculateSeed(N, aux, securityLevel, STRING_QRNCOMMIT_GROUPG),
|
|
- &resultCtr).pow_mod(Bignum(2), N);
|
|
|
|
|
|
+ &resultCtr).pow_mod(CBigNum(2), N);
|
|
params.accumulatorParams.accumulatorQRNCommitmentGroup.h = generateIntegerFromSeed(NLen - 1,
|
|
params.accumulatorParams.accumulatorQRNCommitmentGroup.h = generateIntegerFromSeed(NLen - 1,
|
|
calculateSeed(N, aux, securityLevel, STRING_QRNCOMMIT_GROUPG),
|
|
calculateSeed(N, aux, securityLevel, STRING_QRNCOMMIT_GROUPG),
|
|
- &resultCtr).pow_mod(Bignum(2), N);
|
|
|
|
|
|
+ &resultCtr).pow_mod(CBigNum(2), N);
|
|
|
|
|
|
// Calculate the accumulator base, which we calculate as "u = C**2 mod N"
|
|
// Calculate the accumulator base, which we calculate as "u = C**2 mod N"
|
|
// where C is an arbitrary value. In the unlikely case that "u = 1" we increment
|
|
// where C is an arbitrary value. In the unlikely case that "u = 1" we increment
|
|
// "C" and repeat.
|
|
// "C" and repeat.
|
|
- Bignum constant(ACCUMULATOR_BASE_CONSTANT);
|
|
|
|
- params.accumulatorParams.accumulatorBase = Bignum(1);
|
|
|
|
|
|
+ CBigNum constant(ACCUMULATOR_BASE_CONSTANT);
|
|
|
|
+ params.accumulatorParams.accumulatorBase = CBigNum(1);
|
|
for (uint32_t count = 0; count < MAX_ACCUMGEN_ATTEMPTS && params.accumulatorParams.accumulatorBase.isOne(); count++) {
|
|
for (uint32_t count = 0; count < MAX_ACCUMGEN_ATTEMPTS && params.accumulatorParams.accumulatorBase.isOne(); count++) {
|
|
- params.accumulatorParams.accumulatorBase = constant.pow_mod(Bignum(2), params.accumulatorParams.accumulatorModulus);
|
|
|
|
|
|
+ params.accumulatorParams.accumulatorBase = constant.pow_mod(CBigNum(2), params.accumulatorParams.accumulatorModulus);
|
|
}
|
|
}
|
|
|
|
|
|
// Compute the accumulator range. The upper range is the largest possible coin commitment value.
|
|
// Compute the accumulator range. The upper range is the largest possible coin commitment value.
|
|
// The lower range is sqrt(upper range) + 1. Since OpenSSL doesn't have
|
|
// The lower range is sqrt(upper range) + 1. Since OpenSSL doesn't have
|
|
// a square root function we use a slightly higher approximation.
|
|
// a square root function we use a slightly higher approximation.
|
|
params.accumulatorParams.maxCoinValue = params.coinCommitmentGroup.modulus;
|
|
params.accumulatorParams.maxCoinValue = params.coinCommitmentGroup.modulus;
|
|
- params.accumulatorParams.minCoinValue = Bignum(2).pow((params.coinCommitmentGroup.modulus.bitSize() / 2) + 3);
|
|
|
|
|
|
+ params.accumulatorParams.minCoinValue = CBigNum(2).pow((params.coinCommitmentGroup.modulus.bitSize() / 2) + 3);
|
|
|
|
|
|
// If all went well, mark params as successfully initialized.
|
|
// If all went well, mark params as successfully initialized.
|
|
params.accumulatorParams.initialized = true;
|
|
params.accumulatorParams.initialized = true;
|
|
@@ -113,7 +85,7 @@ CalculateParams(Params ¶ms, Bignum N, string aux, uint32_t securityLevel)
|
|
}
|
|
}
|
|
|
|
|
|
/// \brief Format a seed string by hashing several values.
|
|
/// \brief Format a seed string by hashing several values.
|
|
-/// \param N A Bignum
|
|
|
|
|
|
+/// \param N A CBigNum
|
|
/// \param aux An auxiliary string
|
|
/// \param aux An auxiliary string
|
|
/// \param securityLevel The security level in bits
|
|
/// \param securityLevel The security level in bits
|
|
/// \param groupName A group description string
|
|
/// \param groupName A group description string
|
|
@@ -145,7 +117,7 @@ calculateGeneratorSeed(uint256 seed, uint256 pSeed, uint256 qSeed, string label,
|
|
}
|
|
}
|
|
|
|
|
|
/// \brief Format a seed string by hashing several values.
|
|
/// \brief Format a seed string by hashing several values.
|
|
-/// \param N A Bignum
|
|
|
|
|
|
+/// \param N A CBigNum
|
|
/// \param aux An auxiliary string
|
|
/// \param aux An auxiliary string
|
|
/// \param securityLevel The security level in bits
|
|
/// \param securityLevel The security level in bits
|
|
/// \param groupName A group description string
|
|
/// \param groupName A group description string
|
|
@@ -154,7 +126,7 @@ calculateGeneratorSeed(uint256 seed, uint256 pSeed, uint256 qSeed, string label,
|
|
/// Returns the hash of the value.
|
|
/// Returns the hash of the value.
|
|
|
|
|
|
uint256
|
|
uint256
|
|
-calculateSeed(Bignum modulus, string auxString, uint32_t securityLevel, string groupName)
|
|
|
|
|
|
+calculateSeed(CBigNum modulus, string auxString, uint32_t securityLevel, string groupName)
|
|
{
|
|
{
|
|
CHashWriter hasher(0,0);
|
|
CHashWriter hasher(0,0);
|
|
uint256 hash;
|
|
uint256 hash;
|
|
@@ -244,15 +216,15 @@ IntegerGroupParams
|
|
deriveIntegerGroupParams(uint256 seed, uint32_t pLen, uint32_t qLen)
|
|
deriveIntegerGroupParams(uint256 seed, uint32_t pLen, uint32_t qLen)
|
|
{
|
|
{
|
|
IntegerGroupParams result;
|
|
IntegerGroupParams result;
|
|
- Bignum p;
|
|
|
|
- Bignum q;
|
|
|
|
|
|
+ CBigNum p;
|
|
|
|
+ CBigNum q;
|
|
uint256 pSeed, qSeed;
|
|
uint256 pSeed, qSeed;
|
|
|
|
|
|
// Calculate "p" and "q" and "domain_parameter_seed" from the
|
|
// Calculate "p" and "q" and "domain_parameter_seed" from the
|
|
// "seed" buffer above, using the procedure described in NIST
|
|
// "seed" buffer above, using the procedure described in NIST
|
|
// FIPS 186-3, Appendix A.1.2.
|
|
// FIPS 186-3, Appendix A.1.2.
|
|
- calculateGroupModulusAndOrder(seed, pLen, qLen, &(result.modulus),
|
|
|
|
- &(result.groupOrder), &pSeed, &qSeed);
|
|
|
|
|
|
+ calculateGroupModulusAndOrder(seed, pLen, qLen, result.modulus,
|
|
|
|
+ result.groupOrder, &pSeed, &qSeed);
|
|
|
|
|
|
// Calculate the generators "g", "h" using the process described in
|
|
// Calculate the generators "g", "h" using the process described in
|
|
// NIST FIPS 186-3, Appendix A.2.3. This algorithm takes ("p", "q",
|
|
// NIST FIPS 186-3, Appendix A.2.3. This algorithm takes ("p", "q",
|
|
@@ -268,8 +240,8 @@ deriveIntegerGroupParams(uint256 seed, uint32_t pLen, uint32_t qLen)
|
|
!(result.groupOrder.isPrime()) || // order is prime
|
|
!(result.groupOrder.isPrime()) || // order is prime
|
|
!((result.g.pow_mod(result.groupOrder, result.modulus)).isOne()) || // g^order mod modulus = 1
|
|
!((result.g.pow_mod(result.groupOrder, result.modulus)).isOne()) || // g^order mod modulus = 1
|
|
!((result.h.pow_mod(result.groupOrder, result.modulus)).isOne()) || // h^order mod modulus = 1
|
|
!((result.h.pow_mod(result.groupOrder, result.modulus)).isOne()) || // h^order mod modulus = 1
|
|
- ((result.g.pow_mod(Bignum(100), result.modulus)).isOne()) || // g^100 mod modulus != 1
|
|
|
|
- ((result.h.pow_mod(Bignum(100), result.modulus)).isOne()) || // h^100 mod modulus != 1
|
|
|
|
|
|
+ ((result.g.pow_mod(CBigNum(100), result.modulus)).isOne()) || // g^100 mod modulus != 1
|
|
|
|
+ ((result.h.pow_mod(CBigNum(100), result.modulus)).isOne()) || // h^100 mod modulus != 1
|
|
result.g == result.h || // g != h
|
|
result.g == result.h || // g != h
|
|
result.g.isOne()) { // g != 1
|
|
result.g.isOne()) { // g != 1
|
|
// If any of the above tests fail, throw an exception
|
|
// If any of the above tests fail, throw an exception
|
|
@@ -287,7 +259,7 @@ deriveIntegerGroupParams(uint256 seed, uint32_t pLen, uint32_t qLen)
|
|
/// a field "F_p".
|
|
/// a field "F_p".
|
|
|
|
|
|
IntegerGroupParams
|
|
IntegerGroupParams
|
|
-deriveIntegerGroupFromOrder(Bignum &groupOrder)
|
|
|
|
|
|
+deriveIntegerGroupFromOrder(CBigNum &groupOrder)
|
|
{
|
|
{
|
|
IntegerGroupParams result;
|
|
IntegerGroupParams result;
|
|
|
|
|
|
@@ -298,7 +270,7 @@ deriveIntegerGroupFromOrder(Bignum &groupOrder)
|
|
// "p" is prime and i is a counter starting at 1.
|
|
// "p" is prime and i is a counter starting at 1.
|
|
for (uint32_t i = 1; i < NUM_SCHNORRGEN_ATTEMPTS; i++) {
|
|
for (uint32_t i = 1; i < NUM_SCHNORRGEN_ATTEMPTS; i++) {
|
|
// Set modulus equal to "groupOrder * 2 * i"
|
|
// Set modulus equal to "groupOrder * 2 * i"
|
|
- result.modulus = (result.groupOrder * Bignum(i*2)) + Bignum(1);
|
|
|
|
|
|
+ result.modulus = (result.groupOrder * CBigNum(i*2)) + CBigNum(1);
|
|
|
|
|
|
// Test the result for primality
|
|
// Test the result for primality
|
|
// TODO: This is a probabilistic routine and thus not the right choice
|
|
// TODO: This is a probabilistic routine and thus not the right choice
|
|
@@ -321,8 +293,8 @@ deriveIntegerGroupFromOrder(Bignum &groupOrder)
|
|
!(result.groupOrder.isPrime()) || // order is prime
|
|
!(result.groupOrder.isPrime()) || // order is prime
|
|
!((result.g.pow_mod(result.groupOrder, result.modulus)).isOne()) || // g^order mod modulus = 1
|
|
!((result.g.pow_mod(result.groupOrder, result.modulus)).isOne()) || // g^order mod modulus = 1
|
|
!((result.h.pow_mod(result.groupOrder, result.modulus)).isOne()) || // h^order mod modulus = 1
|
|
!((result.h.pow_mod(result.groupOrder, result.modulus)).isOne()) || // h^order mod modulus = 1
|
|
- ((result.g.pow_mod(Bignum(100), result.modulus)).isOne()) || // g^100 mod modulus != 1
|
|
|
|
- ((result.h.pow_mod(Bignum(100), result.modulus)).isOne()) || // h^100 mod modulus != 1
|
|
|
|
|
|
+ ((result.g.pow_mod(CBigNum(100), result.modulus)).isOne()) || // g^100 mod modulus != 1
|
|
|
|
+ ((result.h.pow_mod(CBigNum(100), result.modulus)).isOne()) || // h^100 mod modulus != 1
|
|
result.g == result.h || // g != h
|
|
result.g == result.h || // g != h
|
|
result.g.isOne()) { // g != 1
|
|
result.g.isOne()) { // g != 1
|
|
// If any of the above tests fail, throw an exception
|
|
// If any of the above tests fail, throw an exception
|
|
@@ -350,9 +322,8 @@ deriveIntegerGroupFromOrder(Bignum &groupOrder)
|
|
/// algorithms described in FIPS 186-3 Appendix A.1.2 to calculate
|
|
/// algorithms described in FIPS 186-3 Appendix A.1.2 to calculate
|
|
/// primes "p" and "q".
|
|
/// primes "p" and "q".
|
|
|
|
|
|
-void
|
|
|
|
-calculateGroupModulusAndOrder(uint256 seed, uint32_t pLen, uint32_t qLen,
|
|
|
|
- Bignum *resultModulus, Bignum *resultGroupOrder,
|
|
|
|
|
|
+void calculateGroupModulusAndOrder(uint256 seed, uint32_t pLen, uint32_t qLen,
|
|
|
|
+ CBigNum &resultModulus, CBigNum &resultGroupOrder,
|
|
uint256 *resultPseed, uint256 *resultQseed)
|
|
uint256 *resultPseed, uint256 *resultQseed)
|
|
{
|
|
{
|
|
// Verify that the seed length is >= qLen
|
|
// Verify that the seed length is >= qLen
|
|
@@ -370,60 +341,60 @@ calculateGroupModulusAndOrder(uint256 seed, uint32_t pLen, uint32_t qLen,
|
|
// Result is the value "resultGroupOrder", "qseed" and "qgen_counter".
|
|
// Result is the value "resultGroupOrder", "qseed" and "qgen_counter".
|
|
uint256 qseed;
|
|
uint256 qseed;
|
|
uint32_t qgen_counter;
|
|
uint32_t qgen_counter;
|
|
- *resultGroupOrder = generateRandomPrime(qLen, seed, &qseed, &qgen_counter);
|
|
|
|
|
|
+ resultGroupOrder = generateRandomPrime(qLen, seed, &qseed, &qgen_counter);
|
|
|
|
|
|
// Using ⎡pLen / 2 + 1⎤ as the length and qseed as the input_seed, use the random prime
|
|
// Using ⎡pLen / 2 + 1⎤ as the length and qseed as the input_seed, use the random prime
|
|
// routine to obtain p0 , pseed, and pgen_counter. We pass exceptions upward.
|
|
// routine to obtain p0 , pseed, and pgen_counter. We pass exceptions upward.
|
|
uint32_t p0len = ceil((pLen / 2.0) + 1);
|
|
uint32_t p0len = ceil((pLen / 2.0) + 1);
|
|
uint256 pseed;
|
|
uint256 pseed;
|
|
uint32_t pgen_counter;
|
|
uint32_t pgen_counter;
|
|
- Bignum p0 = generateRandomPrime(p0len, qseed, &pseed, &pgen_counter);
|
|
|
|
|
|
+ CBigNum p0 = generateRandomPrime(p0len, qseed, &pseed, &pgen_counter);
|
|
|
|
|
|
// Set x = 0, old_counter = pgen_counter
|
|
// Set x = 0, old_counter = pgen_counter
|
|
uint32_t old_counter = pgen_counter;
|
|
uint32_t old_counter = pgen_counter;
|
|
|
|
|
|
// Generate a random integer "x" of pLen bits
|
|
// Generate a random integer "x" of pLen bits
|
|
uint32_t iterations;
|
|
uint32_t iterations;
|
|
- Bignum x = generateIntegerFromSeed(pLen, pseed, &iterations);
|
|
|
|
|
|
+ CBigNum x = generateIntegerFromSeed(pLen, pseed, &iterations);
|
|
pseed += (iterations + 1);
|
|
pseed += (iterations + 1);
|
|
|
|
|
|
// Set x = 2^{pLen−1} + (x mod 2^{pLen–1}).
|
|
// Set x = 2^{pLen−1} + (x mod 2^{pLen–1}).
|
|
- Bignum powerOfTwo = Bignum(2).pow(pLen-1);
|
|
|
|
|
|
+ CBigNum powerOfTwo = CBigNum(2).pow(pLen-1);
|
|
x = powerOfTwo + (x % powerOfTwo);
|
|
x = powerOfTwo + (x % powerOfTwo);
|
|
|
|
|
|
// t = ⎡x / (2 * resultGroupOrder * p0)⎤.
|
|
// t = ⎡x / (2 * resultGroupOrder * p0)⎤.
|
|
// TODO: we don't have a ceiling function
|
|
// TODO: we don't have a ceiling function
|
|
- Bignum t = x / (Bignum(2) * (*resultGroupOrder) * p0);
|
|
|
|
|
|
+ CBigNum t = x / (CBigNum(2) * resultGroupOrder * p0);
|
|
|
|
|
|
// Now loop until we find a valid prime "p" or we fail due to
|
|
// Now loop until we find a valid prime "p" or we fail due to
|
|
// pgen_counter exceeding ((4*pLen) + old_counter).
|
|
// pgen_counter exceeding ((4*pLen) + old_counter).
|
|
for ( ; pgen_counter <= ((4*pLen) + old_counter) ; pgen_counter++) {
|
|
for ( ; pgen_counter <= ((4*pLen) + old_counter) ; pgen_counter++) {
|
|
// If (2 * t * resultGroupOrder * p0 + 1) > 2^{pLen}, then
|
|
// If (2 * t * resultGroupOrder * p0 + 1) > 2^{pLen}, then
|
|
// t = ⎡2^{pLen−1} / (2 * resultGroupOrder * p0)⎤.
|
|
// t = ⎡2^{pLen−1} / (2 * resultGroupOrder * p0)⎤.
|
|
- powerOfTwo = Bignum(2).pow(pLen);
|
|
|
|
- Bignum prod = (Bignum(2) * t * (*resultGroupOrder) * p0) + Bignum(1);
|
|
|
|
|
|
+ powerOfTwo = CBigNum(2).pow(pLen);
|
|
|
|
+ CBigNum prod = (CBigNum(2) * t * resultGroupOrder * p0) + CBigNum(1);
|
|
if (prod > powerOfTwo) {
|
|
if (prod > powerOfTwo) {
|
|
// TODO: implement a ceil function
|
|
// TODO: implement a ceil function
|
|
- t = Bignum(2).pow(pLen-1) / (Bignum(2) * (*resultGroupOrder) * p0);
|
|
|
|
|
|
+ t = CBigNum(2).pow(pLen-1) / (CBigNum(2) * resultGroupOrder * p0);
|
|
}
|
|
}
|
|
|
|
|
|
// Compute a candidate prime resultModulus = 2tqp0 + 1.
|
|
// Compute a candidate prime resultModulus = 2tqp0 + 1.
|
|
- *resultModulus = (Bignum(2) * t * (*resultGroupOrder) * p0) + Bignum(1);
|
|
|
|
|
|
+ resultModulus = (CBigNum(2) * t * resultGroupOrder * p0) + CBigNum(1);
|
|
|
|
|
|
// Verify that resultModulus is prime. First generate a pseudorandom integer "a".
|
|
// Verify that resultModulus is prime. First generate a pseudorandom integer "a".
|
|
- Bignum a = generateIntegerFromSeed(pLen, pseed, &iterations);
|
|
|
|
|
|
+ CBigNum a = generateIntegerFromSeed(pLen, pseed, &iterations);
|
|
pseed += iterations + 1;
|
|
pseed += iterations + 1;
|
|
|
|
|
|
// Set a = 2 + (a mod (resultModulus–3)).
|
|
// Set a = 2 + (a mod (resultModulus–3)).
|
|
- a = Bignum(2) + (a % ((*resultModulus) - Bignum(3)));
|
|
|
|
|
|
+ a = CBigNum(2) + (a % (resultModulus - CBigNum(3)));
|
|
|
|
|
|
// Set z = a^{2 * t * resultGroupOrder} mod resultModulus
|
|
// Set z = a^{2 * t * resultGroupOrder} mod resultModulus
|
|
- Bignum z = a.pow_mod(Bignum(2) * t * (*resultGroupOrder), (*resultModulus));
|
|
|
|
|
|
+ CBigNum z = a.pow_mod(CBigNum(2) * t * resultGroupOrder, resultModulus);
|
|
|
|
|
|
// If GCD(z–1, resultModulus) == 1 AND (z^{p0} mod resultModulus == 1)
|
|
// If GCD(z–1, resultModulus) == 1 AND (z^{p0} mod resultModulus == 1)
|
|
// then we have found our result. Return.
|
|
// then we have found our result. Return.
|
|
- if ((resultModulus->gcd(z - Bignum(1))).isOne() &&
|
|
|
|
- (z.pow_mod(p0, (*resultModulus))).isOne()) {
|
|
|
|
|
|
+ if ((resultModulus.gcd(z - CBigNum(1))).isOne() &&
|
|
|
|
+ (z.pow_mod(p0, resultModulus)).isOne()) {
|
|
// Success! Return the seeds and primes.
|
|
// Success! Return the seeds and primes.
|
|
*resultPseed = pseed;
|
|
*resultPseed = pseed;
|
|
*resultQseed = qseed;
|
|
*resultQseed = qseed;
|
|
@@ -431,7 +402,7 @@ calculateGroupModulusAndOrder(uint256 seed, uint32_t pLen, uint32_t qLen,
|
|
}
|
|
}
|
|
|
|
|
|
// This prime did not work out. Increment "t" and try again.
|
|
// This prime did not work out. Increment "t" and try again.
|
|
- t = t + Bignum(1);
|
|
|
|
|
|
+ t = t + CBigNum(1);
|
|
} // loop continues until pgen_counter exceeds a limit
|
|
} // loop continues until pgen_counter exceeds a limit
|
|
|
|
|
|
// We reach this point only if we exceeded our maximum iteration count.
|
|
// We reach this point only if we exceeded our maximum iteration count.
|
|
@@ -452,10 +423,10 @@ calculateGroupModulusAndOrder(uint256 seed, uint32_t pLen, uint32_t qLen,
|
|
/// Generates a random group generator deterministically as a function of (seed,pSeed,qSeed)
|
|
/// Generates a random group generator deterministically as a function of (seed,pSeed,qSeed)
|
|
/// Uses the algorithm described in FIPS 186-3 Appendix A.2.3.
|
|
/// Uses the algorithm described in FIPS 186-3 Appendix A.2.3.
|
|
|
|
|
|
-Bignum
|
|
|
|
-calculateGroupGenerator(uint256 seed, uint256 pSeed, uint256 qSeed, Bignum modulus, Bignum groupOrder, uint32_t index)
|
|
|
|
|
|
+CBigNum
|
|
|
|
+calculateGroupGenerator(uint256 seed, uint256 pSeed, uint256 qSeed, CBigNum modulus, CBigNum groupOrder, uint32_t index)
|
|
{
|
|
{
|
|
- Bignum result;
|
|
|
|
|
|
+ CBigNum result;
|
|
|
|
|
|
// Verify that 0 <= index < 256
|
|
// Verify that 0 <= index < 256
|
|
if (index > 255) {
|
|
if (index > 255) {
|
|
@@ -463,13 +434,13 @@ calculateGroupGenerator(uint256 seed, uint256 pSeed, uint256 qSeed, Bignum modul
|
|
}
|
|
}
|
|
|
|
|
|
// Compute e = (modulus - 1) / groupOrder
|
|
// Compute e = (modulus - 1) / groupOrder
|
|
- Bignum e = (modulus - Bignum(1)) / groupOrder;
|
|
|
|
|
|
+ CBigNum e = (modulus - CBigNum(1)) / groupOrder;
|
|
|
|
|
|
// Loop until we find a generator
|
|
// Loop until we find a generator
|
|
for (uint32_t count = 1; count < MAX_GENERATOR_ATTEMPTS; count++) {
|
|
for (uint32_t count = 1; count < MAX_GENERATOR_ATTEMPTS; count++) {
|
|
// hash = Hash(seed || pSeed || qSeed || “ggen” || index || count
|
|
// hash = Hash(seed || pSeed || qSeed || “ggen” || index || count
|
|
uint256 hash = calculateGeneratorSeed(seed, pSeed, qSeed, "ggen", index, count);
|
|
uint256 hash = calculateGeneratorSeed(seed, pSeed, qSeed, "ggen", index, count);
|
|
- Bignum W(hash);
|
|
|
|
|
|
+ CBigNum W(hash);
|
|
|
|
|
|
// Compute result = W^e mod p
|
|
// Compute result = W^e mod p
|
|
result = W.pow_mod(e, modulus);
|
|
result = W.pow_mod(e, modulus);
|
|
@@ -496,7 +467,7 @@ calculateGroupGenerator(uint256 seed, uint256 pSeed, uint256 qSeed, Bignum modul
|
|
/// seed. Uses the Shawe-Taylor algorithm as described in FIPS 186-3
|
|
/// seed. Uses the Shawe-Taylor algorithm as described in FIPS 186-3
|
|
/// Appendix C.6. This is a recursive function.
|
|
/// Appendix C.6. This is a recursive function.
|
|
|
|
|
|
-Bignum
|
|
|
|
|
|
+CBigNum
|
|
generateRandomPrime(uint32_t primeBitLen, uint256 in_seed, uint256 *out_seed,
|
|
generateRandomPrime(uint32_t primeBitLen, uint256 in_seed, uint256 *out_seed,
|
|
uint32_t *prime_gen_counter)
|
|
uint32_t *prime_gen_counter)
|
|
{
|
|
{
|
|
@@ -507,7 +478,7 @@ generateRandomPrime(uint32_t primeBitLen, uint256 in_seed, uint256 *out_seed,
|
|
|
|
|
|
// If primeBitLen < 33 bits, perform the base case.
|
|
// If primeBitLen < 33 bits, perform the base case.
|
|
if (primeBitLen < 33) {
|
|
if (primeBitLen < 33) {
|
|
- Bignum result(0);
|
|
|
|
|
|
+ CBigNum result(0);
|
|
|
|
|
|
// Set prime_seed = in_seed, prime_gen_counter = 0.
|
|
// Set prime_seed = in_seed, prime_gen_counter = 0.
|
|
uint256 prime_seed = in_seed;
|
|
uint256 prime_seed = in_seed;
|
|
@@ -518,7 +489,7 @@ generateRandomPrime(uint32_t primeBitLen, uint256 in_seed, uint256 *out_seed,
|
|
|
|
|
|
// Generate a pseudorandom integer "c" of length primeBitLength bits
|
|
// Generate a pseudorandom integer "c" of length primeBitLength bits
|
|
uint32_t iteration_count;
|
|
uint32_t iteration_count;
|
|
- Bignum c = generateIntegerFromSeed(primeBitLen, prime_seed, &iteration_count);
|
|
|
|
|
|
+ CBigNum c = generateIntegerFromSeed(primeBitLen, prime_seed, &iteration_count);
|
|
#ifdef ZEROCOIN_DEBUG
|
|
#ifdef ZEROCOIN_DEBUG
|
|
cout << "generateRandomPrime: primeBitLen = " << primeBitLen << endl;
|
|
cout << "generateRandomPrime: primeBitLen = " << primeBitLen << endl;
|
|
cout << "Generated c = " << c << endl;
|
|
cout << "Generated c = " << c << endl;
|
|
@@ -538,7 +509,7 @@ generateRandomPrime(uint32_t primeBitLen, uint256 in_seed, uint256 *out_seed,
|
|
// Perform trial division on this (relatively small) integer to determine if "intc"
|
|
// Perform trial division on this (relatively small) integer to determine if "intc"
|
|
// is prime. If so, return success.
|
|
// is prime. If so, return success.
|
|
if (primalityTestByTrialDivision(intc)) {
|
|
if (primalityTestByTrialDivision(intc)) {
|
|
- // Return "intc" converted back into a Bignum and "prime_seed". We also updated
|
|
|
|
|
|
+ // Return "intc" converted back into a CBigNum and "prime_seed". We also updated
|
|
// the variable "prime_gen_counter" in previous statements.
|
|
// the variable "prime_gen_counter" in previous statements.
|
|
result = intc;
|
|
result = intc;
|
|
*out_seed = prime_seed;
|
|
*out_seed = prime_seed;
|
|
@@ -558,53 +529,53 @@ generateRandomPrime(uint32_t primeBitLen, uint256 in_seed, uint256 *out_seed,
|
|
else {
|
|
else {
|
|
// Recurse to find a new random prime of roughly half the size
|
|
// Recurse to find a new random prime of roughly half the size
|
|
uint32_t newLength = ceil((double)primeBitLen / 2.0) + 1;
|
|
uint32_t newLength = ceil((double)primeBitLen / 2.0) + 1;
|
|
- Bignum c0 = generateRandomPrime(newLength, in_seed, out_seed, prime_gen_counter);
|
|
|
|
|
|
+ CBigNum c0 = generateRandomPrime(newLength, in_seed, out_seed, prime_gen_counter);
|
|
|
|
|
|
// Generate a random integer "x" of primeBitLen bits using the output
|
|
// Generate a random integer "x" of primeBitLen bits using the output
|
|
// of the previous call.
|
|
// of the previous call.
|
|
uint32_t numIterations;
|
|
uint32_t numIterations;
|
|
- Bignum x = generateIntegerFromSeed(primeBitLen, *out_seed, &numIterations);
|
|
|
|
|
|
+ CBigNum x = generateIntegerFromSeed(primeBitLen, *out_seed, &numIterations);
|
|
(*out_seed) += numIterations + 1;
|
|
(*out_seed) += numIterations + 1;
|
|
|
|
|
|
// Compute "t" = ⎡x / (2 * c0⎤
|
|
// Compute "t" = ⎡x / (2 * c0⎤
|
|
// TODO no Ceiling call
|
|
// TODO no Ceiling call
|
|
- Bignum t = x / (Bignum(2) * c0);
|
|
|
|
|
|
+ CBigNum t = x / (CBigNum(2) * c0);
|
|
|
|
|
|
// Repeat the following procedure until we find a prime (or time out)
|
|
// Repeat the following procedure until we find a prime (or time out)
|
|
for (uint32_t testNum = 0; testNum < MAX_PRIMEGEN_ATTEMPTS; testNum++) {
|
|
for (uint32_t testNum = 0; testNum < MAX_PRIMEGEN_ATTEMPTS; testNum++) {
|
|
|
|
|
|
// If ((2 * t * c0) + 1 > 2^{primeBitLen}),
|
|
// If ((2 * t * c0) + 1 > 2^{primeBitLen}),
|
|
// then t = ⎡2^{primeBitLen} – 1 / (2 * c0)⎤.
|
|
// 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);
|
|
|
|
|
|
+ if ((CBigNum(2) * t * c0) > (CBigNum(2).pow(CBigNum(primeBitLen)))) {
|
|
|
|
+ t = ((CBigNum(2).pow(CBigNum(primeBitLen))) - CBigNum(1)) / (CBigNum(2) * c0);
|
|
}
|
|
}
|
|
|
|
|
|
// Set c = (2 * t * c0) + 1
|
|
// Set c = (2 * t * c0) + 1
|
|
- Bignum c = (Bignum(2) * t * c0) + Bignum(1);
|
|
|
|
|
|
+ CBigNum c = (CBigNum(2) * t * c0) + CBigNum(1);
|
|
|
|
|
|
// Increment prime_gen_counter
|
|
// Increment prime_gen_counter
|
|
(*prime_gen_counter)++;
|
|
(*prime_gen_counter)++;
|
|
|
|
|
|
// Test "c" for primality as follows:
|
|
// Test "c" for primality as follows:
|
|
// 1. First pick an integer "a" in between 2 and (c - 2)
|
|
// 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)));
|
|
|
|
|
|
+ CBigNum a = generateIntegerFromSeed(c.bitSize(), (*out_seed), &numIterations);
|
|
|
|
+ a = CBigNum(2) + (a % (c - CBigNum(3)));
|
|
(*out_seed) += (numIterations + 1);
|
|
(*out_seed) += (numIterations + 1);
|
|
|
|
|
|
// 2. Compute "z" = a^{2*t} mod c
|
|
// 2. Compute "z" = a^{2*t} mod c
|
|
- Bignum z = a.pow_mod(Bignum(2) * t, c);
|
|
|
|
|
|
+ CBigNum z = a.pow_mod(CBigNum(2) * t, c);
|
|
|
|
|
|
// 3. Check if "c" is prime.
|
|
// 3. Check if "c" is prime.
|
|
// Specifically, verify that gcd((z-1), c) == 1 AND (z^c0 mod c) == 1
|
|
// Specifically, verify that gcd((z-1), c) == 1 AND (z^c0 mod c) == 1
|
|
// If so we return "c" as our result.
|
|
// If so we return "c" as our result.
|
|
- if (c.gcd(z - Bignum(1)).isOne() && z.pow_mod(c0, c).isOne()) {
|
|
|
|
|
|
+ if (c.gcd(z - CBigNum(1)).isOne() && z.pow_mod(c0, c).isOne()) {
|
|
// Return "c", out_seed and prime_gen_counter
|
|
// Return "c", out_seed and prime_gen_counter
|
|
// (the latter two of which were already updated)
|
|
// (the latter two of which were already updated)
|
|
return c;
|
|
return c;
|
|
}
|
|
}
|
|
|
|
|
|
// 4. If the test did not succeed, increment "t" and loop
|
|
// 4. If the test did not succeed, increment "t" and loop
|
|
- t = t + Bignum(1);
|
|
|
|
|
|
+ t = t + CBigNum(1);
|
|
} // end of test loop
|
|
} // end of test loop
|
|
}
|
|
}
|
|
|
|
|
|
@@ -613,10 +584,10 @@ generateRandomPrime(uint32_t primeBitLen, uint256 in_seed, uint256 *out_seed,
|
|
throw ZerocoinException("Unable to generate random prime (too many tests)");
|
|
throw ZerocoinException("Unable to generate random prime (too many tests)");
|
|
}
|
|
}
|
|
|
|
|
|
-Bignum
|
|
|
|
|
|
+CBigNum
|
|
generateIntegerFromSeed(uint32_t numBits, uint256 seed, uint32_t *numIterations)
|
|
generateIntegerFromSeed(uint32_t numBits, uint256 seed, uint32_t *numIterations)
|
|
{
|
|
{
|
|
- Bignum result(0);
|
|
|
|
|
|
+ CBigNum result(0);
|
|
uint32_t iterations = ceil((double)numBits / (double)HASH_OUTPUT_BITS);
|
|
uint32_t iterations = ceil((double)numBits / (double)HASH_OUTPUT_BITS);
|
|
|
|
|
|
#ifdef ZEROCOIN_DEBUG
|
|
#ifdef ZEROCOIN_DEBUG
|
|
@@ -627,10 +598,10 @@ generateIntegerFromSeed(uint32_t numBits, uint256 seed, uint32_t *numIterations)
|
|
// Loop "iterations" times filling up the value "result" with random bits
|
|
// Loop "iterations" times filling up the value "result" with random bits
|
|
for (uint32_t count = 0; count < iterations; count++) {
|
|
for (uint32_t count = 0; count < iterations; count++) {
|
|
// result += ( H(pseed + count) * 2^{count * p0len} )
|
|
// result += ( H(pseed + count) * 2^{count * p0len} )
|
|
- result += Bignum(calculateHash(seed + count)) * Bignum(2).pow(count * HASH_OUTPUT_BITS);
|
|
|
|
|
|
+ result += CBigNum(calculateHash(seed + count)) * CBigNum(2).pow(count * HASH_OUTPUT_BITS);
|
|
}
|
|
}
|
|
|
|
|
|
- result = Bignum(2).pow(numBits - 1) + (result % (Bignum(2).pow(numBits - 1)));
|
|
|
|
|
|
+ result = CBigNum(2).pow(numBits - 1) + (result % (CBigNum(2).pow(numBits - 1)));
|
|
|
|
|
|
// Return the number of iterations and the result
|
|
// Return the number of iterations and the result
|
|
*numIterations = iterations;
|
|
*numIterations = iterations;
|
|
@@ -646,8 +617,7 @@ generateIntegerFromSeed(uint32_t numBits, uint256 seed, uint32_t *numIterations)
|
|
bool
|
|
bool
|
|
primalityTestByTrialDivision(uint32_t candidate)
|
|
primalityTestByTrialDivision(uint32_t candidate)
|
|
{
|
|
{
|
|
- // TODO: HACK HACK WRONG WRONG
|
|
|
|
- Bignum canBignum(candidate);
|
|
|
|
|
|
+ CBigNum canBignum(candidate);
|
|
|
|
|
|
return canBignum.isPrime();
|
|
return canBignum.isPrime();
|
|
}
|
|
}
|