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