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

gf2n.cpp

00001 // gf2n.cpp - written and placed in the public domain by Wei Dai
00002 
00003 #include "pch.h"
00004 #include "gf2n.h"
00005 #include "algebra.h"
00006 #include "words.h"
00007 #include "rng.h"
00008 #include "asn.h"
00009 #include "oids.h"
00010 
00011 #include <iostream>
00012 
00013 #include "algebra.cpp"
00014 
00015 NAMESPACE_BEGIN(CryptoPP)
00016 
00017 PolynomialMod2::PolynomialMod2()
00018 {
00019 }
00020 
00021 PolynomialMod2::PolynomialMod2(word value, unsigned int bitLength)
00022         : reg(bitsToWords(bitLength))
00023 {
00024         assert(value==0 || reg.size>0);
00025 
00026         if (reg.size > 0)
00027         {
00028                 reg[0] = value;
00029                 SetWords(reg+1, 0, reg.size-1);
00030         }
00031 }
00032 
00033 PolynomialMod2::PolynomialMod2(const PolynomialMod2& t)
00034         : reg(t.reg.size)
00035 {
00036         CopyWords(reg, t.reg, reg.size);
00037 }
00038 
00039 void PolynomialMod2::Randomize(RandomNumberGenerator &rng, unsigned int nbits)
00040 {
00041         const unsigned int nbytes = nbits/8 + 1;
00042         SecByteBlock buf(nbytes);
00043         rng.GetBlock(buf, nbytes);
00044         buf[0] = (byte)Crop(buf[0], nbits % 8);
00045         Decode(buf, nbytes);
00046 }
00047 
00048 PolynomialMod2 PolynomialMod2::AllOnes(unsigned int bitLength)
00049 {
00050         PolynomialMod2 result((word)0, bitLength);
00051         SetWords(result.reg, ~(word)0, result.reg.size);
00052         if (bitLength%WORD_BITS)
00053                 result.reg[result.reg.size-1] = (word)Crop(result.reg[result.reg.size-1], bitLength%WORD_BITS);
00054         return result;
00055 }
00056 
00057 void PolynomialMod2::SetBit(unsigned int n, int value)
00058 {
00059         if (value)
00060         {
00061                 reg.CleanGrow(n/WORD_BITS + 1);
00062                 reg[n/WORD_BITS] |= (word(1) << (n%WORD_BITS));
00063         }
00064         else
00065         {
00066                 if (n/WORD_BITS < reg.size)
00067                         reg[n/WORD_BITS] &= ~(word(1) << (n%WORD_BITS));
00068         }
00069 }
00070 
00071 byte PolynomialMod2::GetByte(unsigned int n) const
00072 {
00073         if (n/WORD_SIZE >= reg.size)
00074                 return 0;
00075         else
00076                 return byte(reg[n/WORD_SIZE] >> ((n%WORD_SIZE)*8));
00077 }
00078 
00079 void PolynomialMod2::SetByte(unsigned int n, byte value)
00080 {
00081         reg.CleanGrow(bytesToWords(n+1));
00082         reg[n/WORD_SIZE] &= ~(word(0xff) << 8*(n%WORD_SIZE));
00083         reg[n/WORD_SIZE] |= (word(value) << 8*(n%WORD_SIZE));
00084 }
00085 
00086 PolynomialMod2 PolynomialMod2::Monomial(unsigned i) 
00087 {
00088         PolynomialMod2 r((word)0, i+1); 
00089         r.SetBit(i); 
00090         return r;
00091 }
00092 
00093 PolynomialMod2 PolynomialMod2::Trinomial(unsigned t0, unsigned t1, unsigned t2) 
00094 {
00095         PolynomialMod2 r((word)0, t0+1);
00096         r.SetBit(t0);
00097         r.SetBit(t1);
00098         r.SetBit(t2);
00099         return r;
00100 }
00101 
00102 PolynomialMod2 PolynomialMod2::Pentanomial(unsigned t0, unsigned t1, unsigned t2, unsigned int t3, unsigned int t4)
00103 {
00104         PolynomialMod2 r((word)0, t0+1);
00105         r.SetBit(t0);
00106         r.SetBit(t1);
00107         r.SetBit(t2);
00108         r.SetBit(t3);
00109         r.SetBit(t4);
00110         return r;
00111 }
00112 
00113 const PolynomialMod2 &PolynomialMod2::Zero()
00114 {
00115         static const PolynomialMod2 zero;
00116         return zero;
00117 }
00118 
00119 const PolynomialMod2 &PolynomialMod2::One()
00120 {
00121         static const PolynomialMod2 one = 1;
00122         return one;
00123 }
00124 
00125 void PolynomialMod2::Decode(const byte *input, unsigned int inputLen)
00126 {
00127         StringStore store(input, inputLen);
00128         Decode(store, inputLen);
00129 }
00130 
00131 unsigned int PolynomialMod2::Encode(byte *output, unsigned int outputLen) const
00132 {
00133         ArraySink sink(output, outputLen);
00134         return Encode(sink, outputLen);
00135 }
00136 
00137 void PolynomialMod2::Decode(BufferedTransformation &bt, unsigned int inputLen)
00138 {
00139         reg.CleanNew(bytesToWords(inputLen));
00140 
00141         for (unsigned int i=inputLen; i > 0; i--)
00142         {
00143                 byte b;
00144                 bt.Get(b);
00145                 reg[(i-1)/WORD_SIZE] |= b << ((i-1)%WORD_SIZE)*8;
00146         }
00147 }
00148 
00149 unsigned int PolynomialMod2::Encode(BufferedTransformation &bt, unsigned int outputLen) const
00150 {
00151         for (unsigned int i=outputLen; i > 0; i--)
00152                 bt.Put(GetByte(i-1));
00153         return outputLen;
00154 }
00155 
00156 void PolynomialMod2::DEREncodeAsOctetString(BufferedTransformation &bt, unsigned int length) const
00157 {
00158         DERGeneralEncoder enc(bt, OCTET_STRING);
00159         Encode(enc, length);
00160         enc.MessageEnd();
00161 }
00162 
00163 void PolynomialMod2::BERDecodeAsOctetString(BufferedTransformation &bt, unsigned int length)
00164 {
00165         BERGeneralDecoder dec(bt, OCTET_STRING);
00166         if (!dec.IsDefiniteLength() || dec.RemainingLength() != length)
00167                 BERDecodeError();
00168         Decode(dec, length);
00169         dec.MessageEnd();
00170 }
00171 
00172 unsigned int PolynomialMod2::WordCount() const
00173 {
00174         return CountWords(reg, reg.size);
00175 }
00176 
00177 unsigned int PolynomialMod2::ByteCount() const
00178 {
00179         unsigned wordCount = WordCount();
00180         if (wordCount)
00181                 return (wordCount-1)*WORD_SIZE + BytePrecision(reg[wordCount-1]);
00182         else
00183                 return 0;
00184 }
00185 
00186 unsigned int PolynomialMod2::BitCount() const
00187 {
00188         unsigned wordCount = WordCount();
00189         if (wordCount)
00190                 return (wordCount-1)*WORD_BITS + BitPrecision(reg[wordCount-1]);
00191         else
00192                 return 0;
00193 }
00194 
00195 unsigned int PolynomialMod2::Parity() const
00196 {
00197         unsigned i;
00198         word temp=0;
00199         for (i=0; i<reg.size; i++)
00200                 temp ^= reg[i];
00201         return CryptoPP::Parity(temp);
00202 }
00203 
00204 PolynomialMod2& PolynomialMod2::operator=(const PolynomialMod2& t)
00205 {
00206         reg.Assign(t.reg);
00207         return *this;
00208 }
00209 
00210 PolynomialMod2& PolynomialMod2::operator^=(const PolynomialMod2& t)
00211 {
00212         reg.CleanGrow(t.reg.size);
00213         XorWords(reg, t.reg, t.reg.size);
00214         return *this;
00215 }
00216 
00217 PolynomialMod2 PolynomialMod2::Xor(const PolynomialMod2 &b) const
00218 {
00219         if (b.reg.size >= reg.size)
00220         {
00221                 PolynomialMod2 result((word)0, b.reg.size*WORD_BITS);
00222                 XorWords(result.reg, reg, b.reg, reg.size);
00223                 CopyWords(result.reg+reg.size, b.reg+reg.size, b.reg.size-reg.size);
00224                 return result;
00225         }
00226         else
00227         {
00228                 PolynomialMod2 result((word)0, reg.size*WORD_BITS);
00229                 XorWords(result.reg, reg, b.reg, b.reg.size);
00230                 CopyWords(result.reg+b.reg.size, reg+b.reg.size, reg.size-b.reg.size);
00231                 return result;
00232         }
00233 }
00234 
00235 PolynomialMod2 PolynomialMod2::And(const PolynomialMod2 &b) const
00236 {
00237         PolynomialMod2 result((word)0, WORD_BITS*STDMIN(reg.size, b.reg.size));
00238         AndWords(result.reg, reg, b.reg, result.reg.size);
00239         return result;
00240 }
00241 
00242 PolynomialMod2 PolynomialMod2::Times(const PolynomialMod2 &b) const
00243 {
00244         PolynomialMod2 result((word)0, BitCount() + b.BitCount());
00245 
00246         for (int i=b.Degree(); i>=0; i--)
00247         {
00248                 result <<= 1;
00249                 if (b[i])
00250                         XorWords(result.reg, reg, reg.size);
00251         }
00252         return result;
00253 }
00254 
00255 PolynomialMod2 PolynomialMod2::Squared() const
00256 {
00257         static const word map[16] = {0, 1, 4, 5, 16, 17, 20, 21, 64, 65, 68, 69, 80, 81, 84, 85};
00258 
00259         PolynomialMod2 result((word)0, 2*reg.size*WORD_BITS);
00260 
00261         for (unsigned i=0; i<reg.size; i++)
00262         {
00263                 unsigned j;
00264 
00265                 for (j=0; j<WORD_BITS; j+=8)
00266                         result.reg[2*i] |= map[(reg[i] >> (j/2)) % 16] << j;
00267 
00268                 for (j=0; j<WORD_BITS; j+=8)
00269                         result.reg[2*i+1] |= map[(reg[i] >> (j/2 + WORD_BITS/2)) % 16] << j;
00270         }
00271 
00272         return result;
00273 }
00274 
00275 void PolynomialMod2::Divide(PolynomialMod2 &remainder, PolynomialMod2 &quotient,
00276                                    const PolynomialMod2 &dividend, const PolynomialMod2 &divisor)
00277 {
00278         if (!divisor)
00279                 throw PolynomialMod2::DivideByZero();
00280 
00281         int degree = divisor.Degree();
00282         remainder.reg.CleanNew(bitsToWords(degree+1));
00283         if (dividend.BitCount() >= divisor.BitCount())
00284                 quotient.reg.CleanNew(bitsToWords(dividend.BitCount() - divisor.BitCount() + 1));
00285         else
00286                 quotient.reg.CleanNew(0);
00287 
00288         for (int i=dividend.Degree(); i>=0; i--)
00289         {
00290                 remainder <<= 1;
00291                 remainder.reg[0] |= dividend[i];
00292                 if (remainder[degree])
00293                 {
00294                         remainder -= divisor;
00295                         quotient.SetBit(i);
00296                 }
00297         }
00298 }
00299 
00300 PolynomialMod2 PolynomialMod2::DividedBy(const PolynomialMod2 &b) const
00301 {
00302         PolynomialMod2 remainder, quotient;
00303         PolynomialMod2::Divide(remainder, quotient, *this, b);
00304         return quotient;
00305 }
00306 
00307 PolynomialMod2 PolynomialMod2::Modulo(const PolynomialMod2 &b) const
00308 {
00309         PolynomialMod2 remainder, quotient;
00310         PolynomialMod2::Divide(remainder, quotient, *this, b);
00311         return remainder;
00312 }
00313 
00314 PolynomialMod2& PolynomialMod2::operator<<=(unsigned int n)
00315 {
00316         if (!reg.size)
00317                 return *this;
00318 
00319         int i;
00320         word u;
00321         word carry=0;
00322         word *r=reg;
00323 
00324         if (n==1)       // special case code for most frequent case
00325         {
00326                 i = reg.size;
00327                 while (i--)
00328                 {
00329                         u = *r;
00330                         *r = (u << 1) | carry;
00331                         carry = u >> (WORD_BITS-1);
00332                         r++;
00333                 }
00334 
00335                 if (carry)
00336                 {
00337                         reg.Grow(reg.size+1);
00338                         reg[reg.size-1] = carry;
00339                 }
00340 
00341                 return *this;
00342         }
00343 
00344         int shiftWords = n / WORD_BITS;
00345         int shiftBits = n % WORD_BITS;
00346 
00347         if (shiftBits)
00348         {
00349                 i = reg.size;
00350                 while (i--)
00351                 {
00352                         u = *r;
00353                         *r = (u << shiftBits) | carry;
00354                         carry = u >> (WORD_BITS-shiftBits);
00355                         r++;
00356                 }
00357         }
00358 
00359         if (carry)
00360         {
00361                 reg.Grow(reg.size+shiftWords+1);
00362                 reg[reg.size-1] = carry;
00363         }
00364         else
00365                 reg.Grow(reg.size+shiftWords);
00366 
00367         if (shiftWords)
00368         {
00369                 for (i = reg.size-1; i>=shiftWords; i--)
00370                         reg[i] = reg[i-shiftWords];
00371                 for (; i>=0; i--)
00372                         reg[i] = 0;
00373         }
00374 
00375         return *this;
00376 }
00377 
00378 PolynomialMod2& PolynomialMod2::operator>>=(unsigned int n)
00379 {
00380         if (!reg.size)
00381                 return *this;
00382 
00383         int shiftWords = n / WORD_BITS;
00384         int shiftBits = n % WORD_BITS;
00385 
00386         unsigned i;
00387         word u;
00388         word carry=0;
00389         word *r=reg+reg.size-1;
00390 
00391         if (shiftBits)
00392         {
00393                 i = reg.size;
00394                 while (i--)
00395                 {
00396                         u = *r;
00397                         *r = (u >> shiftBits) | carry;
00398                         carry = u << (WORD_BITS-shiftBits);
00399                         r--;
00400                 }
00401         }
00402 
00403         if (shiftWords)
00404         {
00405                 for (i=0; i<reg.size-shiftWords; i++)
00406                         reg[i] = reg[i+shiftWords];
00407                 for (; i<reg.size; i++)
00408                         reg[i] = 0;
00409         }
00410 
00411         return *this;
00412 }
00413 
00414 PolynomialMod2 PolynomialMod2::operator<<(unsigned int n) const
00415 {
00416         PolynomialMod2 result(*this);
00417         return result<<=n;
00418 }
00419 
00420 PolynomialMod2 PolynomialMod2::operator>>(unsigned int n) const
00421 {
00422         PolynomialMod2 result(*this);
00423         return result>>=n;
00424 }
00425 
00426 bool PolynomialMod2::operator!() const
00427 {
00428         for (unsigned i=0; i<reg.size; i++)
00429                 if (reg[i]) return false;
00430         return true;
00431 }
00432 
00433 bool PolynomialMod2::Equals(const PolynomialMod2 &rhs) const
00434 {
00435         unsigned i, smallerSize = STDMIN(reg.size, rhs.reg.size);
00436 
00437         for (i=0; i<smallerSize; i++)
00438                 if (reg[i] != rhs.reg[i]) return false;
00439 
00440         for (i=smallerSize; i<reg.size; i++)
00441                 if (reg[i] != 0) return false;
00442 
00443         for (i=smallerSize; i<rhs.reg.size; i++)
00444                 if (rhs.reg[i] != 0) return false;
00445 
00446         return true;
00447 }
00448 
00449 std::ostream& operator<<(std::ostream& out, const PolynomialMod2 &a)
00450 {
00451         // Get relevant conversion specifications from ostream.
00452         long f = out.flags() & std::ios::basefield;     // Get base digits.
00453         int bits, block;
00454         char suffix;
00455         switch(f)
00456         {
00457         case std::ios::oct :
00458                 bits = 3;
00459                 block = 4;
00460                 suffix = 'o';
00461                 break;
00462         case std::ios::hex :
00463                 bits = 4;
00464                 block = 2;
00465                 suffix = 'h';
00466                 break;
00467         default :
00468                 bits = 1;
00469                 block = 8;
00470                 suffix = 'b';
00471         }
00472 
00473         if (!a)
00474                 return out << '0' << suffix;
00475 
00476         SecBlock<char> s(a.BitCount()/bits+1);
00477         unsigned i;
00478         const char vec[]="0123456789ABCDEF";
00479 
00480         for (i=0; i*bits < a.BitCount(); i++)
00481         {
00482                 int digit=0;
00483                 for (int j=0; j<bits; j++)
00484                         digit |= a[i*bits+j] << j;
00485                 s[i]=vec[digit];
00486         }
00487 
00488         while (i--)
00489         {
00490                 out << s[i];
00491                 if (i && (i%block)==0)
00492                         out << ',';
00493         }
00494 
00495         return out << suffix;
00496 }
00497 
00498 PolynomialMod2 PolynomialMod2::Gcd(const PolynomialMod2 &a, const PolynomialMod2 &b)
00499 {
00500         return EuclideanDomainOf<PolynomialMod2>().Gcd(a, b);
00501 }
00502 
00503 bool PolynomialMod2::IsIrreducible() const
00504 {
00505         signed int d = Degree();
00506         if (d <= 0)
00507                 return false;
00508 
00509         PolynomialMod2 t(2), u(t);
00510         for (int i=1; i<=d/2; i++)
00511         {
00512                 u = u.Squared()%(*this);
00513                 if (!Gcd(u+t, *this).IsUnit())
00514                         return false;
00515         }
00516         return true;
00517 }
00518 
00519 // ********************************************************
00520 
00521 GF2NP::GF2NP(const PolynomialMod2 &modulus)
00522         : QuotientRing<EuclideanDomainOf<PolynomialMod2> >(EuclideanDomainOf<PolynomialMod2>(), modulus), m(modulus.Degree()) 
00523 {
00524 }
00525 
00526 GF2NP::Element GF2NP::SquareRoot(const Element &a) const
00527 {
00528         Element r = a;
00529         for (unsigned int i=1; i<m; i++)
00530                 r = Square(r);
00531         return r;
00532 }
00533 
00534 GF2NP::Element GF2NP::HalfTrace(const Element &a) const
00535 {
00536         assert(m%2 == 1);
00537         Element h = a;
00538         for (unsigned int i=1; i<=(m-1)/2; i++)
00539                 h = Add(Square(Square(h)), a);
00540         return h;
00541 }
00542 
00543 GF2NP::Element GF2NP::SolveQuadraticEquation(const Element &a) const
00544 {
00545         if (m%2 == 0)
00546         {
00547                 Element z, w;
00548                 do
00549                 {
00550                         LC_RNG rng(11111);
00551                         Element p(rng, m);
00552                         z = PolynomialMod2::Zero();
00553                         w = p;
00554                         for (unsigned int i=1; i<=m-1; i++)
00555                         {
00556                                 w = Square(w);
00557                                 z = Square(z);
00558                                 Accumulate(z, Multiply(w, a));
00559                                 Accumulate(w, p);
00560                         }
00561                 } while (w.IsZero());
00562                 return z;
00563         }
00564         else
00565                 return HalfTrace(a);
00566 }
00567 
00568 // ********************************************************
00569 
00570 GF2NT::GF2NT(unsigned int t0, unsigned int t1, unsigned int t2)
00571         : GF2NP(PolynomialMod2::Trinomial(t0, t1, t2))
00572         , t0(t0), t1(t1)
00573         , result((word)0, m)
00574 {
00575         assert(t0 > t1 && t1 > t2 && t2==0);
00576 }
00577 
00578 const GF2NT::Element& GF2NT::MultiplicativeInverse(const Element &a) const
00579 {
00580         if (t0-t1 < WORD_BITS)
00581                 return GF2NP::MultiplicativeInverse(a);
00582 
00583         SecWordBlock T(m_modulus.reg.size * 4);
00584         word *b = T;
00585         word *c = T+m_modulus.reg.size;
00586         word *f = T+2*m_modulus.reg.size;
00587         word *g = T+3*m_modulus.reg.size;
00588         unsigned int bcLen=1, fgLen=m_modulus.reg.size;
00589         unsigned int k=0;
00590 
00591         SetWords(T, 0, 3*m_modulus.reg.size);
00592         b[0]=1;
00593         assert(a.reg.size <= m_modulus.reg.size);
00594         CopyWords(f, a.reg, a.reg.size);
00595         CopyWords(g, m_modulus.reg, m_modulus.reg.size);
00596 
00597         while (1)
00598         {
00599                 word t=f[0];
00600                 while (!t)
00601                 {
00602                         ShiftWordsRightByWords(f, fgLen, 1);
00603                         if (c[bcLen-1])
00604                                 bcLen++;
00605                         assert(bcLen <= m_modulus.reg.size);
00606                         ShiftWordsLeftByWords(c, bcLen, 1);
00607                         k+=WORD_BITS;
00608                         t=f[0];
00609                 }
00610 
00611                 unsigned int i=0;
00612                 while (t%2 == 0)
00613                 {
00614                         t>>=1;
00615                         i++;
00616                 }
00617                 k+=i;
00618 
00619                 if (t==1 && CountWords(f, fgLen)==1)
00620                         break;
00621 
00622                 if (i==1)
00623                 {
00624                         ShiftWordsRightByBits(f, fgLen, 1);
00625                         t=ShiftWordsLeftByBits(c, bcLen, 1);
00626                 }
00627                 else
00628                 {
00629                         ShiftWordsRightByBits(f, fgLen, i);
00630                         t=ShiftWordsLeftByBits(c, bcLen, i);
00631                 }
00632                 if (t)
00633                 {
00634                         c[bcLen] = t;
00635                         bcLen++;
00636                         assert(bcLen <= m_modulus.reg.size);
00637                 }
00638 
00639                 if (f[fgLen-1]==0 && g[fgLen-1]==0)
00640                         fgLen--;
00641 
00642                 if (f[fgLen-1] < g[fgLen-1])
00643                 {
00644                         std::swap(f, g);
00645                         std::swap(b, c);
00646                 }
00647 
00648                 XorWords(f, g, fgLen);
00649                 XorWords(b, c, bcLen);
00650         }
00651 
00652         while (k >= WORD_BITS)
00653         {
00654                 word temp = b[0];
00655                 // right shift b
00656                 for (unsigned i=0; i+1<bitsToWords(m); i++)
00657                         b[i] = b[i+1];
00658                 b[bitsToWords(m)-1] = 0;
00659 
00660                 if (t1 < WORD_BITS)
00661                         for (unsigned int j=0; j<WORD_BITS-t1; j++)
00662                                 temp ^= ((temp >> j) & 1) << (t1 + j);
00663                 else
00664                         b[t1/WORD_BITS-1] ^= temp << t1%WORD_BITS;
00665 
00666                 if (t1 % WORD_BITS)
00667                         b[t1/WORD_BITS] ^= temp >> (WORD_BITS - t1%WORD_BITS);
00668 
00669                 if (t0%WORD_BITS)
00670                 {
00671                         b[t0/WORD_BITS-1] ^= temp << t0%WORD_BITS;
00672                         b[t0/WORD_BITS] ^= temp >> (WORD_BITS - t0%WORD_BITS);
00673                 }
00674                 else
00675                         b[t0/WORD_BITS-1] ^= temp;
00676 
00677                 k -= WORD_BITS;
00678         }
00679 
00680         if (k)
00681         {
00682                 word temp = b[0] << (WORD_BITS - k);
00683                 ShiftWordsRightByBits(b, bitsToWords(m), k);
00684 
00685                 if (t1 < WORD_BITS)
00686                         for (unsigned int j=0; j<WORD_BITS-t1; j++)
00687                                 temp ^= ((temp >> j) & 1) << (t1 + j);
00688                 else
00689                         b[t1/WORD_BITS-1] ^= temp << t1%WORD_BITS;
00690 
00691                 if (t1 % WORD_BITS)
00692                         b[t1/WORD_BITS] ^= temp >> (WORD_BITS - t1%WORD_BITS);
00693 
00694                 if (t0%WORD_BITS)
00695                 {
00696                         b[t0/WORD_BITS-1] ^= temp << t0%WORD_BITS;
00697                         b[t0/WORD_BITS] ^= temp >> (WORD_BITS - t0%WORD_BITS);
00698                 }
00699                 else
00700                         b[t0/WORD_BITS-1] ^= temp;
00701         }
00702 
00703         CopyWords(result.reg.ptr, b, result.reg.size);
00704         return result;
00705 }
00706 
00707 const GF2NT::Element& GF2NT::Multiply(const Element &a, const Element &b) const
00708 {
00709         unsigned int aSize = STDMIN(a.reg.size, result.reg.size);
00710         Element r((word)0, m);
00711 
00712         for (int i=m-1; i>=0; i--)
00713         {
00714                 if (r[m-1])
00715                 {
00716                         ShiftWordsLeftByBits(r.reg.ptr, r.reg.size, 1);
00717                         XorWords(r.reg.ptr, m_modulus.reg, r.reg.size);
00718                 }
00719                 else
00720                         ShiftWordsLeftByBits(r.reg.ptr, r.reg.size, 1);
00721 
00722                 if (b[i])
00723                         XorWords(r.reg.ptr, a.reg, aSize);
00724         }
00725 
00726         if (m%WORD_BITS)
00727                 r.reg.ptr[r.reg.size-1] = (word)Crop(r.reg[r.reg.size-1], m%WORD_BITS);
00728 
00729         CopyWords(result.reg.ptr, r.reg.ptr, result.reg.size);
00730         return result;
00731 }
00732 
00733 const GF2NT::Element& GF2NT::Reduced(const Element &a) const
00734 {
00735         if (t0-t1 < WORD_BITS)
00736                 return m_domain.Mod(a, m_modulus);
00737 
00738         SecWordBlock b(a.reg);
00739 
00740         unsigned i;
00741         for (i=b.size-1; i>=bitsToWords(t0); i--)
00742         {
00743                 word temp = b[i];
00744 
00745                 if (t0%WORD_BITS)
00746                 {
00747                         b[i-t0/WORD_BITS] ^= temp >> t0%WORD_BITS;
00748                         b[i-t0/WORD_BITS-1] ^= temp << (WORD_BITS - t0%WORD_BITS);
00749                 }
00750                 else
00751                         b[i-t0/WORD_BITS] ^= temp;
00752 
00753                 if ((t0-t1)%WORD_BITS)
00754                 {
00755                         b[i-(t0-t1)/WORD_BITS] ^= temp >> (t0-t1)%WORD_BITS;
00756                         b[i-(t0-t1)/WORD_BITS-1] ^= temp << (WORD_BITS - (t0-t1)%WORD_BITS);
00757                 }
00758                 else
00759                         b[i-(t0-t1)/WORD_BITS] ^= temp;
00760         }
00761 
00762         if (i==bitsToWords(t0)-1 && t0%WORD_BITS)
00763         {
00764                 word mask = ((word)1<<(t0%WORD_BITS))-1;
00765                 word temp = b[i] & ~mask;
00766                 b[i] &= mask;
00767 
00768                 b[i-t0/WORD_BITS] ^= temp >> t0%WORD_BITS;
00769 
00770                 if ((t0-t1)%WORD_BITS)
00771                 {
00772                         b[i-(t0-t1)/WORD_BITS] ^= temp >> (t0-t1)%WORD_BITS;
00773                         if ((t0-t1)%WORD_BITS > t0%WORD_BITS)
00774                                 b[i-(t0-t1)/WORD_BITS-1] ^= temp << (WORD_BITS - (t0-t1)%WORD_BITS);
00775                         else
00776                                 assert(temp << (WORD_BITS - (t0-t1)%WORD_BITS) == 0);
00777                 }
00778                 else
00779                         b[i-(t0-t1)/WORD_BITS] ^= temp;
00780         }
00781 
00782         SetWords(result.reg.ptr, 0, result.reg.size);
00783         CopyWords(result.reg.ptr, b, STDMIN(b.size, result.reg.size));
00784         return result;
00785 }
00786 
00787 void GF2NP::DEREncodeElement(BufferedTransformation &out, const Element &a) const
00788 {
00789         a.DEREncodeAsOctetString(out, MaxElementByteLength());
00790 }
00791 
00792 void GF2NP::BERDecodeElement(BufferedTransformation &in, Element &a) const
00793 {
00794         a.BERDecodeAsOctetString(in, MaxElementByteLength());
00795 }
00796 
00797 void GF2NT::DEREncode(BufferedTransformation &bt) const
00798 {
00799         DERSequenceEncoder seq(bt);
00800         DEREncodeUnsigned(seq, m);
00801         ASN1::tpBasis().DEREncode(seq);
00802         DEREncodeUnsigned(seq, t1);
00803         seq.MessageEnd();
00804 }
00805 
00806 void GF2NPP::DEREncode(BufferedTransformation &bt) const
00807 {
00808         DERSequenceEncoder seq(bt);
00809         DEREncodeUnsigned(seq, m);
00810         ASN1::ppBasis().DEREncode(seq);
00811         DERSequenceEncoder pentanomial(seq);
00812         DEREncodeUnsigned(pentanomial, t3);
00813         DEREncodeUnsigned(pentanomial, t2);
00814         DEREncodeUnsigned(pentanomial, t1);
00815         pentanomial.MessageEnd();
00816         seq.MessageEnd();
00817 }
00818 
00819 GF2NP * BERDecodeGF2NP(BufferedTransformation &bt)
00820 {
00821         BERSequenceDecoder seq(bt);
00822         unsigned int m;
00823         BERDecodeUnsigned(seq, m);
00824         OID oid(seq);
00825         if (oid == ASN1::tpBasis())
00826         {
00827                 unsigned int t1;
00828                 BERDecodeUnsigned(seq, t1);
00829                 return new GF2NT(m, t1, 0);
00830         }
00831         else if (oid == ASN1::ppBasis())
00832         {
00833                 unsigned int t1, t2, t3;
00834                 BERSequenceDecoder pentanomial(seq);
00835                 BERDecodeUnsigned(pentanomial, t3);
00836                 BERDecodeUnsigned(pentanomial, t2);
00837                 BERDecodeUnsigned(pentanomial, t1);
00838                 pentanomial.MessageEnd();
00839                 return new GF2NPP(m, t3, t2, t1, 0);
00840         }
00841         else
00842         {
00843                 BERDecodeError();
00844                 return NULL;
00845         }
00846 }
00847 
00848 NAMESPACE_END

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