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