Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

ec2n.cpp

00001 // ec2n.cpp - written and placed in the public domain by Wei Dai
00002 
00003 #include "pch.h"
00004 #include "ec2n.h"
00005 #include "asn.h"
00006 #include "nbtheory.h"   // for primeTable
00007 
00008 #include "algebra.cpp"
00009 #include "eprecomp.cpp"
00010 
00011 NAMESPACE_BEGIN(CryptoPP)
00012 
00013 EC2N::EC2N(BufferedTransformation &bt)
00014         : m_field(BERDecodeGF2NP(bt))
00015 {
00016         BERSequenceDecoder seq(bt);
00017         m_field->BERDecodeElement(seq, m_a);
00018         m_field->BERDecodeElement(seq, m_b);
00019         // skip optional seed
00020         if (!seq.EndReached())
00021                 BERDecodeOctetString(seq, g_bitBucket);
00022         seq.MessageEnd();
00023 }
00024 
00025 void EC2N::DEREncode(BufferedTransformation &bt) const
00026 {
00027         m_field->DEREncode(bt);
00028         DERSequenceEncoder seq(bt);
00029         m_field->DEREncodeElement(seq, m_a);
00030         m_field->DEREncodeElement(seq, m_b);
00031         seq.MessageEnd();
00032 }
00033 
00034 bool EC2N::DecodePoint(EC2N::Point &P, const byte *encodedPoint, unsigned int encodedPointLen) const
00035 {
00036         StringStore store(encodedPoint, encodedPointLen);
00037         return DecodePoint(P, store, encodedPointLen);
00038 }
00039 
00040 bool EC2N::DecodePoint(EC2N::Point &P, BufferedTransformation &bt, unsigned int encodedPointLen) const
00041 {
00042         byte type;
00043         if (encodedPointLen < 1 || !bt.Get(type))
00044                 return false;
00045 
00046         switch (type)
00047         {
00048         case 0:
00049                 P.identity = true;
00050                 return true;
00051         case 2:
00052         case 3:
00053         {
00054                 if (encodedPointLen != EncodedPointSize(true))
00055                         return false;
00056 
00057                 P.identity = false;
00058                 P.x.Decode(bt, m_field->MaxElementByteLength()); 
00059 
00060                 if (P.x.IsZero())
00061                 {
00062                         P.y = m_field->SquareRoot(m_b);
00063                         return true;
00064                 }
00065 
00066                 FieldElement z = m_field->Square(P.x);
00067                 assert(P.x == m_field->SquareRoot(z));
00068                 P.y = m_field->Divide(m_field->Add(m_field->Multiply(z, m_field->Add(P.x, m_a)), m_b), z);
00069                 assert(P.x == m_field->Subtract(m_field->Divide(m_field->Subtract(m_field->Multiply(P.y, z), m_b), z), m_a));
00070                 z = m_field->SolveQuadraticEquation(P.y);
00071                 assert(m_field->Add(m_field->Square(z), z) == P.y);
00072                 z.SetCoefficient(0, type & 1);
00073 
00074                 P.y = m_field->Multiply(z, P.x);
00075                 return true;
00076         }
00077         case 4:
00078         {
00079                 if (encodedPointLen != EncodedPointSize(false))
00080                         return false;
00081 
00082                 unsigned int len = m_field->MaxElementByteLength();
00083                 P.identity = false;
00084                 P.x.Decode(bt, len);
00085                 P.y.Decode(bt, len);
00086                 return true;
00087         }
00088         default:
00089                 return false;
00090         }
00091 }
00092 
00093 void EC2N::EncodePoint(byte *encodedPoint, const Point &P, bool compressed) const
00094 {
00095         if (P.identity)
00096                 memset(encodedPoint, 0, EncodedPointSize(compressed));
00097         else if (compressed)
00098         {
00099                 encodedPoint[0] = 2 + (!P.x ? 0 : m_field->Divide(P.y, P.x).GetBit(0));
00100                 P.x.Encode(encodedPoint+1, m_field->MaxElementByteLength());
00101         }
00102         else
00103         {
00104                 unsigned int len = m_field->MaxElementByteLength();
00105                 encodedPoint[0] = 4;    // uncompressed
00106                 P.x.Encode(encodedPoint+1, len);
00107                 P.y.Encode(encodedPoint+1+len, len);
00108         }
00109 }
00110 
00111 EC2N::Point EC2N::BERDecodePoint(BufferedTransformation &bt) const
00112 {
00113         SecByteBlock str;
00114         BERDecodeOctetString(bt, str);
00115         Point P;
00116         if (!DecodePoint(P, str, str.size))
00117                 BERDecodeError();
00118         return P;
00119 }
00120 
00121 void EC2N::DEREncodePoint(BufferedTransformation &bt, const Point &P, bool compressed) const
00122 {
00123         SecByteBlock str(EncodedPointSize(compressed));
00124         EncodePoint(str, P, compressed);
00125         DEREncodeOctetString(bt, str);
00126 }
00127 
00128 bool EC2N::ValidateParameters(RandomNumberGenerator &rng) const
00129 {
00130         return m_field->GetModulus().IsIrreducible()
00131                 && m_a.CoefficientCount() <= m_field->MaxElementBitLength()
00132                 && m_b.CoefficientCount() <= m_field->MaxElementBitLength() && !!m_b;
00133 }
00134 
00135 bool EC2N::VerifyPoint(const Point &P) const
00136 {
00137         const FieldElement &x = P.x, &y = P.y;
00138         return P.identity || 
00139                 (x.CoefficientCount() <= m_field->MaxElementBitLength()
00140                 && y.CoefficientCount() <= m_field->MaxElementBitLength()
00141                 && !(((x+m_a)*x*x+m_b-(x+y)*y)%m_field->GetModulus()));
00142 }
00143 
00144 bool EC2N::Equal(const Point &P, const Point &Q) const
00145 {
00146         if (P.identity && Q.identity)
00147                 return true;
00148 
00149         if (P.identity && !Q.identity)
00150                 return false;
00151 
00152         if (!P.identity && Q.identity)
00153                 return false;
00154 
00155         return (m_field->Equal(P.x,Q.x) && m_field->Equal(P.y,Q.y));
00156 }
00157 
00158 const EC2N::Point& EC2N::Inverse(const Point &P) const
00159 {
00160         if (P.identity)
00161                 return P;
00162         else
00163         {
00164                 m_R.identity = false;
00165                 m_R.y = m_field->Add(P.x, P.y);
00166                 m_R.x = P.x;
00167                 return m_R;
00168         }
00169 }
00170 
00171 const EC2N::Point& EC2N::Add(const Point &P, const Point &Q) const
00172 {
00173         if (P.identity) return Q;
00174         if (Q.identity) return P;
00175         if (Equal(P, Q)) return Double(P);
00176         if (m_field->Equal(P.x, Q.x) && m_field->Equal(P.y, m_field->Add(Q.x, Q.y))) return Zero();
00177 
00178         FieldElement t = m_field->Add(P.y, Q.y);
00179         t = m_field->Divide(t, m_field->Add(P.x, Q.x));
00180         FieldElement x = m_field->Square(t);
00181         m_field->Accumulate(x, t);
00182         m_field->Accumulate(x, Q.x);
00183         m_field->Accumulate(x, m_a);
00184         m_R.y = m_field->Add(P.y, m_field->Multiply(t, x));
00185         m_field->Accumulate(x, P.x);
00186         m_field->Accumulate(m_R.y, x);
00187 
00188         m_R.x.swap(x);
00189         m_R.identity = false;
00190         return m_R;
00191 }
00192 
00193 const EC2N::Point& EC2N::Double(const Point &P) const
00194 {
00195         if (P.identity) return P;
00196         if (!m_field->IsUnit(P.x)) return Zero();
00197 
00198         FieldElement t = m_field->Divide(P.y, P.x);
00199         m_field->Accumulate(t, P.x);
00200         m_R.y = m_field->Square(P.x);
00201         m_R.x = m_field->Square(t);
00202         m_field->Accumulate(m_R.x, t);
00203         m_field->Accumulate(m_R.x, m_a);
00204         m_field->Accumulate(m_R.y, m_field->Multiply(t, m_R.x));
00205         m_field->Accumulate(m_R.y, m_R.x);
00206 
00207         m_R.identity = false;
00208         return m_R;
00209 }
00210 
00211 // ********************************************************
00212 
00213 EcPrecomputation<EC2N>& EcPrecomputation<EC2N>::operator=(const EcPrecomputation<EC2N> &rhs)
00214 {
00215         m_ec = rhs.m_ec;
00216         m_ep = rhs.m_ep;
00217         m_ep.m_group = m_ec.get();
00218         return *this;
00219 }
00220 
00221 void EcPrecomputation<EC2N>::SetCurveAndBase(const EC2N &ec, const EC2N::Point &base)
00222 {
00223         m_ec.reset(new EC2N(ec));
00224         m_ep.SetGroupAndBase(*m_ec, base);
00225 }
00226 
00227 void EcPrecomputation<EC2N>::Precompute(unsigned int maxExpBits, unsigned int storage)
00228 {
00229         m_ep.Precompute(maxExpBits, storage);
00230 }
00231 
00232 void EcPrecomputation<EC2N>::Load(BufferedTransformation &bt)
00233 {
00234         BERSequenceDecoder seq(bt);
00235         word32 version;
00236         BERDecodeUnsigned<word32>(seq, version, INTEGER, 1, 1);
00237         m_ep.m_exponentBase.BERDecode(seq);
00238         m_ep.m_windowSize = m_ep.m_exponentBase.BitCount() - 1;
00239         m_ep.m_bases.clear();
00240         while (!seq.EndReached())
00241                 m_ep.m_bases.push_back(m_ec->BERDecodePoint(seq));
00242         seq.MessageEnd();
00243 }
00244 
00245 void EcPrecomputation<EC2N>::Save(BufferedTransformation &bt) const
00246 {
00247         DERSequenceEncoder seq(bt);
00248         DEREncodeUnsigned<word32>(seq, 1);      // version
00249         m_ep.m_exponentBase.DEREncode(seq);
00250         for (unsigned i=0; i<m_ep.m_bases.size(); i++)
00251                 m_ec->DEREncodePoint(seq, m_ep.m_bases[i]);
00252         seq.MessageEnd();
00253 }
00254 
00255 EC2N::Point EcPrecomputation<EC2N>::Multiply(const Integer &exponent) const
00256 {
00257         return m_ep.Exponentiate(exponent);
00258 }
00259 
00260 EC2N::Point EcPrecomputation<EC2N>::CascadeMultiply(const Integer &exponent, const EcPrecomputation<EC2N> &pc2, const Integer &exponent2) const
00261 {
00262         return m_ep.CascadeExponentiate(exponent, pc2.m_ep, exponent2);
00263 }
00264 
00265 NAMESPACE_END

Generated at Mon Jan 15 01:16:31 2001 for Crypto++ by doxygen1.2.4 written by Dimitri van Heesch, © 1997-2000