esign.cpp

00001 // esign.cpp - written and placed in the public domain by Wei Dai
00002 
00003 #include "pch.h"
00004 #include "esign.h"
00005 #include "asn.h"
00006 #include "modarith.h"
00007 #include "nbtheory.h"
00008 #include "sha.h"
00009 #include "algparam.h"
00010 
00011 NAMESPACE_BEGIN(CryptoPP)
00012 
00013 void ESIGN_TestInstantiations()
00014 {
00015         ESIGN<SHA>::Verifier x1(1, 1);
00016         ESIGN<SHA>::Signer x2(NullRNG(), 1);
00017         ESIGN<SHA>::Verifier x3(x2);
00018         ESIGN<SHA>::Verifier x4(x2.GetKey());
00019         ESIGN<SHA>::Verifier x5(x3);
00020         ESIGN<SHA>::Signer x6 = x2;
00021 
00022         x6 = x2;
00023         x3 = ESIGN<SHA>::Verifier(x2);
00024         x4 = x2.GetKey();
00025 }
00026 
00027 void ESIGNFunction::BERDecode(BufferedTransformation &bt)
00028 {
00029         BERSequenceDecoder seq(bt);
00030                 m_n.BERDecode(seq);
00031                 m_e.BERDecode(seq);
00032         seq.MessageEnd();
00033 }
00034 
00035 void ESIGNFunction::DEREncode(BufferedTransformation &bt) const
00036 {
00037         DERSequenceEncoder seq(bt);
00038                 m_n.DEREncode(seq);
00039                 m_e.DEREncode(seq);
00040         seq.MessageEnd();
00041 }
00042 
00043 Integer ESIGNFunction::ApplyFunction(const Integer &x) const
00044 {
00045         DoQuickSanityCheck();
00046         return STDMIN(a_exp_b_mod_c(x, m_e, m_n) >> (2*GetK()+2), MaxImage());
00047 }
00048 
00049 bool ESIGNFunction::Validate(RandomNumberGenerator &rng, unsigned int level) const
00050 {
00051         bool pass = true;
00052         pass = pass && m_n > Integer::One() && m_n.IsOdd();
00053         pass = pass && m_e >= 8 && m_e < m_n;
00054         return pass;
00055 }
00056 
00057 bool ESIGNFunction::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
00058 {
00059         return GetValueHelper(this, name, valueType, pValue).Assignable()
00060                 CRYPTOPP_GET_FUNCTION_ENTRY(Modulus)
00061                 CRYPTOPP_GET_FUNCTION_ENTRY(PublicExponent)
00062                 ;
00063 }
00064 
00065 void ESIGNFunction::AssignFrom(const NameValuePairs &source)
00066 {
00067         AssignFromHelper(this, source)
00068                 CRYPTOPP_SET_FUNCTION_ENTRY(Modulus)
00069                 CRYPTOPP_SET_FUNCTION_ENTRY(PublicExponent)
00070                 ;
00071 }
00072 
00073 // *****************************************************************************
00074 
00075 void InvertibleESIGNFunction::GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &param)
00076 {
00077         int modulusSize = 1023*2;
00078         param.GetIntValue("ModulusSize", modulusSize) || param.GetIntValue("KeySize", modulusSize);
00079 
00080         if (modulusSize < 24)
00081                 throw InvalidArgument("InvertibleESIGNFunction: specified modulus size is too small");
00082 
00083         if (modulusSize % 3 != 0)
00084                 throw InvalidArgument("InvertibleESIGNFunction: modulus size must be divisible by 3");
00085 
00086         m_e = param.GetValueWithDefault("PublicExponent", Integer(32));
00087 
00088         if (m_e < 8)
00089                 throw InvalidArgument("InvertibleESIGNFunction: public exponents less than 8 may not be secure");
00090 
00091         // VC70 workaround: putting these after primeParam causes overlapped stack allocation
00092         ConstByteArrayParameter seedParam;
00093         SecByteBlock seed;
00094 
00095         const Integer minP = Integer(204) << (modulusSize/3-8);
00096         const Integer maxP = Integer::Power2(modulusSize/3)-1;
00097         const NameValuePairs &primeParam = MakeParameters("Min", minP)("Max", maxP)("RandomNumberType", Integer::PRIME);
00098 
00099         if (param.GetValue("Seed", seedParam))
00100         {
00101                 seed.resize(seedParam.size() + 4);
00102                 memcpy(seed + 4, seedParam.begin(), seedParam.size());
00103 
00104                 UnalignedPutWord(BIG_ENDIAN_ORDER, seed, (word32)0);
00105                 m_p.GenerateRandom(rng, CombinedNameValuePairs(primeParam, MakeParameters("Seed", ConstByteArrayParameter(seed))));
00106                 UnalignedPutWord(BIG_ENDIAN_ORDER, seed, (word32)1);
00107                 m_q.GenerateRandom(rng, CombinedNameValuePairs(primeParam, MakeParameters("Seed", ConstByteArrayParameter(seed))));
00108         }
00109         else
00110         {
00111                 m_p.GenerateRandom(rng, primeParam);
00112                 m_q.GenerateRandom(rng, primeParam);
00113         }
00114 
00115         m_n = m_p * m_p * m_q;
00116 
00117         assert(m_n.BitCount() == modulusSize);
00118 }
00119 
00120 void InvertibleESIGNFunction::BERDecode(BufferedTransformation &bt)
00121 {
00122         BERSequenceDecoder privateKey(bt);
00123                 m_n.BERDecode(privateKey);
00124                 m_e.BERDecode(privateKey);
00125                 m_p.BERDecode(privateKey);
00126                 m_q.BERDecode(privateKey);
00127         privateKey.MessageEnd();
00128 }
00129 
00130 void InvertibleESIGNFunction::DEREncode(BufferedTransformation &bt) const
00131 {
00132         DERSequenceEncoder privateKey(bt);
00133                 m_n.DEREncode(privateKey);
00134                 m_e.DEREncode(privateKey);
00135                 m_p.DEREncode(privateKey);
00136                 m_q.DEREncode(privateKey);
00137         privateKey.MessageEnd();
00138 }
00139 
00140 Integer InvertibleESIGNFunction::CalculateRandomizedInverse(RandomNumberGenerator &rng, const Integer &x) const 
00141 {
00142         DoQuickSanityCheck();
00143 
00144         Integer pq = m_p * m_q;
00145         Integer p2 = m_p * m_p;
00146         Integer r, z, re, a, w0, w1;
00147 
00148         do
00149         {
00150                 r.Randomize(rng, Integer::Zero(), pq);
00151                 z = x << (2*GetK()+2);
00152                 re = a_exp_b_mod_c(r, m_e, m_n);
00153                 a = (z - re) % m_n;
00154                 Integer::Divide(w1, w0, a, pq);
00155                 if (w1.NotZero())
00156                 {
00157                         ++w0;
00158                         w1 = pq - w1;
00159                 }
00160         }
00161         while ((w1 >> 2*GetK()+1).IsPositive());
00162 
00163         ModularArithmetic modp(m_p);
00164         Integer t = modp.Divide(w0 * r % m_p, m_e * re % m_p);
00165         Integer s = r + t*pq;
00166         assert(s < m_n);
00167 /*
00168         using namespace std;
00169         cout << "f = " << x << endl;
00170         cout << "r = " << r << endl;
00171         cout << "z = " << z << endl;
00172         cout << "a = " << a << endl;
00173         cout << "w0 = " << w0 << endl;
00174         cout << "w1 = " << w1 << endl;
00175         cout << "t = " << t << endl;
00176         cout << "s = " << s << endl;
00177 */
00178         return s;
00179 }
00180 
00181 bool InvertibleESIGNFunction::Validate(RandomNumberGenerator &rng, unsigned int level) const
00182 {
00183         bool pass = ESIGNFunction::Validate(rng, level);
00184         pass = pass && m_p > Integer::One() && m_p.IsOdd() && m_p < m_n;
00185         pass = pass && m_q > Integer::One() && m_q.IsOdd() && m_q < m_n;
00186         pass = pass && m_p.BitCount() == m_q.BitCount();
00187         if (level >= 1)
00188                 pass = pass && m_p * m_p * m_q == m_n;
00189         if (level >= 2)
00190                 pass = pass && VerifyPrime(rng, m_p, level-2) && VerifyPrime(rng, m_q, level-2);
00191         return pass;
00192 }
00193 
00194 bool InvertibleESIGNFunction::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
00195 {
00196         return GetValueHelper<ESIGNFunction>(this, name, valueType, pValue).Assignable()
00197                 CRYPTOPP_GET_FUNCTION_ENTRY(Prime1)
00198                 CRYPTOPP_GET_FUNCTION_ENTRY(Prime2)
00199                 ;
00200 }
00201 
00202 void InvertibleESIGNFunction::AssignFrom(const NameValuePairs &source)
00203 {
00204         AssignFromHelper<ESIGNFunction>(this, source)
00205                 CRYPTOPP_SET_FUNCTION_ENTRY(Prime1)
00206                 CRYPTOPP_SET_FUNCTION_ENTRY(Prime2)
00207                 ;
00208 }
00209 
00210 NAMESPACE_END

Generated on Sat Dec 23 02:07:07 2006 for Crypto++ by  doxygen 1.5.1-p1