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