00001
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 "ient,
00276 const PolynomialMod2 ÷nd, 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)
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
00452 long f = out.flags() & std::ios::basefield;
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
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