1
// ec2n.cpp - written and placed in the public domain by Wei Dai
5
#ifndef CRYPTOPP_IMPORTS
10
#include "algebra.cpp"
11
#include "eprecomp.cpp"
13
NAMESPACE_BEGIN(CryptoPP)
15
EC2N::EC2N(BufferedTransformation &bt)
16
: m_field(BERDecodeGF2NP(bt))
18
BERSequenceDecoder seq(bt);
19
m_field->BERDecodeElement(seq, m_a);
20
m_field->BERDecodeElement(seq, m_b);
22
if (!seq.EndReached())
23
BERDecodeOctetString(seq, TheBitBucket());
27
void EC2N::DEREncode(BufferedTransformation &bt) const
29
m_field->DEREncode(bt);
30
DERSequenceEncoder seq(bt);
31
m_field->DEREncodeElement(seq, m_a);
32
m_field->DEREncodeElement(seq, m_b);
36
bool EC2N::DecodePoint(EC2N::Point &P, const byte *encodedPoint, size_t encodedPointLen) const
38
StringStore store(encodedPoint, encodedPointLen);
39
return DecodePoint(P, store, encodedPointLen);
42
bool EC2N::DecodePoint(EC2N::Point &P, BufferedTransformation &bt, size_t encodedPointLen) const
45
if (encodedPointLen < 1 || !bt.Get(type))
56
if (encodedPointLen != EncodedPointSize(true))
60
P.x.Decode(bt, m_field->MaxElementByteLength());
64
P.y = m_field->SquareRoot(m_b);
68
FieldElement z = m_field->Square(P.x);
69
assert(P.x == m_field->SquareRoot(z));
70
P.y = m_field->Divide(m_field->Add(m_field->Multiply(z, m_field->Add(P.x, m_a)), m_b), z);
71
assert(P.x == m_field->Subtract(m_field->Divide(m_field->Subtract(m_field->Multiply(P.y, z), m_b), z), m_a));
72
z = m_field->SolveQuadraticEquation(P.y);
73
assert(m_field->Add(m_field->Square(z), z) == P.y);
74
z.SetCoefficient(0, type & 1);
76
P.y = m_field->Multiply(z, P.x);
81
if (encodedPointLen != EncodedPointSize(false))
84
unsigned int len = m_field->MaxElementByteLength();
95
void EC2N::EncodePoint(BufferedTransformation &bt, const Point &P, bool compressed) const
98
NullStore().TransferTo(bt, EncodedPointSize(compressed));
101
bt.Put(2 + (!P.x ? 0 : m_field->Divide(P.y, P.x).GetBit(0)));
102
P.x.Encode(bt, m_field->MaxElementByteLength());
106
unsigned int len = m_field->MaxElementByteLength();
107
bt.Put(4); // uncompressed
113
void EC2N::EncodePoint(byte *encodedPoint, const Point &P, bool compressed) const
115
ArraySink sink(encodedPoint, EncodedPointSize(compressed));
116
EncodePoint(sink, P, compressed);
117
assert(sink.TotalPutLength() == EncodedPointSize(compressed));
120
EC2N::Point EC2N::BERDecodePoint(BufferedTransformation &bt) const
123
BERDecodeOctetString(bt, str);
125
if (!DecodePoint(P, str, str.size()))
130
void EC2N::DEREncodePoint(BufferedTransformation &bt, const Point &P, bool compressed) const
132
SecByteBlock str(EncodedPointSize(compressed));
133
EncodePoint(str, P, compressed);
134
DEREncodeOctetString(bt, str);
137
bool EC2N::ValidateParameters(RandomNumberGenerator &rng, unsigned int level) const
140
pass = pass && m_a.CoefficientCount() <= m_field->MaxElementBitLength();
141
pass = pass && m_b.CoefficientCount() <= m_field->MaxElementBitLength();
144
pass = pass && m_field->GetModulus().IsIrreducible();
149
bool EC2N::VerifyPoint(const Point &P) const
151
const FieldElement &x = P.x, &y = P.y;
153
(x.CoefficientCount() <= m_field->MaxElementBitLength()
154
&& y.CoefficientCount() <= m_field->MaxElementBitLength()
155
&& !(((x+m_a)*x*x+m_b-(x+y)*y)%m_field->GetModulus()));
158
bool EC2N::Equal(const Point &P, const Point &Q) const
160
if (P.identity && Q.identity)
163
if (P.identity && !Q.identity)
166
if (!P.identity && Q.identity)
169
return (m_field->Equal(P.x,Q.x) && m_field->Equal(P.y,Q.y));
172
const EC2N::Point& EC2N::Identity() const
174
return Singleton<Point>().Ref();
177
const EC2N::Point& EC2N::Inverse(const Point &P) const
183
m_R.identity = false;
184
m_R.y = m_field->Add(P.x, P.y);
190
const EC2N::Point& EC2N::Add(const Point &P, const Point &Q) const
192
if (P.identity) return Q;
193
if (Q.identity) return P;
194
if (Equal(P, Q)) return Double(P);
195
if (m_field->Equal(P.x, Q.x) && m_field->Equal(P.y, m_field->Add(Q.x, Q.y))) return Identity();
197
FieldElement t = m_field->Add(P.y, Q.y);
198
t = m_field->Divide(t, m_field->Add(P.x, Q.x));
199
FieldElement x = m_field->Square(t);
200
m_field->Accumulate(x, t);
201
m_field->Accumulate(x, Q.x);
202
m_field->Accumulate(x, m_a);
203
m_R.y = m_field->Add(P.y, m_field->Multiply(t, x));
204
m_field->Accumulate(x, P.x);
205
m_field->Accumulate(m_R.y, x);
208
m_R.identity = false;
212
const EC2N::Point& EC2N::Double(const Point &P) const
214
if (P.identity) return P;
215
if (!m_field->IsUnit(P.x)) return Identity();
217
FieldElement t = m_field->Divide(P.y, P.x);
218
m_field->Accumulate(t, P.x);
219
m_R.y = m_field->Square(P.x);
220
m_R.x = m_field->Square(t);
221
m_field->Accumulate(m_R.x, t);
222
m_field->Accumulate(m_R.x, m_a);
223
m_field->Accumulate(m_R.y, m_field->Multiply(t, m_R.x));
224
m_field->Accumulate(m_R.y, m_R.x);
226
m_R.identity = false;
230
// ********************************************************
233
EcPrecomputation<EC2N>& EcPrecomputation<EC2N>::operator=(const EcPrecomputation<EC2N> &rhs)
237
m_ep.m_group = m_ec.get();
241
void EcPrecomputation<EC2N>::SetCurveAndBase(const EC2N &ec, const EC2N::Point &base)
243
m_ec.reset(new EC2N(ec));
244
m_ep.SetGroupAndBase(*m_ec, base);
247
void EcPrecomputation<EC2N>::Precompute(unsigned int maxExpBits, unsigned int storage)
249
m_ep.Precompute(maxExpBits, storage);
252
void EcPrecomputation<EC2N>::Load(BufferedTransformation &bt)
254
BERSequenceDecoder seq(bt);
256
BERDecodeUnsigned<word32>(seq, version, INTEGER, 1, 1);
257
m_ep.m_exponentBase.BERDecode(seq);
258
m_ep.m_windowSize = m_ep.m_exponentBase.BitCount() - 1;
259
m_ep.m_bases.clear();
260
while (!seq.EndReached())
261
m_ep.m_bases.push_back(m_ec->BERDecodePoint(seq));
265
void EcPrecomputation<EC2N>::Save(BufferedTransformation &bt) const
267
DERSequenceEncoder seq(bt);
268
DEREncodeUnsigned<word32>(seq, 1); // version
269
m_ep.m_exponentBase.DEREncode(seq);
270
for (unsigned i=0; i<m_ep.m_bases.size(); i++)
271
m_ec->DEREncodePoint(seq, m_ep.m_bases[i]);
275
EC2N::Point EcPrecomputation<EC2N>::Exponentiate(const Integer &exponent) const
277
return m_ep.Exponentiate(exponent);
280
EC2N::Point EcPrecomputation<EC2N>::CascadeExponentiate(const Integer &exponent, const DL_FixedBasePrecomputation<Element> &pc2, const Integer &exponent2) const
282
return m_ep.CascadeExponentiate(exponent, static_cast<const EcPrecomputation<EC2N> &>(pc2).m_ep, exponent2);