Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

221 lines
5.5 KiB

  1. // rabin.cpp - written and placed in the public domain by Wei Dai
  2. #include "pch.h"
  3. #include "rabin.h"
  4. #include "nbtheory.h"
  5. #include "asn.h"
  6. #include "sha.h"
  7. #include "modarith.h"
  8. NAMESPACE_BEGIN(CryptoPP)
  9. void RabinFunction::BERDecode(BufferedTransformation &bt)
  10. {
  11. BERSequenceDecoder seq(bt);
  12. m_n.BERDecode(seq);
  13. m_r.BERDecode(seq);
  14. m_s.BERDecode(seq);
  15. seq.MessageEnd();
  16. }
  17. void RabinFunction::DEREncode(BufferedTransformation &bt) const
  18. {
  19. DERSequenceEncoder seq(bt);
  20. m_n.DEREncode(seq);
  21. m_r.DEREncode(seq);
  22. m_s.DEREncode(seq);
  23. seq.MessageEnd();
  24. }
  25. Integer RabinFunction::ApplyFunction(const Integer &in) const
  26. {
  27. DoQuickSanityCheck();
  28. Integer out = in.Squared()%m_n;
  29. if (in.IsOdd())
  30. out = out*m_r%m_n;
  31. if (Jacobi(in, m_n)==-1)
  32. out = out*m_s%m_n;
  33. return out;
  34. }
  35. bool RabinFunction::Validate(RandomNumberGenerator &rng, unsigned int level) const
  36. {
  37. bool pass = true;
  38. pass = pass && m_n > Integer::One() && m_n%4 == 1;
  39. pass = pass && m_r > Integer::One() && m_r < m_n;
  40. pass = pass && m_s > Integer::One() && m_s < m_n;
  41. if (level >= 1)
  42. pass = pass && Jacobi(m_r, m_n) == -1 && Jacobi(m_s, m_n) == -1;
  43. return pass;
  44. }
  45. bool RabinFunction::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
  46. {
  47. return GetValueHelper(this, name, valueType, pValue).Assignable()
  48. CRYPTOPP_GET_FUNCTION_ENTRY(Modulus)
  49. CRYPTOPP_GET_FUNCTION_ENTRY(QuadraticResidueModPrime1)
  50. CRYPTOPP_GET_FUNCTION_ENTRY(QuadraticResidueModPrime2)
  51. ;
  52. }
  53. void RabinFunction::AssignFrom(const NameValuePairs &source)
  54. {
  55. AssignFromHelper(this, source)
  56. CRYPTOPP_SET_FUNCTION_ENTRY(Modulus)
  57. CRYPTOPP_SET_FUNCTION_ENTRY(QuadraticResidueModPrime1)
  58. CRYPTOPP_SET_FUNCTION_ENTRY(QuadraticResidueModPrime2)
  59. ;
  60. }
  61. // *****************************************************************************
  62. // private key operations:
  63. // generate a random private key
  64. void InvertibleRabinFunction::GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg)
  65. {
  66. int modulusSize = 2048;
  67. alg.GetIntValue("ModulusSize", modulusSize) || alg.GetIntValue("KeySize", modulusSize);
  68. if (modulusSize < 16)
  69. throw InvalidArgument("InvertibleRabinFunction: specified modulus size is too small");
  70. // VC70 workaround: putting these after primeParam causes overlapped stack allocation
  71. bool rFound=false, sFound=false;
  72. Integer t=2;
  73. AlgorithmParameters primeParam = MakeParametersForTwoPrimesOfEqualSize(modulusSize)
  74. ("EquivalentTo", 3)("Mod", 4);
  75. m_p.GenerateRandom(rng, primeParam);
  76. m_q.GenerateRandom(rng, primeParam);
  77. while (!(rFound && sFound))
  78. {
  79. int jp = Jacobi(t, m_p);
  80. int jq = Jacobi(t, m_q);
  81. if (!rFound && jp==1 && jq==-1)
  82. {
  83. m_r = t;
  84. rFound = true;
  85. }
  86. if (!sFound && jp==-1 && jq==1)
  87. {
  88. m_s = t;
  89. sFound = true;
  90. }
  91. ++t;
  92. }
  93. m_n = m_p * m_q;
  94. m_u = m_q.InverseMod(m_p);
  95. }
  96. void InvertibleRabinFunction::BERDecode(BufferedTransformation &bt)
  97. {
  98. BERSequenceDecoder seq(bt);
  99. m_n.BERDecode(seq);
  100. m_r.BERDecode(seq);
  101. m_s.BERDecode(seq);
  102. m_p.BERDecode(seq);
  103. m_q.BERDecode(seq);
  104. m_u.BERDecode(seq);
  105. seq.MessageEnd();
  106. }
  107. void InvertibleRabinFunction::DEREncode(BufferedTransformation &bt) const
  108. {
  109. DERSequenceEncoder seq(bt);
  110. m_n.DEREncode(seq);
  111. m_r.DEREncode(seq);
  112. m_s.DEREncode(seq);
  113. m_p.DEREncode(seq);
  114. m_q.DEREncode(seq);
  115. m_u.DEREncode(seq);
  116. seq.MessageEnd();
  117. }
  118. Integer InvertibleRabinFunction::CalculateInverse(RandomNumberGenerator &rng, const Integer &in) const
  119. {
  120. DoQuickSanityCheck();
  121. ModularArithmetic modn(m_n);
  122. Integer r(rng, Integer::One(), m_n - Integer::One());
  123. r = modn.Square(r);
  124. Integer r2 = modn.Square(r);
  125. Integer c = modn.Multiply(in, r2); // blind
  126. Integer cp=c%m_p, cq=c%m_q;
  127. int jp = Jacobi(cp, m_p);
  128. int jq = Jacobi(cq, m_q);
  129. if (jq==-1)
  130. {
  131. cp = cp*EuclideanMultiplicativeInverse(m_r, m_p)%m_p;
  132. cq = cq*EuclideanMultiplicativeInverse(m_r, m_q)%m_q;
  133. }
  134. if (jp==-1)
  135. {
  136. cp = cp*EuclideanMultiplicativeInverse(m_s, m_p)%m_p;
  137. cq = cq*EuclideanMultiplicativeInverse(m_s, m_q)%m_q;
  138. }
  139. cp = ModularSquareRoot(cp, m_p);
  140. cq = ModularSquareRoot(cq, m_q);
  141. if (jp==-1)
  142. cp = m_p-cp;
  143. Integer out = CRT(cq, m_q, cp, m_p, m_u);
  144. out = modn.Divide(out, r); // unblind
  145. if ((jq==-1 && out.IsEven()) || (jq==1 && out.IsOdd()))
  146. out = m_n-out;
  147. return out;
  148. }
  149. bool InvertibleRabinFunction::Validate(RandomNumberGenerator &rng, unsigned int level) const
  150. {
  151. bool pass = RabinFunction::Validate(rng, level);
  152. pass = pass && m_p > Integer::One() && m_p%4 == 3 && m_p < m_n;
  153. pass = pass && m_q > Integer::One() && m_q%4 == 3 && m_q < m_n;
  154. pass = pass && m_u.IsPositive() && m_u < m_p;
  155. if (level >= 1)
  156. {
  157. pass = pass && m_p * m_q == m_n;
  158. pass = pass && m_u * m_q % m_p == 1;
  159. pass = pass && Jacobi(m_r, m_p) == 1;
  160. pass = pass && Jacobi(m_r, m_q) == -1;
  161. pass = pass && Jacobi(m_s, m_p) == -1;
  162. pass = pass && Jacobi(m_s, m_q) == 1;
  163. }
  164. if (level >= 2)
  165. pass = pass && VerifyPrime(rng, m_p, level-2) && VerifyPrime(rng, m_q, level-2);
  166. return pass;
  167. }
  168. bool InvertibleRabinFunction::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
  169. {
  170. return GetValueHelper<RabinFunction>(this, name, valueType, pValue).Assignable()
  171. CRYPTOPP_GET_FUNCTION_ENTRY(Prime1)
  172. CRYPTOPP_GET_FUNCTION_ENTRY(Prime2)
  173. CRYPTOPP_GET_FUNCTION_ENTRY(MultiplicativeInverseOfPrime2ModPrime1)
  174. ;
  175. }
  176. void InvertibleRabinFunction::AssignFrom(const NameValuePairs &source)
  177. {
  178. AssignFromHelper<RabinFunction>(this, source)
  179. CRYPTOPP_SET_FUNCTION_ENTRY(Prime1)
  180. CRYPTOPP_SET_FUNCTION_ENTRY(Prime2)
  181. CRYPTOPP_SET_FUNCTION_ENTRY(MultiplicativeInverseOfPrime2ModPrime1)
  182. ;
  183. }
  184. NAMESPACE_END