Crypto++
esign.cpp
1 // esign.cpp - written and placed in the public domain by Wei Dai
2 
3 #include "pch.h"
4 #include "esign.h"
5 #include "asn.h"
6 #include "modarith.h"
7 #include "nbtheory.h"
8 #include "sha.h"
9 #include "algparam.h"
10 
11 NAMESPACE_BEGIN(CryptoPP)
12 
13 void ESIGN_TestInstantiations()
14 {
15  ESIGN<SHA>::Verifier x1(1, 1);
16  ESIGN<SHA>::Signer x2(NullRNG(), 1);
17  ESIGN<SHA>::Verifier x3(x2);
18  ESIGN<SHA>::Verifier x4(x2.GetKey());
19  ESIGN<SHA>::Verifier x5(x3);
20  ESIGN<SHA>::Signer x6 = x2;
21 
22  x6 = x2;
23  x3 = ESIGN<SHA>::Verifier(x2);
24  x4 = x2.GetKey();
25 }
26 
28 {
29  BERSequenceDecoder seq(bt);
30  m_n.BERDecode(seq);
31  m_e.BERDecode(seq);
32  seq.MessageEnd();
33 }
34 
36 {
37  DERSequenceEncoder seq(bt);
38  m_n.DEREncode(seq);
39  m_e.DEREncode(seq);
40  seq.MessageEnd();
41 }
42 
43 Integer ESIGNFunction::ApplyFunction(const Integer &x) const
44 {
45  DoQuickSanityCheck();
46  return STDMIN(a_exp_b_mod_c(x, m_e, m_n) >> (2*GetK()+2), MaxImage());
47 }
48 
49 bool ESIGNFunction::Validate(RandomNumberGenerator &rng, unsigned int level) const
50 {
51  bool pass = true;
52  pass = pass && m_n > Integer::One() && m_n.IsOdd();
53  pass = pass && m_e >= 8 && m_e < m_n;
54  return pass;
55 }
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 
66 {
67  AssignFromHelper(this, source)
68  CRYPTOPP_SET_FUNCTION_ENTRY(Modulus)
69  CRYPTOPP_SET_FUNCTION_ENTRY(PublicExponent)
70  ;
71 }
72 
73 // *****************************************************************************
74 
76 {
77  int modulusSize = 1023*2;
78  param.GetIntValue("ModulusSize", modulusSize) || param.GetIntValue("KeySize", modulusSize);
79 
80  if (modulusSize < 24)
81  throw InvalidArgument("InvertibleESIGNFunction: specified modulus size is too small");
82 
83  if (modulusSize % 3 != 0)
84  throw InvalidArgument("InvertibleESIGNFunction: modulus size must be divisible by 3");
85 
86  m_e = param.GetValueWithDefault("PublicExponent", Integer(32));
87 
88  if (m_e < 8)
89  throw InvalidArgument("InvertibleESIGNFunction: public exponents less than 8 may not be secure");
90 
91  // VC70 workaround: putting these after primeParam causes overlapped stack allocation
92  ConstByteArrayParameter seedParam;
93  SecByteBlock seed;
94 
95  const Integer minP = Integer(204) << (modulusSize/3-8);
96  const Integer maxP = Integer::Power2(modulusSize/3)-1;
97  AlgorithmParameters primeParam = MakeParameters("Min", minP)("Max", maxP)("RandomNumberType", Integer::PRIME);
98 
99  if (param.GetValue("Seed", seedParam))
100  {
101  seed.resize(seedParam.size() + 4);
102  memcpy(seed + 4, seedParam.begin(), seedParam.size());
103 
104  PutWord(false, BIG_ENDIAN_ORDER, seed, (word32)0);
105  m_p.GenerateRandom(rng, CombinedNameValuePairs(primeParam, MakeParameters("Seed", ConstByteArrayParameter(seed))));
106  PutWord(false, BIG_ENDIAN_ORDER, seed, (word32)1);
107  m_q.GenerateRandom(rng, CombinedNameValuePairs(primeParam, MakeParameters("Seed", ConstByteArrayParameter(seed))));
108  }
109  else
110  {
111  m_p.GenerateRandom(rng, primeParam);
112  m_q.GenerateRandom(rng, primeParam);
113  }
114 
115  m_n = m_p * m_p * m_q;
116 
117  assert(m_n.BitCount() == modulusSize);
118 }
119 
121 {
122  BERSequenceDecoder privateKey(bt);
123  m_n.BERDecode(privateKey);
124  m_e.BERDecode(privateKey);
125  m_p.BERDecode(privateKey);
126  m_q.BERDecode(privateKey);
127  privateKey.MessageEnd();
128 }
129 
131 {
132  DERSequenceEncoder privateKey(bt);
133  m_n.DEREncode(privateKey);
134  m_e.DEREncode(privateKey);
135  m_p.DEREncode(privateKey);
136  m_q.DEREncode(privateKey);
137  privateKey.MessageEnd();
138 }
139 
140 Integer InvertibleESIGNFunction::CalculateRandomizedInverse(RandomNumberGenerator &rng, const Integer &x) const
141 {
142  DoQuickSanityCheck();
143 
144  Integer pq = m_p * m_q;
145  Integer p2 = m_p * m_p;
146  Integer r, z, re, a, w0, w1;
147 
148  do
149  {
150  r.Randomize(rng, Integer::Zero(), pq);
151  z = x << (2*GetK()+2);
152  re = a_exp_b_mod_c(r, m_e, m_n);
153  a = (z - re) % m_n;
154  Integer::Divide(w1, w0, a, pq);
155  if (w1.NotZero())
156  {
157  ++w0;
158  w1 = pq - w1;
159  }
160  }
161  while ((w1 >> 2*GetK()+1).IsPositive());
162 
163  ModularArithmetic modp(m_p);
164  Integer t = modp.Divide(w0 * r % m_p, m_e * re % m_p);
165  Integer s = r + t*pq;
166  assert(s < m_n);
167 /*
168  using namespace std;
169  cout << "f = " << x << endl;
170  cout << "r = " << r << endl;
171  cout << "z = " << z << endl;
172  cout << "a = " << a << endl;
173  cout << "w0 = " << w0 << endl;
174  cout << "w1 = " << w1 << endl;
175  cout << "t = " << t << endl;
176  cout << "s = " << s << endl;
177 */
178  return s;
179 }
180 
181 bool InvertibleESIGNFunction::Validate(RandomNumberGenerator &rng, unsigned int level) const
182 {
183  bool pass = ESIGNFunction::Validate(rng, level);
184  pass = pass && m_p > Integer::One() && m_p.IsOdd() && m_p < m_n;
185  pass = pass && m_q > Integer::One() && m_q.IsOdd() && m_q < m_n;
186  pass = pass && m_p.BitCount() == m_q.BitCount();
187  if (level >= 1)
188  pass = pass && m_p * m_p * m_q == m_n;
189  if (level >= 2)
190  pass = pass && VerifyPrime(rng, m_p, level-2) && VerifyPrime(rng, m_q, level-2);
191  return pass;
192 }
193 
194 bool InvertibleESIGNFunction::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
195 {
196  return GetValueHelper<ESIGNFunction>(this, name, valueType, pValue).Assignable()
197  CRYPTOPP_GET_FUNCTION_ENTRY(Prime1)
198  CRYPTOPP_GET_FUNCTION_ENTRY(Prime2)
199  ;
200 }
201 
203 {
204  AssignFromHelper<ESIGNFunction>(this, source)
205  CRYPTOPP_SET_FUNCTION_ENTRY(Prime1)
206  CRYPTOPP_SET_FUNCTION_ENTRY(Prime2)
207  ;
208 }
209 
210 NAMESPACE_END
used to pass byte array input as part of a NameValuePairs object
Definition: algparam.h:13
exception thrown when an invalid argument is detected
Definition: cryptlib.h:145
T GetValueWithDefault(const char *name, T defaultValue) const
get a named value, returns the default if the name doesn&#39;t exist
Definition: cryptlib.h:269
void resize(size_type newSize)
change size and preserve contents
Definition: secblock.h:396
ring of congruence classes modulo n
Definition: modarith.h:19
void DEREncode(BufferedTransformation &bt) const
encode this object into a BufferedTransformation, using DER (Distinguished Encoding Rules) ...
Definition: esign.cpp:130
interface for random number generators
Definition: cryptlib.h:669
bool Validate(RandomNumberGenerator &rng, unsigned int level) const
check this object for errors
Definition: esign.cpp:181
BER Sequence Decoder.
Definition: asn.h:177
interface for buffered transformations
Definition: cryptlib.h:771
static const Integer & One()
avoid calling constructors for these frequently used integers
Definition: integer.cpp:2867
This file contains classes that implement the ESIGN signature schemes as defined in IEEE P1363a...
bool GetIntValue(const char *name, int &value) const
get a named value with type int
Definition: cryptlib.h:282
PK_FinalTemplate< TF_VerifierImpl< SchemeOptions > > Verifier
implements PK_Verifier interface
Definition: pubkey.h:1642
unsigned int BitCount() const
number of significant bits = floor(log2(abs(*this))) + 1
Definition: integer.cpp:3054
void BERDecode(BufferedTransformation &bt)
decode this object from a BufferedTransformation, using BER (Basic Encoding Rules) ...
Definition: esign.cpp:120
bool Validate(RandomNumberGenerator &rng, unsigned int level) const
check this object for errors
Definition: esign.cpp:49
bool GetValue(const char *name, T &value) const
get a named value, returns true if the name exists
Definition: cryptlib.h:262
void AssignFrom(const NameValuePairs &source)
assign values from source to this object
Definition: esign.cpp:202
static Integer Power2(size_t e)
return the integer 2**e
Definition: integer.cpp:2846
multiple precision integer and basic arithmetics
Definition: integer.h:26
void BERDecode(BufferedTransformation &bt)
decode this object from a BufferedTransformation, using BER (Basic Encoding Rules) ...
Definition: esign.cpp:27
RandomNumberGenerator & NullRNG()
returns a reference that can be passed to functions that ask for a RNG but doesn&#39;t actually use it ...
Definition: cryptlib.cpp:295
static void Divide(Integer &r, Integer &q, const Integer &a, const Integer &d)
calculate r and q such that (a == d*q + r) &amp;&amp; (0 &lt;= r &lt; abs(d))
Definition: integer.cpp:3734
bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
to be implemented by derived classes, users should use one of the above functions instead ...
Definition: esign.cpp:194
void DEREncode(BufferedTransformation &bt) const
encode using Distinguished Encoding Rules, put result into a BufferedTransformation object ...
Definition: integer.cpp:3133
DER Sequence Encoder.
Definition: asn.h:187
static const Integer & Zero()
avoid calling constructors for these frequently used integers
Definition: integer.cpp:2862
void AssignFrom(const NameValuePairs &source)
assign values from source to this object
Definition: esign.cpp:65
void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg)
Definition: esign.cpp:75
bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
to be implemented by derived classes, users should use one of the above functions instead ...
Definition: esign.cpp:57
void DEREncode(BufferedTransformation &bt) const
encode this object into a BufferedTransformation, using DER (Distinguished Encoding Rules) ...
Definition: esign.cpp:35
interface for retrieving values given their names
Definition: cryptlib.h:225
A template implementing constructors for public key algorithm classes.
Definition: pubkey.h:1488