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

Generated on Tue Jul 8 23:34:24 2003 for Crypto++ by doxygen 1.3.2