Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Namespace Members | Compound Members | File Members

# rw.cpp

    00001 // rw.cpp - written and placed in the public domain by Wei Dai
    00002
    00003 #include "pch.h"
    00004 #include "rw.h"
    00005 #include "nbtheory.h"
    00006 #include "asn.h"
    00007
    00008 NAMESPACE_BEGIN(CryptoPP)
    00009
    00010 template<> const byte EMSA2DigestDecoration<SHA>::decoration = 0x33;
    00011 template<> const byte EMSA2DigestDecoration<RIPEMD160>::decoration = 0x31;
    00012
    00013 void EMSA2Pad::Pad(RandomNumberGenerator &, const byte *input, unsigned int inputLen, byte *emsa2Block, unsigned int emsa2BlockLen) const
    00014 {
    00015         assert (inputLen > 0 && inputLen <= MaxUnpaddedLength(emsa2BlockLen));
    00016
    00017         // convert from bit length to byte length
    00018         emsa2BlockLen++;
    00019         if (emsa2BlockLen % 8 > 1)
    00020         {
    00021                 emsa2Block[0] = 0;
    00022                 emsa2Block++;
    00023         }
    00024         emsa2BlockLen /= 8;
    00025
    00026         emsa2Block[0] = input[0];                       // indicate empty or non-empty message
    00027         memset(emsa2Block+1, 0xbb, emsa2BlockLen-inputLen-2);   // padd with 0xbb
    00028         emsa2Block[emsa2BlockLen-inputLen-1] = 0xba;    // separator
    00029         memcpy(emsa2Block+emsa2BlockLen-inputLen, input+1, inputLen-1);
    00030         emsa2Block[emsa2BlockLen-1] = 0xcc;     // make it congruent to 12 mod 16
    00031 }
    00032
    00033 DecodingResult EMSA2Pad::Unpad(const byte *emsa2Block, unsigned int emsa2BlockLen, byte *output) const
    00034 {
    00035         // convert from bit length to byte length
    00036         emsa2BlockLen++;
    00037         if (emsa2BlockLen % 8 > 1)
    00038         {
    00039                 if (emsa2Block[0] != 0)
    00040                         return DecodingResult();
    00041                 emsa2Block++;
    00042         }
    00043         emsa2BlockLen /= 8;
    00044
    00045         // check last byte
    00046         if (emsa2Block[emsa2BlockLen-1] != 0xcc)
    00047                 return DecodingResult();
    00048
    00049         // skip past the padding until we find the seperator
    00050         unsigned i=1;
    00051         while (i<emsa2BlockLen-1 && emsa2Block[i++] != 0xba)
    00052                 if (emsa2Block[i-1] != 0xbb)     // not valid padding
    00053                         return DecodingResult();
    00054         assert(i==emsa2BlockLen-1 || emsa2Block[i-1]==0xba);
    00055
    00056         unsigned int outputLen = emsa2BlockLen - i;
    00057         output[0] = emsa2Block[0];
    00058         memcpy (output+1, emsa2Block+i, outputLen-1);
    00059         return DecodingResult(outputLen);
    00060 }
    00061
    00062 // *****************************************************************************
    00063
    00064 template <word r>
    00065 void RWFunction<r>::BERDecode(BufferedTransformation &bt)
    00066 {
    00067         BERSequenceDecoder seq(bt);
    00068         m_n.BERDecode(seq);
    00069         seq.MessageEnd();
    00070 }
    00071
    00072 template <word r>
    00073 void RWFunction<r>::DEREncode(BufferedTransformation &bt) const
    00074 {
    00075         DERSequenceEncoder seq(bt);
    00076         m_n.DEREncode(seq);
    00077         seq.MessageEnd();
    00078 }
    00079
    00080 template <word r>
    00081 Integer RWFunction<r>::ApplyFunction(const Integer &in) const
    00082 {
    00083         DoQuickSanityCheck();
    00084
    00085         Integer out = in.Squared()%m_n;
    00086         const word r2 = r/2;
    00087         const word r3a = (16 + 5 - r) % 16;     // n%16 could be 5 or 13
    00088         const word r3b = (16 + 13 - r) % 16;
    00089         const word r4 = (8 + 5 - r/2) % 8;      // n%8 == 5
    00090         switch (out % 16)
    00091         {
    00092         case r:
    00093                 break;
    00094         case r2:
    00095         case r2+8:
    00096                 out <<= 1;
    00097                 break;
    00098         case r3a:
    00099         case r3b:
    00100                 out.Negate();
    00101                 out += m_n;
    00102                 break;
    00103         case r4:
    00104         case r4+8:
    00105                 out.Negate();
    00106                 out += m_n;
    00107                 out <<= 1;
    00108                 break;
    00109         default:
    00110                 out = Integer::Zero();
    00111         }
    00112         return out;
    00113 }
    00114
    00115 template <word r>
    00116 bool RWFunction<r>::Validate(RandomNumberGenerator &rng, unsigned int level) const
    00117 {
    00118         bool pass = true;
    00119         pass = pass && m_n > Integer::One() && m_n%8 == 5;
    00120         return pass;
    00121 }
    00122
    00123 template <word r>
    00124 bool RWFunction<r>::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
    00125 {
    00126         return GetValueHelper(this, name, valueType, pValue).Assignable()
    00127                 CRYPTOPP_GET_FUNCTION_ENTRY(Modulus)
    00128                 ;
    00129 }
    00130
    00131 template <word r>
    00132 void RWFunction<r>::AssignFrom(const NameValuePairs &source)
    00133 {
    00134         AssignFromHelper(this, source)
    00135                 CRYPTOPP_SET_FUNCTION_ENTRY(Modulus)
    00136                 ;
    00137 }
    00138
    00139 // *****************************************************************************
    00140 // private key operations:
    00141
    00142 // generate a random private key
    00143 template <word r>
    00144 void InvertibleRWFunction<r>::GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg)
    00145 {
    00146         int modulusSize = 2048;
    00147         alg.GetIntValue("ModulusSize", modulusSize) || alg.GetIntValue("KeySize", modulusSize);
    00148
    00149         if (modulusSize < 16)
    00150                 throw InvalidArgument("InvertibleRWFunction: specified modulus length is too small");
    00151
    00152         const NameValuePairs &primeParam = MakeParametersForTwoPrimesOfEqualSize(modulusSize);
    00153         m_p.GenerateRandom(rng, CombinedNameValuePairs(primeParam, MakeParameters("EquivalentTo", 3)("Mod", 8)));
    00154         m_q.GenerateRandom(rng, CombinedNameValuePairs(primeParam, MakeParameters("EquivalentTo", 7)("Mod", 8)));
    00155
    00156         m_n = m_p * m_q;
    00157         m_u = m_q.InverseMod(m_p);
    00158 }
    00159
    00160 template <word r>
    00161 void InvertibleRWFunction<r>::BERDecode(BufferedTransformation &bt)
    00162 {
    00163         BERSequenceDecoder seq(bt);
    00164         m_n.BERDecode(seq);
    00165         m_p.BERDecode(seq);
    00166         m_q.BERDecode(seq);
    00167         m_u.BERDecode(seq);
    00168         seq.MessageEnd();
    00169 }
    00170
    00171 template <word r>
    00172 void InvertibleRWFunction<r>::DEREncode(BufferedTransformation &bt) const
    00173 {
    00174         DERSequenceEncoder seq(bt);
    00175         m_n.DEREncode(seq);
    00176         m_p.DEREncode(seq);
    00177         m_q.DEREncode(seq);
    00178         m_u.DEREncode(seq);
    00179         seq.MessageEnd();
    00180 }
    00181
    00182 template <word r>
    00183 Integer InvertibleRWFunction<r>::CalculateInverse(const Integer &in) const
    00184 {
    00185         DoQuickSanityCheck();
    00186
    00187         Integer cp=in%m_p, cq=in%m_q;
    00188
    00189         if (Jacobi(cp, m_p) * Jacobi(cq, m_q) != 1)
    00190         {
    00191                 cp = cp%2 ? (cp+m_p) >> 1 : cp >> 1;
    00192                 cq = cq%2 ? (cq+m_q) >> 1 : cq >> 1;
    00193         }
    00194
    00195         cp = ModularSquareRoot(cp, m_p);
    00196         cq = ModularSquareRoot(cq, m_q);
    00197
    00198         Integer out = CRT(cq, m_q, cp, m_p, m_u);
    00199
    00200         return STDMIN(out, m_n-out);
    00201 }
    00202
    00203 template <word r>
    00204 bool InvertibleRWFunction<r>::Validate(RandomNumberGenerator &rng, unsigned int level) const
    00205 {
    00206         bool pass = RWFunction<r>::Validate(rng, level);
    00207         pass = pass && m_p > Integer::One() && m_p%8 == 3 && m_p < m_n;
    00208         pass = pass && m_q > Integer::One() && m_q%8 == 7 && m_q < m_n;
    00209         pass = pass && m_u.IsPositive() && m_u < m_p;
    00210         if (level >= 1)
    00211         {
    00212                 pass = pass && m_p * m_q == m_n;
    00213                 pass = pass && m_u * m_q % m_p == 1;
    00214         }
    00215         if (level >= 2)
    00216                 pass = pass && VerifyPrime(rng, m_p, level-2) && VerifyPrime(rng, m_q, level-2);
    00217         return pass;
    00218 }
    00219
    00220 template <word r>
    00221 bool InvertibleRWFunction<r>::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
    00222 {
    00223         return GetValueHelper<RWFunction<r> >(this, name, valueType, pValue).Assignable()
    00224                 CRYPTOPP_GET_FUNCTION_ENTRY(Prime1)
    00225                 CRYPTOPP_GET_FUNCTION_ENTRY(Prime2)
    00226                 CRYPTOPP_GET_FUNCTION_ENTRY(MultiplicativeInverseOfPrime2ModPrime1)
    00227                 ;
    00228 }
    00229
    00230 template <word r>
    00231 void InvertibleRWFunction<r>::AssignFrom(const NameValuePairs &source)
    00232 {
    00233         AssignFromHelper<RWFunction<r> >(this, source)
    00234                 CRYPTOPP_SET_FUNCTION_ENTRY(Prime1)
    00235                 CRYPTOPP_SET_FUNCTION_ENTRY(Prime2)
    00236                 CRYPTOPP_SET_FUNCTION_ENTRY(MultiplicativeInverseOfPrime2ModPrime1)
    00237                 ;
    00238 }
    00239
    00240 template class RWFunction<IFSSA_R>;
    00241 template class InvertibleRWFunction<IFSSA_R>;
    00242
    00243 NAMESPACE_END