AccumulatorProofOfKnowledge.cpp 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. // ECOin - Copyright (c) - 2014/2022 - GPLv3 - epsylon@riseup.net (https://03c8.net)
  2. #include "Zerocoin.h"
  3. namespace libzerocoin {
  4. AccumulatorProofOfKnowledge::AccumulatorProofOfKnowledge(const AccumulatorAndProofParams* p): params(p) {}
  5. AccumulatorProofOfKnowledge::AccumulatorProofOfKnowledge(const AccumulatorAndProofParams* p,
  6. const Commitment& commitmentToCoin, const AccumulatorWitness& witness,
  7. Accumulator& a): params(p) {
  8. CBigNum sg = params->accumulatorPoKCommitmentGroup.g;
  9. CBigNum sh = params->accumulatorPoKCommitmentGroup.h;
  10. CBigNum g_n = params->accumulatorQRNCommitmentGroup.g;
  11. CBigNum h_n = params->accumulatorQRNCommitmentGroup.h;
  12. CBigNum e = commitmentToCoin.getContents();
  13. CBigNum r = commitmentToCoin.getRandomness();
  14. CBigNum r_1 = CBigNum::randBignum(params->accumulatorModulus/4);
  15. CBigNum r_2 = CBigNum::randBignum(params->accumulatorModulus/4);
  16. CBigNum r_3 = CBigNum::randBignum(params->accumulatorModulus/4);
  17. this->C_e = g_n.pow_mod(e, params->accumulatorModulus) * h_n.pow_mod(r_1, params->accumulatorModulus);
  18. this->C_u = witness.getValue() * h_n.pow_mod(r_2, params->accumulatorModulus);
  19. this->C_r = g_n.pow_mod(r_2, params->accumulatorModulus) * h_n.pow_mod(r_3, params->accumulatorModulus);
  20. CBigNum r_alpha = CBigNum::randBignum(params->maxCoinValue * CBigNum(2).pow(params->k_prime + params->k_dprime));
  21. if(!(CBigNum::randBignum(CBigNum(3)) % 2)) {
  22. r_alpha = 0-r_alpha;
  23. }
  24. CBigNum r_gamma = CBigNum::randBignum(params->accumulatorPoKCommitmentGroup.modulus);
  25. CBigNum r_phi = CBigNum::randBignum(params->accumulatorPoKCommitmentGroup.modulus);
  26. CBigNum r_psi = CBigNum::randBignum(params->accumulatorPoKCommitmentGroup.modulus);
  27. CBigNum r_sigma = CBigNum::randBignum(params->accumulatorPoKCommitmentGroup.modulus);
  28. CBigNum r_xi = CBigNum::randBignum(params->accumulatorPoKCommitmentGroup.modulus);
  29. CBigNum r_epsilon = CBigNum::randBignum((params->accumulatorModulus/4) * CBigNum(2).pow(params->k_prime + params->k_dprime));
  30. if(!(CBigNum::randBignum(CBigNum(3)) % 2)) {
  31. r_epsilon = 0-r_epsilon;
  32. }
  33. CBigNum r_eta = CBigNum::randBignum((params->accumulatorModulus/4) * CBigNum(2).pow(params->k_prime + params->k_dprime));
  34. if(!(CBigNum::randBignum(CBigNum(3)) % 2)) {
  35. r_eta = 0-r_eta;
  36. }
  37. CBigNum r_zeta = CBigNum::randBignum((params->accumulatorModulus/4) * CBigNum(2).pow(params->k_prime + params->k_dprime));
  38. if(!(CBigNum::randBignum(CBigNum(3)) % 2)) {
  39. r_zeta = 0-r_zeta;
  40. }
  41. CBigNum r_beta = CBigNum::randBignum((params->accumulatorModulus/4) * params->accumulatorPoKCommitmentGroup.modulus * CBigNum(2).pow(params->k_prime + params->k_dprime));
  42. if(!(CBigNum::randBignum(CBigNum(3)) % 2)) {
  43. r_beta = 0-r_beta;
  44. }
  45. CBigNum r_delta = CBigNum::randBignum((params->accumulatorModulus/4) * params->accumulatorPoKCommitmentGroup.modulus * CBigNum(2).pow(params->k_prime + params->k_dprime));
  46. if(!(CBigNum::randBignum(CBigNum(3)) % 2)) {
  47. r_delta = 0-r_delta;
  48. }
  49. this->st_1 = (sg.pow_mod(r_alpha, params->accumulatorPoKCommitmentGroup.modulus) * sh.pow_mod(r_phi, params->accumulatorPoKCommitmentGroup.modulus)) % params->accumulatorPoKCommitmentGroup.modulus;
  50. this->st_2 = (((commitmentToCoin.getCommitmentValue() * sg.inverse(params->accumulatorPoKCommitmentGroup.modulus)).pow_mod(r_gamma, params->accumulatorPoKCommitmentGroup.modulus)) * sh.pow_mod(r_psi, params->accumulatorPoKCommitmentGroup.modulus)) % params->accumulatorPoKCommitmentGroup.modulus;
  51. this->st_3 = ((sg * commitmentToCoin.getCommitmentValue()).pow_mod(r_sigma, params->accumulatorPoKCommitmentGroup.modulus) * sh.pow_mod(r_xi, params->accumulatorPoKCommitmentGroup.modulus)) % params->accumulatorPoKCommitmentGroup.modulus;
  52. this->t_1 = (h_n.pow_mod(r_zeta, params->accumulatorModulus) * g_n.pow_mod(r_epsilon, params->accumulatorModulus)) % params->accumulatorModulus;
  53. this->t_2 = (h_n.pow_mod(r_eta, params->accumulatorModulus) * g_n.pow_mod(r_alpha, params->accumulatorModulus)) % params->accumulatorModulus;
  54. this->t_3 = (C_u.pow_mod(r_alpha, params->accumulatorModulus) * ((h_n.inverse(params->accumulatorModulus)).pow_mod(r_beta, params->accumulatorModulus))) % params->accumulatorModulus;
  55. this->t_4 = (C_r.pow_mod(r_alpha, params->accumulatorModulus) * ((h_n.inverse(params->accumulatorModulus)).pow_mod(r_delta, params->accumulatorModulus)) * ((g_n.inverse(params->accumulatorModulus)).pow_mod(r_beta, params->accumulatorModulus))) % params->accumulatorModulus;
  56. CHashWriter hasher(0,0);
  57. hasher << *params << sg << sh << g_n << h_n << commitmentToCoin.getCommitmentValue() << C_e << C_u << C_r << st_1 << st_2 << st_3 << t_1 << t_2 << t_3 << t_4;
  58. //According to the proof, this hash should be of length k_prime bits. It is currently greater than that, which should not be a problem, but we should check this.
  59. CBigNum c = CBigNum(hasher.GetHash());
  60. this->s_alpha = r_alpha - c*e;
  61. this->s_beta = r_beta - c*r_2*e;
  62. this->s_zeta = r_zeta - c*r_3;
  63. this->s_sigma = r_sigma - c*((e+1).inverse(params->accumulatorPoKCommitmentGroup.groupOrder));
  64. this->s_eta = r_eta - c*r_1;
  65. this->s_epsilon = r_epsilon - c*r_2;
  66. this->s_delta = r_delta - c*r_3*e;
  67. this->s_xi = r_xi + c*r*((e+1).inverse(params->accumulatorPoKCommitmentGroup.groupOrder));
  68. this->s_phi = (r_phi - c*r) % params->accumulatorPoKCommitmentGroup.groupOrder;
  69. this->s_gamma = r_gamma - c*((e-1).inverse(params->accumulatorPoKCommitmentGroup.groupOrder));
  70. this->s_psi = r_psi + c*r*((e-1).inverse(params->accumulatorPoKCommitmentGroup.groupOrder));
  71. }
  72. /** Verifies that a commitment c is accumulated in accumulator a
  73. */
  74. bool AccumulatorProofOfKnowledge:: Verify(const Accumulator& a, const CBigNum& valueOfCommitmentToCoin) const {
  75. CBigNum sg = params->accumulatorPoKCommitmentGroup.g;
  76. CBigNum sh = params->accumulatorPoKCommitmentGroup.h;
  77. CBigNum g_n = params->accumulatorQRNCommitmentGroup.g;
  78. CBigNum h_n = params->accumulatorQRNCommitmentGroup.h;
  79. //According to the proof, this hash should be of length k_prime bits. It is currently greater than that, which should not be a problem, but we should check this.
  80. CHashWriter hasher(0,0);
  81. hasher << *params << sg << sh << g_n << h_n << valueOfCommitmentToCoin << C_e << C_u << C_r << st_1 << st_2 << st_3 << t_1 << t_2 << t_3 << t_4;
  82. CBigNum c = CBigNum(hasher.GetHash()); //this hash should be of length k_prime bits
  83. CBigNum st_1_prime = (valueOfCommitmentToCoin.pow_mod(c, params->accumulatorPoKCommitmentGroup.modulus) * sg.pow_mod(s_alpha, params->accumulatorPoKCommitmentGroup.modulus) * sh.pow_mod(s_phi, params->accumulatorPoKCommitmentGroup.modulus)) % params->accumulatorPoKCommitmentGroup.modulus;
  84. CBigNum st_2_prime = (sg.pow_mod(c, params->accumulatorPoKCommitmentGroup.modulus) * ((valueOfCommitmentToCoin * sg.inverse(params->accumulatorPoKCommitmentGroup.modulus)).pow_mod(s_gamma, params->accumulatorPoKCommitmentGroup.modulus)) * sh.pow_mod(s_psi, params->accumulatorPoKCommitmentGroup.modulus)) % params->accumulatorPoKCommitmentGroup.modulus;
  85. CBigNum st_3_prime = (sg.pow_mod(c, params->accumulatorPoKCommitmentGroup.modulus) * (sg * valueOfCommitmentToCoin).pow_mod(s_sigma, params->accumulatorPoKCommitmentGroup.modulus) * sh.pow_mod(s_xi, params->accumulatorPoKCommitmentGroup.modulus)) % params->accumulatorPoKCommitmentGroup.modulus;
  86. CBigNum t_1_prime = (C_r.pow_mod(c, params->accumulatorModulus) * h_n.pow_mod(s_zeta, params->accumulatorModulus) * g_n.pow_mod(s_epsilon, params->accumulatorModulus)) % params->accumulatorModulus;
  87. CBigNum t_2_prime = (C_e.pow_mod(c, params->accumulatorModulus) * h_n.pow_mod(s_eta, params->accumulatorModulus) * g_n.pow_mod(s_alpha, params->accumulatorModulus)) % params->accumulatorModulus;
  88. CBigNum t_3_prime = ((a.getValue()).pow_mod(c, params->accumulatorModulus) * C_u.pow_mod(s_alpha, params->accumulatorModulus) * ((h_n.inverse(params->accumulatorModulus)).pow_mod(s_beta, params->accumulatorModulus))) % params->accumulatorModulus;
  89. CBigNum t_4_prime = (C_r.pow_mod(s_alpha, params->accumulatorModulus) * ((h_n.inverse(params->accumulatorModulus)).pow_mod(s_delta, params->accumulatorModulus)) * ((g_n.inverse(params->accumulatorModulus)).pow_mod(s_beta, params->accumulatorModulus))) % params->accumulatorModulus;
  90. bool result = false;
  91. bool result_st1 = (st_1 == st_1_prime);
  92. bool result_st2 = (st_2 == st_2_prime);
  93. bool result_st3 = (st_3 == st_3_prime);
  94. bool result_t1 = (t_1 == t_1_prime);
  95. bool result_t2 = (t_2 == t_2_prime);
  96. bool result_t3 = (t_3 == t_3_prime);
  97. bool result_t4 = (t_4 == t_4_prime);
  98. bool result_range = ((s_alpha >= -(params->maxCoinValue * CBigNum(2).pow(params->k_prime + params->k_dprime + 1))) && (s_alpha <= (params->maxCoinValue * CBigNum(2).pow(params->k_prime + params->k_dprime + 1))));
  99. result = result_st1 && result_st2 && result_st3 && result_t1 && result_t2 && result_t3 && result_t4 && result_range;
  100. return result;
  101. }
  102. } /* namespace libzerocoin */