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.

221 lines
5.9 KiB

  1. // esign.cpp - written and placed in the public domain by Wei Dai
  2. #include "pch.h"
  3. #include "config.h"
  4. // TODO: fix the C4589 warnings
  5. #if CRYPTOPP_MSC_VERSION
  6. # pragma warning(disable: 4589)
  7. #endif
  8. #include "esign.h"
  9. #include "modarith.h"
  10. #include "integer.h"
  11. #include "nbtheory.h"
  12. #include "algparam.h"
  13. #include "sha.h"
  14. #include "asn.h"
  15. NAMESPACE_BEGIN(CryptoPP)
  16. #if !defined(NDEBUG) && !defined(CRYPTOPP_DOXYGEN_PROCESSING)
  17. void ESIGN_TestInstantiations()
  18. {
  19. ESIGN<SHA>::Verifier x1(1, 1);
  20. ESIGN<SHA>::Signer x2(NullRNG(), 1);
  21. ESIGN<SHA>::Verifier x3(x2);
  22. ESIGN<SHA>::Verifier x4(x2.GetKey());
  23. ESIGN<SHA>::Verifier x5(x3);
  24. ESIGN<SHA>::Signer x6 = x2;
  25. x6 = x2;
  26. x3 = ESIGN<SHA>::Verifier(x2);
  27. x4 = x2.GetKey();
  28. }
  29. #endif
  30. void ESIGNFunction::BERDecode(BufferedTransformation &bt)
  31. {
  32. BERSequenceDecoder seq(bt);
  33. m_n.BERDecode(seq);
  34. m_e.BERDecode(seq);
  35. seq.MessageEnd();
  36. }
  37. void ESIGNFunction::DEREncode(BufferedTransformation &bt) const
  38. {
  39. DERSequenceEncoder seq(bt);
  40. m_n.DEREncode(seq);
  41. m_e.DEREncode(seq);
  42. seq.MessageEnd();
  43. }
  44. Integer ESIGNFunction::ApplyFunction(const Integer &x) const
  45. {
  46. DoQuickSanityCheck();
  47. return STDMIN(a_exp_b_mod_c(x, m_e, m_n) >> (2*GetK()+2), MaxImage());
  48. }
  49. bool ESIGNFunction::Validate(RandomNumberGenerator& rng, unsigned int level) const
  50. {
  51. CRYPTOPP_UNUSED(rng), CRYPTOPP_UNUSED(level);
  52. bool pass = true;
  53. pass = pass && m_n > Integer::One() && m_n.IsOdd();
  54. pass = pass && m_e >= 8 && m_e < m_n;
  55. return pass;
  56. }
  57. bool ESIGNFunction::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
  58. {
  59. return GetValueHelper(this, name, valueType, pValue).Assignable()
  60. CRYPTOPP_GET_FUNCTION_ENTRY(Modulus)
  61. CRYPTOPP_GET_FUNCTION_ENTRY(PublicExponent)
  62. ;
  63. }
  64. void ESIGNFunction::AssignFrom(const NameValuePairs &source)
  65. {
  66. AssignFromHelper(this, source)
  67. CRYPTOPP_SET_FUNCTION_ENTRY(Modulus)
  68. CRYPTOPP_SET_FUNCTION_ENTRY(PublicExponent)
  69. ;
  70. }
  71. // *****************************************************************************
  72. void InvertibleESIGNFunction::GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &param)
  73. {
  74. int modulusSize = 1023*2;
  75. param.GetIntValue("ModulusSize", modulusSize) || param.GetIntValue("KeySize", modulusSize);
  76. if (modulusSize < 24)
  77. throw InvalidArgument("InvertibleESIGNFunction: specified modulus size is too small");
  78. if (modulusSize % 3 != 0)
  79. throw InvalidArgument("InvertibleESIGNFunction: modulus size must be divisible by 3");
  80. m_e = param.GetValueWithDefault("PublicExponent", Integer(32));
  81. if (m_e < 8)
  82. throw InvalidArgument("InvertibleESIGNFunction: public exponents less than 8 may not be secure");
  83. // VC70 workaround: putting these after primeParam causes overlapped stack allocation
  84. ConstByteArrayParameter seedParam;
  85. SecByteBlock seed;
  86. const Integer minP = Integer(204) << (modulusSize/3-8);
  87. const Integer maxP = Integer::Power2(modulusSize/3)-1;
  88. AlgorithmParameters primeParam = MakeParameters("Min", minP)("Max", maxP)("RandomNumberType", Integer::PRIME);
  89. if (param.GetValue("Seed", seedParam))
  90. {
  91. seed.resize(seedParam.size() + 4);
  92. memcpy(seed + 4, seedParam.begin(), seedParam.size());
  93. PutWord(false, BIG_ENDIAN_ORDER, seed, (word32)0);
  94. m_p.GenerateRandom(rng, CombinedNameValuePairs(primeParam, MakeParameters("Seed", ConstByteArrayParameter(seed))));
  95. PutWord(false, BIG_ENDIAN_ORDER, seed, (word32)1);
  96. m_q.GenerateRandom(rng, CombinedNameValuePairs(primeParam, MakeParameters("Seed", ConstByteArrayParameter(seed))));
  97. }
  98. else
  99. {
  100. m_p.GenerateRandom(rng, primeParam);
  101. m_q.GenerateRandom(rng, primeParam);
  102. }
  103. m_n = m_p * m_p * m_q;
  104. assert(m_n.BitCount() == (unsigned int)modulusSize);
  105. }
  106. void InvertibleESIGNFunction::BERDecode(BufferedTransformation &bt)
  107. {
  108. BERSequenceDecoder privateKey(bt);
  109. m_n.BERDecode(privateKey);
  110. m_e.BERDecode(privateKey);
  111. m_p.BERDecode(privateKey);
  112. m_q.BERDecode(privateKey);
  113. privateKey.MessageEnd();
  114. }
  115. void InvertibleESIGNFunction::DEREncode(BufferedTransformation &bt) const
  116. {
  117. DERSequenceEncoder privateKey(bt);
  118. m_n.DEREncode(privateKey);
  119. m_e.DEREncode(privateKey);
  120. m_p.DEREncode(privateKey);
  121. m_q.DEREncode(privateKey);
  122. privateKey.MessageEnd();
  123. }
  124. Integer InvertibleESIGNFunction::CalculateRandomizedInverse(RandomNumberGenerator &rng, const Integer &x) const
  125. {
  126. DoQuickSanityCheck();
  127. Integer pq = m_p * m_q;
  128. Integer p2 = m_p * m_p;
  129. Integer r, z, re, a, w0, w1;
  130. do
  131. {
  132. r.Randomize(rng, Integer::Zero(), pq);
  133. z = x << (2*GetK()+2);
  134. re = a_exp_b_mod_c(r, m_e, m_n);
  135. a = (z - re) % m_n;
  136. Integer::Divide(w1, w0, a, pq);
  137. if (w1.NotZero())
  138. {
  139. ++w0;
  140. w1 = pq - w1;
  141. }
  142. }
  143. while ((w1 >> (2*GetK()+1)).IsPositive());
  144. ModularArithmetic modp(m_p);
  145. Integer t = modp.Divide(w0 * r % m_p, m_e * re % m_p);
  146. Integer s = r + t*pq;
  147. assert(s < m_n);
  148. #if 0
  149. using namespace std;
  150. cout << "f = " << x << endl;
  151. cout << "r = " << r << endl;
  152. cout << "z = " << z << endl;
  153. cout << "a = " << a << endl;
  154. cout << "w0 = " << w0 << endl;
  155. cout << "w1 = " << w1 << endl;
  156. cout << "t = " << t << endl;
  157. cout << "s = " << s << endl;
  158. #endif
  159. return s;
  160. }
  161. bool InvertibleESIGNFunction::Validate(RandomNumberGenerator &rng, unsigned int level) const
  162. {
  163. bool pass = ESIGNFunction::Validate(rng, level);
  164. pass = pass && m_p > Integer::One() && m_p.IsOdd() && m_p < m_n;
  165. pass = pass && m_q > Integer::One() && m_q.IsOdd() && m_q < m_n;
  166. pass = pass && m_p.BitCount() == m_q.BitCount();
  167. if (level >= 1)
  168. pass = pass && m_p * m_p * m_q == m_n;
  169. if (level >= 2)
  170. pass = pass && VerifyPrime(rng, m_p, level-2) && VerifyPrime(rng, m_q, level-2);
  171. return pass;
  172. }
  173. bool InvertibleESIGNFunction::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
  174. {
  175. return GetValueHelper<ESIGNFunction>(this, name, valueType, pValue).Assignable()
  176. CRYPTOPP_GET_FUNCTION_ENTRY(Prime1)
  177. CRYPTOPP_GET_FUNCTION_ENTRY(Prime2)
  178. ;
  179. }
  180. void InvertibleESIGNFunction::AssignFrom(const NameValuePairs &source)
  181. {
  182. AssignFromHelper<ESIGNFunction>(this, source)
  183. CRYPTOPP_SET_FUNCTION_ENTRY(Prime1)
  184. CRYPTOPP_SET_FUNCTION_ENTRY(Prime2)
  185. ;
  186. }
  187. NAMESPACE_END