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