00001
00002
00003 #include "pch.h"
00004 #include "ec2n.h"
00005 #include "asn.h"
00006 #include "nbtheory.h"
00007
00008 #include "algebra.cpp"
00009 #include "eprecomp.cpp"
00010
00011 NAMESPACE_BEGIN(CryptoPP)
00012
00013 EC2N::EC2N(BufferedTransformation &bt)
00014 : m_field(BERDecodeGF2NP(bt))
00015 {
00016 BERSequenceDecoder seq(bt);
00017 m_field->BERDecodeElement(seq, m_a);
00018 m_field->BERDecodeElement(seq, m_b);
00019
00020 if (!seq.EndReached())
00021 BERDecodeOctetString(seq, g_bitBucket);
00022 seq.MessageEnd();
00023 }
00024
00025 void EC2N::DEREncode(BufferedTransformation &bt) const
00026 {
00027 m_field->DEREncode(bt);
00028 DERSequenceEncoder seq(bt);
00029 m_field->DEREncodeElement(seq, m_a);
00030 m_field->DEREncodeElement(seq, m_b);
00031 seq.MessageEnd();
00032 }
00033
00034 bool EC2N::DecodePoint(EC2N::Point &P, const byte *encodedPoint, unsigned int encodedPointLen) const
00035 {
00036 StringStore store(encodedPoint, encodedPointLen);
00037 return DecodePoint(P, store, encodedPointLen);
00038 }
00039
00040 bool EC2N::DecodePoint(EC2N::Point &P, BufferedTransformation &bt, unsigned int encodedPointLen) const
00041 {
00042 byte type;
00043 if (encodedPointLen < 1 || !bt.Get(type))
00044 return false;
00045
00046 switch (type)
00047 {
00048 case 0:
00049 P.identity = true;
00050 return true;
00051 case 2:
00052 case 3:
00053 {
00054 if (encodedPointLen != EncodedPointSize(true))
00055 return false;
00056
00057 P.identity = false;
00058 P.x.Decode(bt, m_field->MaxElementByteLength());
00059
00060 if (P.x.IsZero())
00061 {
00062 P.y = m_field->SquareRoot(m_b);
00063 return true;
00064 }
00065
00066 FieldElement z = m_field->Square(P.x);
00067 assert(P.x == m_field->SquareRoot(z));
00068 P.y = m_field->Divide(m_field->Add(m_field->Multiply(z, m_field->Add(P.x, m_a)), m_b), z);
00069 assert(P.x == m_field->Subtract(m_field->Divide(m_field->Subtract(m_field->Multiply(P.y, z), m_b), z), m_a));
00070 z = m_field->SolveQuadraticEquation(P.y);
00071 assert(m_field->Add(m_field->Square(z), z) == P.y);
00072 z.SetCoefficient(0, type & 1);
00073
00074 P.y = m_field->Multiply(z, P.x);
00075 return true;
00076 }
00077 case 4:
00078 {
00079 if (encodedPointLen != EncodedPointSize(false))
00080 return false;
00081
00082 unsigned int len = m_field->MaxElementByteLength();
00083 P.identity = false;
00084 P.x.Decode(bt, len);
00085 P.y.Decode(bt, len);
00086 return true;
00087 }
00088 default:
00089 return false;
00090 }
00091 }
00092
00093 void EC2N::EncodePoint(byte *encodedPoint, const Point &P, bool compressed) const
00094 {
00095 if (P.identity)
00096 memset(encodedPoint, 0, EncodedPointSize(compressed));
00097 else if (compressed)
00098 {
00099 encodedPoint[0] = 2 + (!P.x ? 0 : m_field->Divide(P.y, P.x).GetBit(0));
00100 P.x.Encode(encodedPoint+1, m_field->MaxElementByteLength());
00101 }
00102 else
00103 {
00104 unsigned int len = m_field->MaxElementByteLength();
00105 encodedPoint[0] = 4;
00106 P.x.Encode(encodedPoint+1, len);
00107 P.y.Encode(encodedPoint+1+len, len);
00108 }
00109 }
00110
00111 EC2N::Point EC2N::BERDecodePoint(BufferedTransformation &bt) const
00112 {
00113 SecByteBlock str;
00114 BERDecodeOctetString(bt, str);
00115 Point P;
00116 if (!DecodePoint(P, str, str.size))
00117 BERDecodeError();
00118 return P;
00119 }
00120
00121 void EC2N::DEREncodePoint(BufferedTransformation &bt, const Point &P, bool compressed) const
00122 {
00123 SecByteBlock str(EncodedPointSize(compressed));
00124 EncodePoint(str, P, compressed);
00125 DEREncodeOctetString(bt, str);
00126 }
00127
00128 bool EC2N::ValidateParameters(RandomNumberGenerator &rng) const
00129 {
00130 return m_field->GetModulus().IsIrreducible()
00131 && m_a.CoefficientCount() <= m_field->MaxElementBitLength()
00132 && m_b.CoefficientCount() <= m_field->MaxElementBitLength() && !!m_b;
00133 }
00134
00135 bool EC2N::VerifyPoint(const Point &P) const
00136 {
00137 const FieldElement &x = P.x, &y = P.y;
00138 return P.identity ||
00139 (x.CoefficientCount() <= m_field->MaxElementBitLength()
00140 && y.CoefficientCount() <= m_field->MaxElementBitLength()
00141 && !(((x+m_a)*x*x+m_b-(x+y)*y)%m_field->GetModulus()));
00142 }
00143
00144 bool EC2N::Equal(const Point &P, const Point &Q) const
00145 {
00146 if (P.identity && Q.identity)
00147 return true;
00148
00149 if (P.identity && !Q.identity)
00150 return false;
00151
00152 if (!P.identity && Q.identity)
00153 return false;
00154
00155 return (m_field->Equal(P.x,Q.x) && m_field->Equal(P.y,Q.y));
00156 }
00157
00158 const EC2N::Point& EC2N::Inverse(const Point &P) const
00159 {
00160 if (P.identity)
00161 return P;
00162 else
00163 {
00164 m_R.identity = false;
00165 m_R.y = m_field->Add(P.x, P.y);
00166 m_R.x = P.x;
00167 return m_R;
00168 }
00169 }
00170
00171 const EC2N::Point& EC2N::Add(const Point &P, const Point &Q) const
00172 {
00173 if (P.identity) return Q;
00174 if (Q.identity) return P;
00175 if (Equal(P, Q)) return Double(P);
00176 if (m_field->Equal(P.x, Q.x) && m_field->Equal(P.y, m_field->Add(Q.x, Q.y))) return Zero();
00177
00178 FieldElement t = m_field->Add(P.y, Q.y);
00179 t = m_field->Divide(t, m_field->Add(P.x, Q.x));
00180 FieldElement x = m_field->Square(t);
00181 m_field->Accumulate(x, t);
00182 m_field->Accumulate(x, Q.x);
00183 m_field->Accumulate(x, m_a);
00184 m_R.y = m_field->Add(P.y, m_field->Multiply(t, x));
00185 m_field->Accumulate(x, P.x);
00186 m_field->Accumulate(m_R.y, x);
00187
00188 m_R.x.swap(x);
00189 m_R.identity = false;
00190 return m_R;
00191 }
00192
00193 const EC2N::Point& EC2N::Double(const Point &P) const
00194 {
00195 if (P.identity) return P;
00196 if (!m_field->IsUnit(P.x)) return Zero();
00197
00198 FieldElement t = m_field->Divide(P.y, P.x);
00199 m_field->Accumulate(t, P.x);
00200 m_R.y = m_field->Square(P.x);
00201 m_R.x = m_field->Square(t);
00202 m_field->Accumulate(m_R.x, t);
00203 m_field->Accumulate(m_R.x, m_a);
00204 m_field->Accumulate(m_R.y, m_field->Multiply(t, m_R.x));
00205 m_field->Accumulate(m_R.y, m_R.x);
00206
00207 m_R.identity = false;
00208 return m_R;
00209 }
00210
00211
00212
00213 EcPrecomputation<EC2N>& EcPrecomputation<EC2N>::operator=(const EcPrecomputation<EC2N> &rhs)
00214 {
00215 m_ec = rhs.m_ec;
00216 m_ep = rhs.m_ep;
00217 m_ep.m_group = m_ec.get();
00218 return *this;
00219 }
00220
00221 void EcPrecomputation<EC2N>::SetCurveAndBase(const EC2N &ec, const EC2N::Point &base)
00222 {
00223 m_ec.reset(new EC2N(ec));
00224 m_ep.SetGroupAndBase(*m_ec, base);
00225 }
00226
00227 void EcPrecomputation<EC2N>::Precompute(unsigned int maxExpBits, unsigned int storage)
00228 {
00229 m_ep.Precompute(maxExpBits, storage);
00230 }
00231
00232 void EcPrecomputation<EC2N>::Load(BufferedTransformation &bt)
00233 {
00234 BERSequenceDecoder seq(bt);
00235 word32 version;
00236 BERDecodeUnsigned<word32>(seq, version, INTEGER, 1, 1);
00237 m_ep.m_exponentBase.BERDecode(seq);
00238 m_ep.m_windowSize = m_ep.m_exponentBase.BitCount() - 1;
00239 m_ep.m_bases.clear();
00240 while (!seq.EndReached())
00241 m_ep.m_bases.push_back(m_ec->BERDecodePoint(seq));
00242 seq.MessageEnd();
00243 }
00244
00245 void EcPrecomputation<EC2N>::Save(BufferedTransformation &bt) const
00246 {
00247 DERSequenceEncoder seq(bt);
00248 DEREncodeUnsigned<word32>(seq, 1);
00249 m_ep.m_exponentBase.DEREncode(seq);
00250 for (unsigned i=0; i<m_ep.m_bases.size(); i++)
00251 m_ec->DEREncodePoint(seq, m_ep.m_bases[i]);
00252 seq.MessageEnd();
00253 }
00254
00255 EC2N::Point EcPrecomputation<EC2N>::Multiply(const Integer &exponent) const
00256 {
00257 return m_ep.Exponentiate(exponent);
00258 }
00259
00260 EC2N::Point EcPrecomputation<EC2N>::CascadeMultiply(const Integer &exponent, const EcPrecomputation<EC2N> &pc2, const Integer &exponent2) const
00261 {
00262 return m_ep.CascadeExponentiate(exponent, pc2.m_ep, exponent2);
00263 }
00264
00265 NAMESPACE_END