< Summary

Information
Class: Renci.SshNet.Security.Org.BouncyCastle.Math.EC.ECFieldElement
Assembly: Renci.SshNet
File(s): \home\appveyor\projects\ssh-net\src\Renci.SshNet\Security\BouncyCastle\math\ec\ECFieldElement.cs
Line coverage
24%
Covered lines: 11
Uncovered lines: 34
Coverable lines: 45
Total lines: 972
Line coverage: 24.4%
Branch coverage
33%
Covered branches: 2
Total branches: 6
Branch coverage: 33.3%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity Line coverage
get_BitLength()100%1100%
get_IsOne()100%1100%
get_IsZero()100%1100%
MultiplyMinusProduct(...)100%10%
MultiplyPlusProduct(...)100%10%
SquareMinusProduct(...)100%10%
SquarePlusProduct(...)100%10%
SquarePow(...)0%20%
TestBitZero()100%10%
Equals(...)100%10%
Equals(...)50%471.42%
GetHashCode()100%10%
ToString()100%10%
GetEncoded()100%1100%

File(s)

\home\appveyor\projects\ssh-net\src\Renci.SshNet\Security\BouncyCastle\math\ec\ECFieldElement.cs

#LineLine coverage
 1using System;
 2using System.Diagnostics;
 3
 4using Renci.SshNet.Security.Org.BouncyCastle.Math.Raw;
 5using Renci.SshNet.Security.Org.BouncyCastle.Utilities;
 6
 7namespace Renci.SshNet.Security.Org.BouncyCastle.Math.EC
 8{
 9    internal abstract class ECFieldElement
 10    {
 11        public abstract BigInteger ToBigInteger();
 12        public abstract string FieldName { get; }
 13        public abstract int FieldSize { get; }
 14        public abstract ECFieldElement Add(ECFieldElement b);
 15        public abstract ECFieldElement AddOne();
 16        public abstract ECFieldElement Subtract(ECFieldElement b);
 17        public abstract ECFieldElement Multiply(ECFieldElement b);
 18        public abstract ECFieldElement Divide(ECFieldElement b);
 19        public abstract ECFieldElement Negate();
 20        public abstract ECFieldElement Square();
 21        public abstract ECFieldElement Invert();
 22        public abstract ECFieldElement Sqrt();
 23
 24        public virtual int BitLength
 25        {
 3852026            get { return ToBigInteger().BitLength; }
 27        }
 28
 29        public virtual bool IsOne
 30        {
 3011431            get { return BitLength == 1; }
 32        }
 33
 34        public virtual bool IsZero
 35        {
 3656736            get { return 0 == ToBigInteger().SignValue; }
 37        }
 38
 39        public virtual ECFieldElement MultiplyMinusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y)
 040        {
 041            return Multiply(b).Subtract(x.Multiply(y));
 042        }
 43
 44        public virtual ECFieldElement MultiplyPlusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y)
 045        {
 046            return Multiply(b).Add(x.Multiply(y));
 047        }
 48
 49        public virtual ECFieldElement SquareMinusProduct(ECFieldElement x, ECFieldElement y)
 050        {
 051            return Square().Subtract(x.Multiply(y));
 052        }
 53
 54        public virtual ECFieldElement SquarePlusProduct(ECFieldElement x, ECFieldElement y)
 055        {
 056            return Square().Add(x.Multiply(y));
 057        }
 58
 59        public virtual ECFieldElement SquarePow(int pow)
 060        {
 061            ECFieldElement r = this;
 062            for (int i = 0; i < pow; ++i)
 063            {
 064                r = r.Square();
 065            }
 066            return r;
 067        }
 68
 69        public virtual bool TestBitZero()
 070        {
 071            return ToBigInteger().TestBit(0);
 072        }
 73
 74        public override bool Equals(object obj)
 075        {
 076            return Equals(obj as ECFieldElement);
 077        }
 78
 79        public virtual bool Equals(ECFieldElement other)
 141580        {
 141581            if (this == other)
 082                return true;
 141583            if (null == other)
 084                return false;
 141585            return ToBigInteger().Equals(other.ToBigInteger());
 141586        }
 87
 88        public override int GetHashCode()
 089        {
 090            return ToBigInteger().GetHashCode();
 091        }
 92
 93        public override string ToString()
 094        {
 095            return this.ToBigInteger().ToString(16);
 096        }
 97
 98        public virtual byte[] GetEncoded()
 3699        {
 36100            return BigIntegers.AsUnsignedByteArray((FieldSize + 7) / 8, ToBigInteger());
 36101        }
 102    }
 103
 104    internal abstract class AbstractFpFieldElement
 105        : ECFieldElement
 106    {
 107    }
 108
 109    internal class FpFieldElement
 110        : AbstractFpFieldElement
 111    {
 112        private readonly BigInteger q, r, x;
 113
 114        internal static BigInteger CalculateResidue(BigInteger p)
 115        {
 116            int bitLength = p.BitLength;
 117            if (bitLength >= 96)
 118            {
 119                BigInteger firstWord = p.ShiftRight(bitLength - 64);
 120                if (firstWord.LongValue == -1L)
 121                {
 122                    return BigInteger.One.ShiftLeft(bitLength).Subtract(p);
 123                }
 124                if ((bitLength & 7) == 0)
 125                {
 126                    return BigInteger.One.ShiftLeft(bitLength << 1).Divide(p).Negate();
 127                }
 128            }
 129            return null;
 130        }
 131
 132        [Obsolete("Use ECCurve.FromBigInteger to construct field elements")]
 133        public FpFieldElement(BigInteger q, BigInteger x)
 134            : this(q, CalculateResidue(q), x)
 135        {
 136        }
 137
 138        internal FpFieldElement(BigInteger q, BigInteger r, BigInteger x)
 139        {
 140            if (x == null || x.SignValue < 0 || x.CompareTo(q) >= 0)
 141                throw new ArgumentException("value invalid in Fp field element", "x");
 142
 143            this.q = q;
 144            this.r = r;
 145            this.x = x;
 146        }
 147
 148        public override BigInteger ToBigInteger()
 149        {
 150            return x;
 151        }
 152
 153        /**
 154         * return the field name for this field.
 155         *
 156         * @return the string "Fp".
 157         */
 158        public override string FieldName
 159        {
 160            get { return "Fp"; }
 161        }
 162
 163        public override int FieldSize
 164        {
 165            get { return q.BitLength; }
 166        }
 167
 168        public BigInteger Q
 169        {
 170            get { return q; }
 171        }
 172
 173        public override ECFieldElement Add(
 174            ECFieldElement b)
 175        {
 176            return new FpFieldElement(q, r, ModAdd(x, b.ToBigInteger()));
 177        }
 178
 179        public override ECFieldElement AddOne()
 180        {
 181            BigInteger x2 = x.Add(BigInteger.One);
 182            if (x2.CompareTo(q) == 0)
 183            {
 184                x2 = BigInteger.Zero;
 185            }
 186            return new FpFieldElement(q, r, x2);
 187        }
 188
 189        public override ECFieldElement Subtract(
 190            ECFieldElement b)
 191        {
 192            return new FpFieldElement(q, r, ModSubtract(x, b.ToBigInteger()));
 193        }
 194
 195        public override ECFieldElement Multiply(
 196            ECFieldElement b)
 197        {
 198            return new FpFieldElement(q, r, ModMult(x, b.ToBigInteger()));
 199        }
 200
 201        public override ECFieldElement MultiplyMinusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y)
 202        {
 203            BigInteger ax = this.x, bx = b.ToBigInteger(), xx = x.ToBigInteger(), yx = y.ToBigInteger();
 204            BigInteger ab = ax.Multiply(bx);
 205            BigInteger xy = xx.Multiply(yx);
 206            return new FpFieldElement(q, r, ModReduce(ab.Subtract(xy)));
 207        }
 208
 209        public override ECFieldElement MultiplyPlusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y)
 210        {
 211            BigInteger ax = this.x, bx = b.ToBigInteger(), xx = x.ToBigInteger(), yx = y.ToBigInteger();
 212            BigInteger ab = ax.Multiply(bx);
 213            BigInteger xy = xx.Multiply(yx);
 214            BigInteger sum = ab.Add(xy);
 215            if (r != null && r.SignValue < 0 && sum.BitLength > (q.BitLength << 1))
 216            {
 217                sum = sum.Subtract(q.ShiftLeft(q.BitLength));
 218            }
 219            return new FpFieldElement(q, r, ModReduce(sum));
 220        }
 221
 222        public override ECFieldElement Divide(
 223            ECFieldElement b)
 224        {
 225            return new FpFieldElement(q, r, ModMult(x, ModInverse(b.ToBigInteger())));
 226        }
 227
 228        public override ECFieldElement Negate()
 229        {
 230            return x.SignValue == 0 ? this : new FpFieldElement(q, r, q.Subtract(x));
 231        }
 232
 233        public override ECFieldElement Square()
 234        {
 235            return new FpFieldElement(q, r, ModMult(x, x));
 236        }
 237
 238        public override ECFieldElement SquareMinusProduct(ECFieldElement x, ECFieldElement y)
 239        {
 240            BigInteger ax = this.x, xx = x.ToBigInteger(), yx = y.ToBigInteger();
 241            BigInteger aa = ax.Multiply(ax);
 242            BigInteger xy = xx.Multiply(yx);
 243            return new FpFieldElement(q, r, ModReduce(aa.Subtract(xy)));
 244        }
 245
 246        public override ECFieldElement SquarePlusProduct(ECFieldElement x, ECFieldElement y)
 247        {
 248            BigInteger ax = this.x, xx = x.ToBigInteger(), yx = y.ToBigInteger();
 249            BigInteger aa = ax.Multiply(ax);
 250            BigInteger xy = xx.Multiply(yx);
 251            BigInteger sum = aa.Add(xy);
 252            if (r != null && r.SignValue < 0 && sum.BitLength > (q.BitLength << 1))
 253            {
 254                sum = sum.Subtract(q.ShiftLeft(q.BitLength));
 255            }
 256            return new FpFieldElement(q, r, ModReduce(sum));
 257        }
 258
 259        public override ECFieldElement Invert()
 260        {
 261            // TODO Modular inversion can be faster for a (Generalized) Mersenne Prime.
 262            return new FpFieldElement(q, r, ModInverse(x));
 263        }
 264
 265        /**
 266         * return a sqrt root - the routine verifies that the calculation
 267         * returns the right value - if none exists it returns null.
 268         */
 269        public override ECFieldElement Sqrt()
 270        {
 271            if (IsZero || IsOne)
 272                return this;
 273
 274            if (!q.TestBit(0))
 275                throw new NotImplementedException("even value of q");
 276
 277            if (q.TestBit(1)) // q == 4m + 3
 278            {
 279                BigInteger e = q.ShiftRight(2).Add(BigInteger.One);
 280                return CheckSqrt(new FpFieldElement(q, r, x.ModPow(e, q)));
 281            }
 282
 283            if (q.TestBit(2)) // q == 8m + 5
 284            {
 285                BigInteger t1 = x.ModPow(q.ShiftRight(3), q);
 286                BigInteger t2 = ModMult(t1, x);
 287                BigInteger t3 = ModMult(t2, t1);
 288
 289                if (t3.Equals(BigInteger.One))
 290                {
 291                    return CheckSqrt(new FpFieldElement(q, r, t2));
 292                }
 293
 294                // TODO This is constant and could be precomputed
 295                BigInteger t4 = BigInteger.Two.ModPow(q.ShiftRight(2), q);
 296
 297                BigInteger y = ModMult(t2, t4);
 298
 299                return CheckSqrt(new FpFieldElement(q, r, y));
 300            }
 301
 302            // q == 8m + 1
 303
 304            BigInteger legendreExponent = q.ShiftRight(1);
 305            if (!(x.ModPow(legendreExponent, q).Equals(BigInteger.One)))
 306                return null;
 307
 308            BigInteger X = this.x;
 309            BigInteger fourX = ModDouble(ModDouble(X)); ;
 310
 311            BigInteger k = legendreExponent.Add(BigInteger.One), qMinusOne = q.Subtract(BigInteger.One);
 312
 313            BigInteger U, V;
 314            do
 315            {
 316                BigInteger P;
 317                do
 318                {
 319                    P = BigInteger.Arbitrary(q.BitLength);
 320                }
 321                while (P.CompareTo(q) >= 0
 322                    || !ModReduce(P.Multiply(P).Subtract(fourX)).ModPow(legendreExponent, q).Equals(qMinusOne));
 323
 324                BigInteger[] result = LucasSequence(P, X, k);
 325                U = result[0];
 326                V = result[1];
 327
 328                if (ModMult(V, V).Equals(fourX))
 329                {
 330                    return new FpFieldElement(q, r, ModHalfAbs(V));
 331                }
 332            }
 333            while (U.Equals(BigInteger.One) || U.Equals(qMinusOne));
 334
 335            return null;
 336        }
 337
 338        private ECFieldElement CheckSqrt(ECFieldElement z)
 339        {
 340            return z.Square().Equals(this) ? z : null;
 341        }
 342
 343        private BigInteger[] LucasSequence(
 344            BigInteger  P,
 345            BigInteger  Q,
 346            BigInteger  k)
 347        {
 348            // TODO Research and apply "common-multiplicand multiplication here"
 349
 350            int n = k.BitLength;
 351            int s = k.GetLowestSetBit();
 352
 353            Debug.Assert(k.TestBit(s));
 354
 355            BigInteger Uh = BigInteger.One;
 356            BigInteger Vl = BigInteger.Two;
 357            BigInteger Vh = P;
 358            BigInteger Ql = BigInteger.One;
 359            BigInteger Qh = BigInteger.One;
 360
 361            for (int j = n - 1; j >= s + 1; --j)
 362            {
 363                Ql = ModMult(Ql, Qh);
 364
 365                if (k.TestBit(j))
 366                {
 367                    Qh = ModMult(Ql, Q);
 368                    Uh = ModMult(Uh, Vh);
 369                    Vl = ModReduce(Vh.Multiply(Vl).Subtract(P.Multiply(Ql)));
 370                    Vh = ModReduce(Vh.Multiply(Vh).Subtract(Qh.ShiftLeft(1)));
 371                }
 372                else
 373                {
 374                    Qh = Ql;
 375                    Uh = ModReduce(Uh.Multiply(Vl).Subtract(Ql));
 376                    Vh = ModReduce(Vh.Multiply(Vl).Subtract(P.Multiply(Ql)));
 377                    Vl = ModReduce(Vl.Multiply(Vl).Subtract(Ql.ShiftLeft(1)));
 378                }
 379            }
 380
 381            Ql = ModMult(Ql, Qh);
 382            Qh = ModMult(Ql, Q);
 383            Uh = ModReduce(Uh.Multiply(Vl).Subtract(Ql));
 384            Vl = ModReduce(Vh.Multiply(Vl).Subtract(P.Multiply(Ql)));
 385            Ql = ModMult(Ql, Qh);
 386
 387            for (int j = 1; j <= s; ++j)
 388            {
 389                Uh = ModMult(Uh, Vl);
 390                Vl = ModReduce(Vl.Multiply(Vl).Subtract(Ql.ShiftLeft(1)));
 391                Ql = ModMult(Ql, Ql);
 392            }
 393
 394            return new BigInteger[] { Uh, Vl };
 395        }
 396
 397        protected virtual BigInteger ModAdd(BigInteger x1, BigInteger x2)
 398        {
 399            BigInteger x3 = x1.Add(x2);
 400            if (x3.CompareTo(q) >= 0)
 401            {
 402                x3 = x3.Subtract(q);
 403            }
 404            return x3;
 405        }
 406
 407        protected virtual BigInteger ModDouble(BigInteger x)
 408        {
 409            BigInteger _2x = x.ShiftLeft(1);
 410            if (_2x.CompareTo(q) >= 0)
 411            {
 412                _2x = _2x.Subtract(q);
 413            }
 414            return _2x;
 415        }
 416
 417        protected virtual BigInteger ModHalf(BigInteger x)
 418        {
 419            if (x.TestBit(0))
 420            {
 421                x = q.Add(x);
 422            }
 423            return x.ShiftRight(1);
 424        }
 425
 426        protected virtual BigInteger ModHalfAbs(BigInteger x)
 427        {
 428            if (x.TestBit(0))
 429            {
 430                x = q.Subtract(x);
 431            }
 432            return x.ShiftRight(1);
 433        }
 434
 435        protected virtual BigInteger ModInverse(BigInteger x)
 436        {
 437            int bits = FieldSize;
 438            int len = (bits + 31) >> 5;
 439            uint[] p = Nat.FromBigInteger(bits, q);
 440            uint[] n = Nat.FromBigInteger(bits, x);
 441            uint[] z = Nat.Create(len);
 442            Mod.Invert(p, n, z);
 443            return Nat.ToBigInteger(len, z);
 444        }
 445
 446        protected virtual BigInteger ModMult(BigInteger x1, BigInteger x2)
 447        {
 448            return ModReduce(x1.Multiply(x2));
 449        }
 450
 451        protected virtual BigInteger ModReduce(BigInteger x)
 452        {
 453            if (r == null)
 454            {
 455                x = x.Mod(q);
 456            }
 457            else
 458            {
 459                bool negative = x.SignValue < 0;
 460                if (negative)
 461                {
 462                    x = x.Abs();
 463                }
 464                int qLen = q.BitLength;
 465                if (r.SignValue > 0)
 466                {
 467                    BigInteger qMod = BigInteger.One.ShiftLeft(qLen);
 468                    bool rIsOne = r.Equals(BigInteger.One);
 469                    while (x.BitLength > (qLen + 1))
 470                    {
 471                        BigInteger u = x.ShiftRight(qLen);
 472                        BigInteger v = x.Remainder(qMod);
 473                        if (!rIsOne)
 474                        {
 475                            u = u.Multiply(r);
 476                        }
 477                        x = u.Add(v);
 478                    }
 479                }
 480                else
 481                {
 482                    int d = ((qLen - 1) & 31) + 1;
 483                    BigInteger mu = r.Negate();
 484                    BigInteger u = mu.Multiply(x.ShiftRight(qLen - d));
 485                    BigInteger quot = u.ShiftRight(qLen + d);
 486                    BigInteger v = quot.Multiply(q);
 487                    BigInteger bk1 = BigInteger.One.ShiftLeft(qLen + d);
 488                    v = v.Remainder(bk1);
 489                    x = x.Remainder(bk1);
 490                    x = x.Subtract(v);
 491                    if (x.SignValue < 0)
 492                    {
 493                        x = x.Add(bk1);
 494                    }
 495                }
 496                while (x.CompareTo(q) >= 0)
 497                {
 498                    x = x.Subtract(q);
 499                }
 500                if (negative && x.SignValue != 0)
 501                {
 502                    x = q.Subtract(x);
 503                }
 504            }
 505            return x;
 506        }
 507
 508        protected virtual BigInteger ModSubtract(BigInteger x1, BigInteger x2)
 509        {
 510            BigInteger x3 = x1.Subtract(x2);
 511            if (x3.SignValue < 0)
 512            {
 513                x3 = x3.Add(q);
 514            }
 515            return x3;
 516        }
 517
 518        public override bool Equals(
 519            object obj)
 520        {
 521            if (obj == this)
 522                return true;
 523
 524            FpFieldElement other = obj as FpFieldElement;
 525
 526            if (other == null)
 527                return false;
 528
 529            return Equals(other);
 530        }
 531
 532        public virtual bool Equals(
 533            FpFieldElement other)
 534        {
 535            return q.Equals(other.q) && base.Equals(other);
 536        }
 537
 538        public override int GetHashCode()
 539        {
 540            return q.GetHashCode() ^ base.GetHashCode();
 541        }
 542    }
 543
 544    internal abstract class AbstractF2mFieldElement
 545        :   ECFieldElement
 546    {
 547        public virtual ECFieldElement HalfTrace()
 548        {
 549            int m = FieldSize;
 550            if ((m & 1) == 0)
 551                throw new InvalidOperationException("Half-trace only defined for odd m");
 552
 553            ECFieldElement fe = this;
 554            ECFieldElement ht = fe;
 555            for (int i = 2; i < m; i += 2)
 556            {
 557                fe = fe.SquarePow(2);
 558                ht = ht.Add(fe);
 559            }
 560
 561            return ht;
 562        }
 563
 564        public virtual int Trace()
 565        {
 566            int m = FieldSize;
 567            ECFieldElement fe = this;
 568            ECFieldElement tr = fe;
 569            for (int i = 1; i < m; ++i)
 570            {
 571                fe = fe.Square();
 572                tr = tr.Add(fe);
 573            }
 574            if (tr.IsZero)
 575                return 0;
 576            if (tr.IsOne)
 577                return 1;
 578
 579            throw new InvalidOperationException("Internal error in trace calculation");
 580        }
 581    }
 582
 583    /**
 584     * Class representing the Elements of the finite field
 585     * <code>F<sub>2<sup>m</sup></sub></code> in polynomial basis (PB)
 586     * representation. Both trinomial (Tpb) and pentanomial (Ppb) polynomial
 587     * basis representations are supported. Gaussian normal basis (GNB)
 588     * representation is not supported.
 589     */
 590    internal class F2mFieldElement
 591        :   AbstractF2mFieldElement
 592    {
 593        /**
 594         * Indicates gaussian normal basis representation (GNB). Number chosen
 595         * according to X9.62. GNB is not implemented at present.
 596         */
 597        public const int Gnb = 1;
 598
 599        /**
 600         * Indicates trinomial basis representation (Tpb). Number chosen
 601         * according to X9.62.
 602         */
 603        public const int Tpb = 2;
 604
 605        /**
 606         * Indicates pentanomial basis representation (Ppb). Number chosen
 607         * according to X9.62.
 608         */
 609        public const int Ppb = 3;
 610
 611        /**
 612         * Tpb or Ppb.
 613         */
 614        private int representation;
 615
 616        /**
 617         * The exponent <code>m</code> of <code>F<sub>2<sup>m</sup></sub></code>.
 618         */
 619        private int m;
 620
 621        private int[] ks;
 622
 623        /**
 624         * The <code>LongArray</code> holding the bits.
 625         */
 626        internal LongArray x;
 627
 628        /**
 629         * Constructor for Ppb.
 630         * @param m  The exponent <code>m</code> of
 631         * <code>F<sub>2<sup>m</sup></sub></code>.
 632         * @param k1 The integer <code>k1</code> where <code>x<sup>m</sup> +
 633         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
 634         * represents the reduction polynomial <code>f(z)</code>.
 635         * @param k2 The integer <code>k2</code> where <code>x<sup>m</sup> +
 636         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
 637         * represents the reduction polynomial <code>f(z)</code>.
 638         * @param k3 The integer <code>k3</code> where <code>x<sup>m</sup> +
 639         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
 640         * represents the reduction polynomial <code>f(z)</code>.
 641         * @param x The BigInteger representing the value of the field element.
 642         */
 643        public F2mFieldElement(
 644            int      m,
 645            int      k1,
 646            int      k2,
 647            int      k3,
 648            BigInteger  x)
 649        {
 650            if (x == null || x.SignValue < 0 || x.BitLength > m)
 651                throw new ArgumentException("value invalid in F2m field element", "x");
 652
 653            if ((k2 == 0) && (k3 == 0))
 654            {
 655                this.representation = Tpb;
 656                this.ks = new int[] { k1 };
 657            }
 658            else
 659            {
 660                if (k2 >= k3)
 661                    throw new ArgumentException("k2 must be smaller than k3");
 662                if (k2 <= 0)
 663                    throw new ArgumentException("k2 must be larger than 0");
 664
 665                this.representation = Ppb;
 666                this.ks = new int[] { k1, k2, k3 };
 667            }
 668
 669            this.m = m;
 670            this.x = new LongArray(x);
 671        }
 672
 673        /**
 674         * Constructor for Tpb.
 675         * @param m  The exponent <code>m</code> of
 676         * <code>F<sub>2<sup>m</sup></sub></code>.
 677         * @param k The integer <code>k</code> where <code>x<sup>m</sup> +
 678         * x<sup>k</sup> + 1</code> represents the reduction
 679         * polynomial <code>f(z)</code>.
 680         * @param x The BigInteger representing the value of the field element.
 681         */
 682        public F2mFieldElement(
 683            int      m,
 684            int      k,
 685            BigInteger  x)
 686            : this(m, k, 0, 0, x)
 687        {
 688            // Set k1 to k, and set k2 and k3 to 0
 689        }
 690
 691        internal F2mFieldElement(int m, int[] ks, LongArray x)
 692        {
 693            this.m = m;
 694            this.representation = (ks.Length == 1) ? Tpb : Ppb;
 695            this.ks = ks;
 696            this.x = x;
 697        }
 698
 699        public override int BitLength
 700        {
 701            get { return x.Degree(); }
 702        }
 703
 704        public override bool IsOne
 705        {
 706            get { return x.IsOne(); }
 707        }
 708
 709        public override bool IsZero
 710        {
 711            get { return x.IsZero(); }
 712        }
 713
 714        public override bool TestBitZero()
 715        {
 716            return x.TestBitZero();
 717        }
 718
 719        public override BigInteger ToBigInteger()
 720        {
 721            return x.ToBigInteger();
 722        }
 723
 724        public override string FieldName
 725        {
 726            get { return "F2m"; }
 727        }
 728
 729        public override int FieldSize
 730        {
 731            get { return m; }
 732        }
 733
 734        /**
 735        * Checks, if the ECFieldElements <code>a</code> and <code>b</code>
 736        * are elements of the same field <code>F<sub>2<sup>m</sup></sub></code>
 737        * (having the same representation).
 738        * @param a field element.
 739        * @param b field element to be compared.
 740        * @throws ArgumentException if <code>a</code> and <code>b</code>
 741        * are not elements of the same field
 742        * <code>F<sub>2<sup>m</sup></sub></code> (having the same
 743        * representation).
 744        */
 745        public static void CheckFieldElements(
 746            ECFieldElement  a,
 747            ECFieldElement  b)
 748        {
 749            if (!(a is F2mFieldElement) || !(b is F2mFieldElement))
 750            {
 751                throw new ArgumentException("Field elements are not "
 752                    + "both instances of F2mFieldElement");
 753            }
 754
 755            F2mFieldElement aF2m = (F2mFieldElement)a;
 756            F2mFieldElement bF2m = (F2mFieldElement)b;
 757
 758            if (aF2m.representation != bF2m.representation)
 759            {
 760                // Should never occur
 761                throw new ArgumentException("One of the F2m field elements has incorrect representation");
 762            }
 763
 764            if ((aF2m.m != bF2m.m) || !Arrays.AreEqual(aF2m.ks, bF2m.ks))
 765            {
 766                throw new ArgumentException("Field elements are not elements of the same field F2m");
 767            }
 768        }
 769
 770        public override ECFieldElement Add(
 771            ECFieldElement b)
 772        {
 773            // No check performed here for performance reasons. Instead the
 774            // elements involved are checked in ECPoint.F2m
 775            // checkFieldElements(this, b);
 776            LongArray iarrClone = this.x.Copy();
 777            F2mFieldElement bF2m = (F2mFieldElement)b;
 778            iarrClone.AddShiftedByWords(bF2m.x, 0);
 779            return new F2mFieldElement(m, ks, iarrClone);
 780        }
 781
 782        public override ECFieldElement AddOne()
 783        {
 784            return new F2mFieldElement(m, ks, x.AddOne());
 785        }
 786
 787        public override ECFieldElement Subtract(
 788            ECFieldElement b)
 789        {
 790            // Addition and subtraction are the same in F2m
 791            return Add(b);
 792        }
 793
 794        public override ECFieldElement Multiply(
 795            ECFieldElement b)
 796        {
 797            // Right-to-left comb multiplication in the LongArray
 798            // Input: Binary polynomials a(z) and b(z) of degree at most m-1
 799            // Output: c(z) = a(z) * b(z) mod f(z)
 800
 801            // No check performed here for performance reasons. Instead the
 802            // elements involved are checked in ECPoint.F2m
 803            // checkFieldElements(this, b);
 804            return new F2mFieldElement(m, ks, x.ModMultiply(((F2mFieldElement)b).x, m, ks));
 805        }
 806
 807        public override ECFieldElement MultiplyMinusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y)
 808        {
 809            return MultiplyPlusProduct(b, x, y);
 810        }
 811
 812        public override ECFieldElement MultiplyPlusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y)
 813        {
 814            LongArray ax = this.x, bx = ((F2mFieldElement)b).x, xx = ((F2mFieldElement)x).x, yx = ((F2mFieldElement)y).x
 815
 816            LongArray ab = ax.Multiply(bx, m, ks);
 817            LongArray xy = xx.Multiply(yx, m, ks);
 818
 819            if (ab == ax || ab == bx)
 820            {
 821                ab = (LongArray)ab.Copy();
 822            }
 823
 824            ab.AddShiftedByWords(xy, 0);
 825            ab.Reduce(m, ks);
 826
 827            return new F2mFieldElement(m, ks, ab);
 828        }
 829
 830        public override ECFieldElement Divide(
 831            ECFieldElement b)
 832        {
 833            // There may be more efficient implementations
 834            ECFieldElement bInv = b.Invert();
 835            return Multiply(bInv);
 836        }
 837
 838        public override ECFieldElement Negate()
 839        {
 840            // -x == x holds for all x in F2m
 841            return this;
 842        }
 843
 844        public override ECFieldElement Square()
 845        {
 846            return new F2mFieldElement(m, ks, x.ModSquare(m, ks));
 847        }
 848
 849        public override ECFieldElement SquareMinusProduct(ECFieldElement x, ECFieldElement y)
 850        {
 851            return SquarePlusProduct(x, y);
 852        }
 853
 854        public override ECFieldElement SquarePlusProduct(ECFieldElement x, ECFieldElement y)
 855        {
 856            LongArray ax = this.x, xx = ((F2mFieldElement)x).x, yx = ((F2mFieldElement)y).x;
 857
 858            LongArray aa = ax.Square(m, ks);
 859            LongArray xy = xx.Multiply(yx, m, ks);
 860
 861            if (aa == ax)
 862            {
 863                aa = (LongArray)aa.Copy();
 864            }
 865
 866            aa.AddShiftedByWords(xy, 0);
 867            aa.Reduce(m, ks);
 868
 869            return new F2mFieldElement(m, ks, aa);
 870        }
 871
 872        public override ECFieldElement SquarePow(int pow)
 873        {
 874            return pow < 1 ? this : new F2mFieldElement(m, ks, x.ModSquareN(pow, m, ks));
 875        }
 876
 877        public override ECFieldElement Invert()
 878        {
 879            return new F2mFieldElement(this.m, this.ks, this.x.ModInverse(m, ks));
 880        }
 881
 882        public override ECFieldElement Sqrt()
 883        {
 884            return (x.IsZero() || x.IsOne()) ? this : SquarePow(m - 1);
 885        }
 886
 887        /**
 888            * @return the representation of the field
 889            * <code>F<sub>2<sup>m</sup></sub></code>, either of
 890            * {@link F2mFieldElement.Tpb} (trinomial
 891            * basis representation) or
 892            * {@link F2mFieldElement.Ppb} (pentanomial
 893            * basis representation).
 894            */
 895        public int Representation
 896        {
 897            get { return this.representation; }
 898        }
 899
 900        /**
 901            * @return the degree <code>m</code> of the reduction polynomial
 902            * <code>f(z)</code>.
 903            */
 904        public int M
 905        {
 906            get { return this.m; }
 907        }
 908
 909        /**
 910            * @return Tpb: The integer <code>k</code> where <code>x<sup>m</sup> +
 911            * x<sup>k</sup> + 1</code> represents the reduction polynomial
 912            * <code>f(z)</code>.<br/>
 913            * Ppb: The integer <code>k1</code> where <code>x<sup>m</sup> +
 914            * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
 915            * represents the reduction polynomial <code>f(z)</code>.<br/>
 916            */
 917        public int K1
 918        {
 919            get { return this.ks[0]; }
 920        }
 921
 922        /**
 923            * @return Tpb: Always returns <code>0</code><br/>
 924            * Ppb: The integer <code>k2</code> where <code>x<sup>m</sup> +
 925            * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
 926            * represents the reduction polynomial <code>f(z)</code>.<br/>
 927            */
 928        public int K2
 929        {
 930            get { return this.ks.Length >= 2 ? this.ks[1] : 0; }
 931        }
 932
 933        /**
 934            * @return Tpb: Always set to <code>0</code><br/>
 935            * Ppb: The integer <code>k3</code> where <code>x<sup>m</sup> +
 936            * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
 937            * represents the reduction polynomial <code>f(z)</code>.<br/>
 938            */
 939        public int K3
 940        {
 941            get { return this.ks.Length >= 3 ? this.ks[2] : 0; }
 942        }
 943
 944        public override bool Equals(
 945            object obj)
 946        {
 947            if (obj == this)
 948                return true;
 949
 950            F2mFieldElement other = obj as F2mFieldElement;
 951
 952            if (other == null)
 953                return false;
 954
 955            return Equals(other);
 956        }
 957
 958        public virtual bool Equals(
 959            F2mFieldElement other)
 960        {
 961            return ((this.m == other.m)
 962                && (this.representation == other.representation)
 963                && Arrays.AreEqual(this.ks, other.ks)
 964                && (this.x.Equals(other.x)));
 965        }
 966
 967        public override int GetHashCode()
 968        {
 969            return x.GetHashCode() ^ m ^ Arrays.GetHashCode(ks);
 970        }
 971    }
 972}