00001
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
00018 emsa2BlockLen++;
00019 if (emsa2BlockLen % 8 > 1)
00020 {
00021 emsa2Block[0] = 0;
00022 emsa2Block++;
00023 }
00024 emsa2BlockLen /= 8;
00025
00026 emsa2Block[0] = input[0];
00027 memset(emsa2Block+1, 0xbb, emsa2BlockLen-inputLen-2);
00028 emsa2Block[emsa2BlockLen-inputLen-1] = 0xba;
00029 memcpy(emsa2Block+emsa2BlockLen-inputLen, input+1, inputLen-1);
00030 emsa2Block[emsa2BlockLen-1] = 0xcc;
00031 }
00032
00033 DecodingResult EMSA2Pad::Unpad(const byte *emsa2Block, unsigned int emsa2BlockLen, byte *output) const
00034 {
00035
00036 emsa2BlockLen++;
00037 if (emsa2BlockLen % 8 > 1)
00038 {
00039 if (emsa2Block[0] != 0)
00040 return DecodingResult();
00041 emsa2Block++;
00042 }
00043 emsa2BlockLen /= 8;
00044
00045
00046 if (emsa2Block[emsa2BlockLen-1] != 0xcc)
00047 return DecodingResult();
00048
00049
00050 unsigned i=1;
00051 while (i<emsa2BlockLen-1 && emsa2Block[i++] != 0xba)
00052 if (emsa2Block[i-1] != 0xbb)
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;
00088 const word r3b = (16 + 13 - r) % 16;
00089 const word r4 = (8 + 5 - r/2) % 8;
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
00141
00142
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