Team Fortress 2 Source Code as on 22/4/2020
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.

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