Crypto++  5.6.4
Free C++ class library of cryptographic schemes
esign.cpp
1 // esign.cpp - written and placed in the public domain by Wei Dai
2 
3 #include "pch.h"
4 #include "config.h"
5 
6 // TODO: fix the C4589 warnings
7 #if CRYPTOPP_MSC_VERSION
8 # pragma warning(disable: 4589)
9 #endif
10 
11 #include "esign.h"
12 #include "modarith.h"
13 #include "integer.h"
14 #include "nbtheory.h"
15 #include "algparam.h"
16 #include "sha.h"
17 #include "asn.h"
18 
19 NAMESPACE_BEGIN(CryptoPP)
20 
21 #if CRYPTOPP_DEBUG && !defined(CRYPTOPP_DOXYGEN_PROCESSING)
22 void ESIGN_TestInstantiations()
23 {
24  ESIGN<SHA>::Verifier x1(1, 1);
25  ESIGN<SHA>::Signer x2(NullRNG(), 1);
26  ESIGN<SHA>::Verifier x3(x2);
27  ESIGN<SHA>::Verifier x4(x2.GetKey());
28  ESIGN<SHA>::Verifier x5(x3);
29  ESIGN<SHA>::Signer x6 = x2;
30 
31  x6 = x2;
32  x3 = ESIGN<SHA>::Verifier(x2);
33  x4 = x2.GetKey();
34 }
35 #endif
36 
38 {
39  BERSequenceDecoder seq(bt);
40  m_n.BERDecode(seq);
41  m_e.BERDecode(seq);
42  seq.MessageEnd();
43 }
44 
46 {
47  DERSequenceEncoder seq(bt);
48  m_n.DEREncode(seq);
49  m_e.DEREncode(seq);
50  seq.MessageEnd();
51 }
52 
54 {
56  return STDMIN(a_exp_b_mod_c(x, m_e, m_n) >> (2*GetK()+2), MaxImage());
57 }
58 
59 bool ESIGNFunction::Validate(RandomNumberGenerator& rng, unsigned int level) const
60 {
61  CRYPTOPP_UNUSED(rng), CRYPTOPP_UNUSED(level);
62  bool pass = true;
63  pass = pass && m_n > Integer::One() && m_n.IsOdd();
64  pass = pass && m_e >= 8 && m_e < m_n;
65  return pass;
66 }
67 
68 bool ESIGNFunction::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
69 {
70  return GetValueHelper(this, name, valueType, pValue).Assignable()
71  CRYPTOPP_GET_FUNCTION_ENTRY(Modulus)
72  CRYPTOPP_GET_FUNCTION_ENTRY(PublicExponent)
73  ;
74 }
75 
77 {
78  AssignFromHelper(this, source)
79  CRYPTOPP_SET_FUNCTION_ENTRY(Modulus)
80  CRYPTOPP_SET_FUNCTION_ENTRY(PublicExponent)
81  ;
82 }
83 
84 // *****************************************************************************
85 
87 {
88  int modulusSize = 1023*2;
89  param.GetIntValue("ModulusSize", modulusSize) || param.GetIntValue("KeySize", modulusSize);
90 
91  if (modulusSize < 24)
92  throw InvalidArgument("InvertibleESIGNFunction: specified modulus size is too small");
93 
94  if (modulusSize % 3 != 0)
95  throw InvalidArgument("InvertibleESIGNFunction: modulus size must be divisible by 3");
96 
97  m_e = param.GetValueWithDefault("PublicExponent", Integer(32));
98 
99  if (m_e < 8)
100  throw InvalidArgument("InvertibleESIGNFunction: public exponents less than 8 may not be secure");
101 
102  // VC70 workaround: putting these after primeParam causes overlapped stack allocation
103  ConstByteArrayParameter seedParam;
104  SecByteBlock seed;
105 
106  const Integer minP = Integer(204) << (modulusSize/3-8);
107  const Integer maxP = Integer::Power2(modulusSize/3)-1;
108  AlgorithmParameters primeParam = MakeParameters("Min", minP)("Max", maxP)("RandomNumberType", Integer::PRIME);
109 
110  if (param.GetValue("Seed", seedParam))
111  {
112  seed.resize(seedParam.size() + 4);
113  memcpy(seed + 4, seedParam.begin(), seedParam.size());
114 
115  PutWord(false, BIG_ENDIAN_ORDER, seed, (word32)0);
116  m_p.GenerateRandom(rng, CombinedNameValuePairs(primeParam, MakeParameters("Seed", ConstByteArrayParameter(seed))));
117  PutWord(false, BIG_ENDIAN_ORDER, seed, (word32)1);
118  m_q.GenerateRandom(rng, CombinedNameValuePairs(primeParam, MakeParameters("Seed", ConstByteArrayParameter(seed))));
119  }
120  else
121  {
122  m_p.GenerateRandom(rng, primeParam);
123  m_q.GenerateRandom(rng, primeParam);
124  }
125 
126  m_n = m_p * m_p * m_q;
127 
128  CRYPTOPP_ASSERT(m_n.BitCount() == (unsigned int)modulusSize);
129 }
130 
132 {
133  BERSequenceDecoder privateKey(bt);
134  m_n.BERDecode(privateKey);
135  m_e.BERDecode(privateKey);
136  m_p.BERDecode(privateKey);
137  m_q.BERDecode(privateKey);
138  privateKey.MessageEnd();
139 }
140 
142 {
143  DERSequenceEncoder privateKey(bt);
144  m_n.DEREncode(privateKey);
145  m_e.DEREncode(privateKey);
146  m_p.DEREncode(privateKey);
147  m_q.DEREncode(privateKey);
148  privateKey.MessageEnd();
149 }
150 
152 {
154 
155  Integer pq = m_p * m_q;
156  Integer p2 = m_p * m_p;
157  Integer r, z, re, a, w0, w1;
158 
159  do
160  {
161  r.Randomize(rng, Integer::Zero(), pq);
162  z = x << (2*GetK()+2);
163  re = a_exp_b_mod_c(r, m_e, m_n);
164  a = (z - re) % m_n;
165  Integer::Divide(w1, w0, a, pq);
166  if (w1.NotZero())
167  {
168  ++w0;
169  w1 = pq - w1;
170  }
171  }
172  while ((w1 >> (2*GetK()+1)).IsPositive());
173 
174  ModularArithmetic modp(m_p);
175  Integer t = modp.Divide(w0 * r % m_p, m_e * re % m_p);
176  Integer s = r + t*pq;
177  CRYPTOPP_ASSERT(s < m_n);
178 #if 0
179  using namespace std;
180  cout << "f = " << x << endl;
181  cout << "r = " << r << endl;
182  cout << "z = " << z << endl;
183  cout << "a = " << a << endl;
184  cout << "w0 = " << w0 << endl;
185  cout << "w1 = " << w1 << endl;
186  cout << "t = " << t << endl;
187  cout << "s = " << s << endl;
188 #endif
189  return s;
190 }
191 
192 bool InvertibleESIGNFunction::Validate(RandomNumberGenerator &rng, unsigned int level) const
193 {
194  bool pass = ESIGNFunction::Validate(rng, level);
195  pass = pass && m_p > Integer::One() && m_p.IsOdd() && m_p < m_n;
196  pass = pass && m_q > Integer::One() && m_q.IsOdd() && m_q < m_n;
197  pass = pass && m_p.BitCount() == m_q.BitCount();
198  if (level >= 1)
199  pass = pass && m_p * m_p * m_q == m_n;
200  if (level >= 2)
201  pass = pass && VerifyPrime(rng, m_p, level-2) && VerifyPrime(rng, m_q, level-2);
202  return pass;
203 }
204 
205 bool InvertibleESIGNFunction::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
206 {
207  return GetValueHelper<ESIGNFunction>(this, name, valueType, pValue).Assignable()
208  CRYPTOPP_GET_FUNCTION_ENTRY(Prime1)
209  CRYPTOPP_GET_FUNCTION_ENTRY(Prime2)
210  ;
211 }
212 
214 {
215  AssignFromHelper<ESIGNFunction>(this, source)
216  CRYPTOPP_SET_FUNCTION_ENTRY(Prime1)
217  CRYPTOPP_SET_FUNCTION_ENTRY(Prime2)
218  ;
219 }
220 
221 NAMESPACE_END
Used to pass byte array input as part of a NameValuePairs object.
Definition: algparam.h:29
Integer CalculateRandomizedInverse(RandomNumberGenerator &rng, const Integer &x) const
Applies the inverse of the trapdoor function, using random data if required.
Definition: esign.cpp:151
An invalid argument was detected.
Definition: cryptlib.h:187
Classes for working with NameValuePairs.
a number which is probabilistically prime
Definition: integer.h:91
bool NotZero() const
Determines if the Integer is non-0.
Definition: integer.h:329
const char * Prime2()
Integer.
Definition: argnames.h:43
bool IsOdd() const
Determines if the Integer is odd parity.
Definition: integer.h:347
T GetValueWithDefault(const char *name, T defaultValue) const
Get a named value.
Definition: cryptlib.h:353
void resize(size_type newSize)
Change size and preserve contents.
Definition: secblock.h:705
size_t size() const
Length of the memory block.
Definition: algparam.h:93
Library configuration file.
Ring of congruence classes modulo n.
Definition: modarith.h:34
STL namespace.
void DEREncode(BufferedTransformation &bt) const
Encode this object into a BufferedTransformation.
Definition: esign.cpp:141
Interface for random number generators.
Definition: cryptlib.h:1193
bool Validate(RandomNumberGenerator &rng, unsigned int level) const
Check this object for errors.
Definition: esign.cpp:192
void Randomize(RandomNumberGenerator &rng, size_t bitCount)
Set this Integer to random integer.
Definition: integer.cpp:3430
Combines two sets of NameValuePairs.
Definition: algparam.h:135
SecBlock typedef.
Definition: secblock.h:731
BER Sequence Decoder.
Definition: asn.h:294
Interface for buffered transformations.
Definition: cryptlib.h:1359
const byte * begin() const
Pointer to the first byte in the memory block.
Definition: algparam.h:89
static const Integer & One()
Integer representing 1.
Definition: integer.cpp:3019
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:376
PK_FinalTemplate< TF_VerifierImpl< SchemeOptions > > Verifier
implements PK_Verifier interface
Definition: pubkey.h:2203
const char * Prime1()
Integer.
Definition: argnames.h:42
unsigned int BitCount() const
Determines the number of bits required to represent the Integer.
Definition: integer.cpp:3280
void BERDecode(BufferedTransformation &bt)
Decode this object from a BufferedTransformation.
Definition: esign.cpp:131
bool Validate(RandomNumberGenerator &rng, unsigned int level) const
Check this object for errors.
Definition: esign.cpp:59
bool GetValue(const char *name, T &value) const
Get a named value.
Definition: cryptlib.h:340
AlgorithmParameters MakeParameters(const char *name, const T &value, bool throwIfNotUsed=true)
Create an object that implements NameValuePairs.
Definition: algparam.h:554
const char * PublicExponent()
Integer.
Definition: argnames.h:33
bool VerifyPrime(RandomNumberGenerator &rng, const Integer &p, unsigned int level=1)
Verifies a prime number.
Definition: nbtheory.cpp:249
void AssignFrom(const NameValuePairs &source)
Assign values to this object.
Definition: esign.cpp:213
static Integer Power2(size_t e)
Exponentiates to a power of 2.
Definition: integer.cpp:2998
Multiple precision integer with arithmetic operations.
Definition: integer.h:45
virtual Integer MaxImage() const
Returns the maximum size of a message after the trapdoor function is applied bound to a public key...
Definition: pubkey.h:96
void BERDecode(BufferedTransformation &bt)
Decode this object from a BufferedTransformation.
Definition: esign.cpp:37
byte order is big-endian
Definition: cryptlib.h:132
RandomNumberGenerator & NullRNG()
Random Number Generator that does not produce random numbers.
Definition: cryptlib.cpp:402
const T & STDMIN(const T &a, const T &b)
Replacement function for std::min.
Definition: misc.h:467
#define CRYPTOPP_ASSERT(exp)
Debugging and diagnostic assertion.
Definition: trap.h:62
static void Divide(Integer &r, Integer &q, const Integer &a, const Integer &d)
calculate r and q such that (a == d*q + r) && (0 <= r < abs(d))
Definition: integer.cpp:3974
const Integer & Divide(const Integer &a, const Integer &b) const
Divides elements in the ring.
Definition: modarith.h:200
Classes and functions for working with ANS.1 objects.
Classes for SHA-1 and SHA-2 family of message digests.
bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
Get a named value.
Definition: esign.cpp:205
Classes and functions for number theoretic operations.
void DEREncode(BufferedTransformation &bt) const
Encode in DER format.
Definition: integer.cpp:3363
DER Sequence Encoder.
Definition: asn.h:304
An object that implements NameValuePairs.
Definition: algparam.h:489
const char * Modulus()
Integer.
Definition: argnames.h:32
Multiple precision integer with arithmetic operations.
static const Integer & Zero()
Integer representing 0.
Definition: integer.cpp:3014
void BERDecode(const byte *input, size_t inputLen)
Decode from BER format.
Definition: integer.cpp:3370
void AssignFrom(const NameValuePairs &source)
Assign values to this object.
Definition: esign.cpp:76
Class file for performing modular arithmetic.
Crypto++ library namespace.
void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg)
Definition: esign.cpp:86
bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
Get a named value.
Definition: esign.cpp:68
void DEREncode(BufferedTransformation &bt) const
Encode this object into a BufferedTransformation.
Definition: esign.cpp:45
Integer ApplyFunction(const Integer &x) const
Applies the trapdoor.
Definition: esign.cpp:53
Interface for retrieving values given their names.
Definition: cryptlib.h:282
void DoQuickSanityCheck() const
Perform a quick sanity check.
Definition: cryptlib.h:2155
Template implementing constructors for public key algorithm classes.
Definition: pubkey.h:2037