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,
unsigned int 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,
unsigned int 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