- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

# 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