123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931 |
- #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
- using System;
- using System.Diagnostics;
- using Org.BouncyCastle.Math.Raw;
- using Org.BouncyCastle.Utilities;
- namespace Org.BouncyCastle.Math.EC
- {
- public abstract class ECFieldElement
- {
- public abstract BigInteger ToBigInteger();
- public abstract string FieldName { get; }
- public abstract int FieldSize { get; }
- public abstract ECFieldElement Add(ECFieldElement b);
- public abstract ECFieldElement AddOne();
- public abstract ECFieldElement Subtract(ECFieldElement b);
- public abstract ECFieldElement Multiply(ECFieldElement b);
- public abstract ECFieldElement Divide(ECFieldElement b);
- public abstract ECFieldElement Negate();
- public abstract ECFieldElement Square();
- public abstract ECFieldElement Invert();
- public abstract ECFieldElement Sqrt();
- public virtual int BitLength
- {
- get { return ToBigInteger().BitLength; }
- }
- public virtual bool IsOne
- {
- get { return BitLength == 1; }
- }
- public virtual bool IsZero
- {
- get { return 0 == ToBigInteger().SignValue; }
- }
- public virtual ECFieldElement MultiplyMinusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y)
- {
- return Multiply(b).Subtract(x.Multiply(y));
- }
- public virtual ECFieldElement MultiplyPlusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y)
- {
- return Multiply(b).Add(x.Multiply(y));
- }
- public virtual ECFieldElement SquareMinusProduct(ECFieldElement x, ECFieldElement y)
- {
- return Square().Subtract(x.Multiply(y));
- }
- public virtual ECFieldElement SquarePlusProduct(ECFieldElement x, ECFieldElement y)
- {
- return Square().Add(x.Multiply(y));
- }
- public virtual ECFieldElement SquarePow(int pow)
- {
- ECFieldElement r = this;
- for (int i = 0; i < pow; ++i)
- {
- r = r.Square();
- }
- return r;
- }
- public virtual bool TestBitZero()
- {
- return ToBigInteger().TestBit(0);
- }
- public override bool Equals(object obj)
- {
- return Equals(obj as ECFieldElement);
- }
- public virtual bool Equals(ECFieldElement other)
- {
- if (this == other)
- return true;
- if (null == other)
- return false;
- return ToBigInteger().Equals(other.ToBigInteger());
- }
- public override int GetHashCode()
- {
- return ToBigInteger().GetHashCode();
- }
- public override string ToString()
- {
- return this.ToBigInteger().ToString(16);
- }
- public virtual byte[] GetEncoded()
- {
- return BigIntegers.AsUnsignedByteArray((FieldSize + 7) / 8, ToBigInteger());
- }
- }
- public class FpFieldElement
- : ECFieldElement
- {
- private readonly BigInteger q, r, x;
- internal static BigInteger CalculateResidue(BigInteger p)
- {
- int bitLength = p.BitLength;
- if (bitLength >= 96)
- {
- BigInteger firstWord = p.ShiftRight(bitLength - 64);
- if (firstWord.LongValue == -1L)
- {
- return BigInteger.One.ShiftLeft(bitLength).Subtract(p);
- }
- if ((bitLength & 7) == 0)
- {
- return BigInteger.One.ShiftLeft(bitLength << 1).Divide(p).Negate();
- }
- }
- return null;
- }
- public FpFieldElement(BigInteger q, BigInteger x)
- : this(q, CalculateResidue(q), x)
- {
- }
- internal FpFieldElement(BigInteger q, BigInteger r, BigInteger x)
- {
- if (x == null || x.SignValue < 0 || x.CompareTo(q) >= 0)
- throw new ArgumentException("value invalid in Fp field element", "x");
- this.q = q;
- this.r = r;
- this.x = x;
- }
- public override BigInteger ToBigInteger()
- {
- return x;
- }
- /**
- * return the field name for this field.
- *
- * @return the string "Fp".
- */
- public override string FieldName
- {
- get { return "Fp"; }
- }
- public override int FieldSize
- {
- get { return q.BitLength; }
- }
- public BigInteger Q
- {
- get { return q; }
- }
- public override ECFieldElement Add(
- ECFieldElement b)
- {
- return new FpFieldElement(q, r, ModAdd(x, b.ToBigInteger()));
- }
- public override ECFieldElement AddOne()
- {
- BigInteger x2 = x.Add(BigInteger.One);
- if (x2.CompareTo(q) == 0)
- {
- x2 = BigInteger.Zero;
- }
- return new FpFieldElement(q, r, x2);
- }
- public override ECFieldElement Subtract(
- ECFieldElement b)
- {
- return new FpFieldElement(q, r, ModSubtract(x, b.ToBigInteger()));
- }
- public override ECFieldElement Multiply(
- ECFieldElement b)
- {
- return new FpFieldElement(q, r, ModMult(x, b.ToBigInteger()));
- }
- public override ECFieldElement MultiplyMinusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y)
- {
- BigInteger ax = this.x, bx = b.ToBigInteger(), xx = x.ToBigInteger(), yx = y.ToBigInteger();
- BigInteger ab = ax.Multiply(bx);
- BigInteger xy = xx.Multiply(yx);
- return new FpFieldElement(q, r, ModReduce(ab.Subtract(xy)));
- }
- public override ECFieldElement MultiplyPlusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y)
- {
- BigInteger ax = this.x, bx = b.ToBigInteger(), xx = x.ToBigInteger(), yx = y.ToBigInteger();
- BigInteger ab = ax.Multiply(bx);
- BigInteger xy = xx.Multiply(yx);
- BigInteger sum = ab.Add(xy);
- if (r != null && r.SignValue < 0 && sum.BitLength > (q.BitLength << 1))
- {
- sum = sum.Subtract(q.ShiftLeft(q.BitLength));
- }
- return new FpFieldElement(q, r, ModReduce(sum));
- }
- public override ECFieldElement Divide(
- ECFieldElement b)
- {
- return new FpFieldElement(q, r, ModMult(x, ModInverse(b.ToBigInteger())));
- }
- public override ECFieldElement Negate()
- {
- return x.SignValue == 0 ? this : new FpFieldElement(q, r, q.Subtract(x));
- }
- public override ECFieldElement Square()
- {
- return new FpFieldElement(q, r, ModMult(x, x));
- }
- public override ECFieldElement SquareMinusProduct(ECFieldElement x, ECFieldElement y)
- {
- BigInteger ax = this.x, xx = x.ToBigInteger(), yx = y.ToBigInteger();
- BigInteger aa = ax.Multiply(ax);
- BigInteger xy = xx.Multiply(yx);
- return new FpFieldElement(q, r, ModReduce(aa.Subtract(xy)));
- }
- public override ECFieldElement SquarePlusProduct(ECFieldElement x, ECFieldElement y)
- {
- BigInteger ax = this.x, xx = x.ToBigInteger(), yx = y.ToBigInteger();
- BigInteger aa = ax.Multiply(ax);
- BigInteger xy = xx.Multiply(yx);
- BigInteger sum = aa.Add(xy);
- if (r != null && r.SignValue < 0 && sum.BitLength > (q.BitLength << 1))
- {
- sum = sum.Subtract(q.ShiftLeft(q.BitLength));
- }
- return new FpFieldElement(q, r, ModReduce(sum));
- }
- public override ECFieldElement Invert()
- {
- // TODO Modular inversion can be faster for a (Generalized) Mersenne Prime.
- return new FpFieldElement(q, r, ModInverse(x));
- }
- /**
- * return a sqrt root - the routine verifies that the calculation
- * returns the right value - if none exists it returns null.
- */
- public override ECFieldElement Sqrt()
- {
- if (IsZero || IsOne)
- return this;
- if (!q.TestBit(0))
- throw Org.BouncyCastle.Utilities.Platform.CreateNotImplementedException("even value of q");
- if (q.TestBit(1)) // q == 4m + 3
- {
- BigInteger e = q.ShiftRight(2).Add(BigInteger.One);
- return CheckSqrt(new FpFieldElement(q, r, x.ModPow(e, q)));
- }
- if (q.TestBit(2)) // q == 8m + 5
- {
- BigInteger t1 = x.ModPow(q.ShiftRight(3), q);
- BigInteger t2 = ModMult(t1, x);
- BigInteger t3 = ModMult(t2, t1);
- if (t3.Equals(BigInteger.One))
- {
- return CheckSqrt(new FpFieldElement(q, r, t2));
- }
- // TODO This is constant and could be precomputed
- BigInteger t4 = BigInteger.Two.ModPow(q.ShiftRight(2), q);
- BigInteger y = ModMult(t2, t4);
- return CheckSqrt(new FpFieldElement(q, r, y));
- }
- // q == 8m + 1
- BigInteger legendreExponent = q.ShiftRight(1);
- if (!(x.ModPow(legendreExponent, q).Equals(BigInteger.One)))
- return null;
- BigInteger X = this.x;
- BigInteger fourX = ModDouble(ModDouble(X)); ;
- BigInteger k = legendreExponent.Add(BigInteger.One), qMinusOne = q.Subtract(BigInteger.One);
- BigInteger U, V;
- do
- {
- BigInteger P;
- do
- {
- P = BigInteger.Arbitrary(q.BitLength);
- }
- while (P.CompareTo(q) >= 0
- || !ModReduce(P.Multiply(P).Subtract(fourX)).ModPow(legendreExponent, q).Equals(qMinusOne));
- BigInteger[] result = LucasSequence(P, X, k);
- U = result[0];
- V = result[1];
- if (ModMult(V, V).Equals(fourX))
- {
- return new FpFieldElement(q, r, ModHalfAbs(V));
- }
- }
- while (U.Equals(BigInteger.One) || U.Equals(qMinusOne));
- return null;
- }
- private ECFieldElement CheckSqrt(ECFieldElement z)
- {
- return z.Square().Equals(this) ? z : null;
- }
- private BigInteger[] LucasSequence(
- BigInteger P,
- BigInteger Q,
- BigInteger k)
- {
- // TODO Research and apply "common-multiplicand multiplication here"
- int n = k.BitLength;
- int s = k.GetLowestSetBit();
- Debug.Assert(k.TestBit(s));
- BigInteger Uh = BigInteger.One;
- BigInteger Vl = BigInteger.Two;
- BigInteger Vh = P;
- BigInteger Ql = BigInteger.One;
- BigInteger Qh = BigInteger.One;
- for (int j = n - 1; j >= s + 1; --j)
- {
- Ql = ModMult(Ql, Qh);
- if (k.TestBit(j))
- {
- Qh = ModMult(Ql, Q);
- Uh = ModMult(Uh, Vh);
- Vl = ModReduce(Vh.Multiply(Vl).Subtract(P.Multiply(Ql)));
- Vh = ModReduce(Vh.Multiply(Vh).Subtract(Qh.ShiftLeft(1)));
- }
- else
- {
- Qh = Ql;
- Uh = ModReduce(Uh.Multiply(Vl).Subtract(Ql));
- Vh = ModReduce(Vh.Multiply(Vl).Subtract(P.Multiply(Ql)));
- Vl = ModReduce(Vl.Multiply(Vl).Subtract(Ql.ShiftLeft(1)));
- }
- }
- Ql = ModMult(Ql, Qh);
- Qh = ModMult(Ql, Q);
- Uh = ModReduce(Uh.Multiply(Vl).Subtract(Ql));
- Vl = ModReduce(Vh.Multiply(Vl).Subtract(P.Multiply(Ql)));
- Ql = ModMult(Ql, Qh);
- for (int j = 1; j <= s; ++j)
- {
- Uh = ModMult(Uh, Vl);
- Vl = ModReduce(Vl.Multiply(Vl).Subtract(Ql.ShiftLeft(1)));
- Ql = ModMult(Ql, Ql);
- }
- return new BigInteger[] { Uh, Vl };
- }
- protected virtual BigInteger ModAdd(BigInteger x1, BigInteger x2)
- {
- BigInteger x3 = x1.Add(x2);
- if (x3.CompareTo(q) >= 0)
- {
- x3 = x3.Subtract(q);
- }
- return x3;
- }
- protected virtual BigInteger ModDouble(BigInteger x)
- {
- BigInteger _2x = x.ShiftLeft(1);
- if (_2x.CompareTo(q) >= 0)
- {
- _2x = _2x.Subtract(q);
- }
- return _2x;
- }
- protected virtual BigInteger ModHalf(BigInteger x)
- {
- if (x.TestBit(0))
- {
- x = q.Add(x);
- }
- return x.ShiftRight(1);
- }
- protected virtual BigInteger ModHalfAbs(BigInteger x)
- {
- if (x.TestBit(0))
- {
- x = q.Subtract(x);
- }
- return x.ShiftRight(1);
- }
- protected virtual BigInteger ModInverse(BigInteger x)
- {
- int bits = FieldSize;
- int len = (bits + 31) >> 5;
- uint[] p = Nat.FromBigInteger(bits, q);
- uint[] n = Nat.FromBigInteger(bits, x);
- uint[] z = Nat.Create(len);
- Mod.Invert(p, n, z);
- return Nat.ToBigInteger(len, z);
- }
- protected virtual BigInteger ModMult(BigInteger x1, BigInteger x2)
- {
- return ModReduce(x1.Multiply(x2));
- }
- protected virtual BigInteger ModReduce(BigInteger x)
- {
- if (r == null)
- {
- x = x.Mod(q);
- }
- else
- {
- bool negative = x.SignValue < 0;
- if (negative)
- {
- x = x.Abs();
- }
- int qLen = q.BitLength;
- if (r.SignValue > 0)
- {
- BigInteger qMod = BigInteger.One.ShiftLeft(qLen);
- bool rIsOne = r.Equals(BigInteger.One);
- while (x.BitLength > (qLen + 1))
- {
- BigInteger u = x.ShiftRight(qLen);
- BigInteger v = x.Remainder(qMod);
- if (!rIsOne)
- {
- u = u.Multiply(r);
- }
- x = u.Add(v);
- }
- }
- else
- {
- int d = ((qLen - 1) & 31) + 1;
- BigInteger mu = r.Negate();
- BigInteger u = mu.Multiply(x.ShiftRight(qLen - d));
- BigInteger quot = u.ShiftRight(qLen + d);
- BigInteger v = quot.Multiply(q);
- BigInteger bk1 = BigInteger.One.ShiftLeft(qLen + d);
- v = v.Remainder(bk1);
- x = x.Remainder(bk1);
- x = x.Subtract(v);
- if (x.SignValue < 0)
- {
- x = x.Add(bk1);
- }
- }
- while (x.CompareTo(q) >= 0)
- {
- x = x.Subtract(q);
- }
- if (negative && x.SignValue != 0)
- {
- x = q.Subtract(x);
- }
- }
- return x;
- }
- protected virtual BigInteger ModSubtract(BigInteger x1, BigInteger x2)
- {
- BigInteger x3 = x1.Subtract(x2);
- if (x3.SignValue < 0)
- {
- x3 = x3.Add(q);
- }
- return x3;
- }
- public override bool Equals(
- object obj)
- {
- if (obj == this)
- return true;
- FpFieldElement other = obj as FpFieldElement;
- if (other == null)
- return false;
- return Equals(other);
- }
- public virtual bool Equals(
- FpFieldElement other)
- {
- return q.Equals(other.q) && base.Equals(other);
- }
- public override int GetHashCode()
- {
- return q.GetHashCode() ^ base.GetHashCode();
- }
- }
- /**
- * Class representing the Elements of the finite field
- * <code>F<sub>2<sup>m</sup></sub></code> in polynomial basis (PB)
- * representation. Both trinomial (Tpb) and pentanomial (Ppb) polynomial
- * basis representations are supported. Gaussian normal basis (GNB)
- * representation is not supported.
- */
- public class F2mFieldElement
- : ECFieldElement
- {
- /**
- * Indicates gaussian normal basis representation (GNB). Number chosen
- * according to X9.62. GNB is not implemented at present.
- */
- public const int Gnb = 1;
- /**
- * Indicates trinomial basis representation (Tpb). Number chosen
- * according to X9.62.
- */
- public const int Tpb = 2;
- /**
- * Indicates pentanomial basis representation (Ppb). Number chosen
- * according to X9.62.
- */
- public const int Ppb = 3;
- /**
- * Tpb or Ppb.
- */
- private int representation;
- /**
- * The exponent <code>m</code> of <code>F<sub>2<sup>m</sup></sub></code>.
- */
- private int m;
- private int[] ks;
- /**
- * The <code>LongArray</code> holding the bits.
- */
- private LongArray x;
- /**
- * Constructor for Ppb.
- * @param m The exponent <code>m</code> of
- * <code>F<sub>2<sup>m</sup></sub></code>.
- * @param k1 The integer <code>k1</code> where <code>x<sup>m</sup> +
- * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
- * represents the reduction polynomial <code>f(z)</code>.
- * @param k2 The integer <code>k2</code> where <code>x<sup>m</sup> +
- * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
- * represents the reduction polynomial <code>f(z)</code>.
- * @param k3 The integer <code>k3</code> where <code>x<sup>m</sup> +
- * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
- * represents the reduction polynomial <code>f(z)</code>.
- * @param x The BigInteger representing the value of the field element.
- */
- public F2mFieldElement(
- int m,
- int k1,
- int k2,
- int k3,
- BigInteger x)
- {
- if (x == null || x.SignValue < 0 || x.BitLength > m)
- throw new ArgumentException("value invalid in F2m field element", "x");
- if ((k2 == 0) && (k3 == 0))
- {
- this.representation = Tpb;
- this.ks = new int[] { k1 };
- }
- else
- {
- if (k2 >= k3)
- throw new ArgumentException("k2 must be smaller than k3");
- if (k2 <= 0)
- throw new ArgumentException("k2 must be larger than 0");
- this.representation = Ppb;
- this.ks = new int[] { k1, k2, k3 };
- }
- this.m = m;
- this.x = new LongArray(x);
- }
- /**
- * Constructor for Tpb.
- * @param m The exponent <code>m</code> of
- * <code>F<sub>2<sup>m</sup></sub></code>.
- * @param k The integer <code>k</code> where <code>x<sup>m</sup> +
- * x<sup>k</sup> + 1</code> represents the reduction
- * polynomial <code>f(z)</code>.
- * @param x The BigInteger representing the value of the field element.
- */
- public F2mFieldElement(
- int m,
- int k,
- BigInteger x)
- : this(m, k, 0, 0, x)
- {
- // SaveLocal k1 to k, and set k2 and k3 to 0
- }
- private F2mFieldElement(int m, int[] ks, LongArray x)
- {
- this.m = m;
- this.representation = (ks.Length == 1) ? Tpb : Ppb;
- this.ks = ks;
- this.x = x;
- }
- public override int BitLength
- {
- get { return x.Degree(); }
- }
- public override bool IsOne
- {
- get { return x.IsOne(); }
- }
- public override bool IsZero
- {
- get { return x.IsZero(); }
- }
- public override bool TestBitZero()
- {
- return x.TestBitZero();
- }
- public override BigInteger ToBigInteger()
- {
- return x.ToBigInteger();
- }
- public override string FieldName
- {
- get { return "F2m"; }
- }
- public override int FieldSize
- {
- get { return m; }
- }
- /**
- * Checks, if the ECFieldElements <code>a</code> and <code>b</code>
- * are elements of the same field <code>F<sub>2<sup>m</sup></sub></code>
- * (having the same representation).
- * @param a field element.
- * @param b field element to be compared.
- * @throws ArgumentException if <code>a</code> and <code>b</code>
- * are not elements of the same field
- * <code>F<sub>2<sup>m</sup></sub></code> (having the same
- * representation).
- */
- public static void CheckFieldElements(
- ECFieldElement a,
- ECFieldElement b)
- {
- if (!(a is F2mFieldElement) || !(b is F2mFieldElement))
- {
- throw new ArgumentException("Field elements are not "
- + "both instances of F2mFieldElement");
- }
- F2mFieldElement aF2m = (F2mFieldElement)a;
- F2mFieldElement bF2m = (F2mFieldElement)b;
- if (aF2m.representation != bF2m.representation)
- {
- // Should never occur
- throw new ArgumentException("One of the F2m field elements has incorrect representation");
- }
- if ((aF2m.m != bF2m.m) || !Arrays.AreEqual(aF2m.ks, bF2m.ks))
- {
- throw new ArgumentException("Field elements are not elements of the same field F2m");
- }
- }
- public override ECFieldElement Add(
- ECFieldElement b)
- {
- // No check performed here for performance reasons. Instead the
- // elements involved are checked in ECPoint.F2m
- // checkFieldElements(this, b);
- LongArray iarrClone = this.x.Copy();
- F2mFieldElement bF2m = (F2mFieldElement)b;
- iarrClone.AddShiftedByWords(bF2m.x, 0);
- return new F2mFieldElement(m, ks, iarrClone);
- }
- public override ECFieldElement AddOne()
- {
- return new F2mFieldElement(m, ks, x.AddOne());
- }
- public override ECFieldElement Subtract(
- ECFieldElement b)
- {
- // Addition and subtraction are the same in F2m
- return Add(b);
- }
- public override ECFieldElement Multiply(
- ECFieldElement b)
- {
- // Right-to-left comb multiplication in the LongArray
- // Input: Binary polynomials a(z) and b(z) of degree at most m-1
- // Output: c(z) = a(z) * b(z) mod f(z)
- // No check performed here for performance reasons. Instead the
- // elements involved are checked in ECPoint.F2m
- // checkFieldElements(this, b);
- return new F2mFieldElement(m, ks, x.ModMultiply(((F2mFieldElement)b).x, m, ks));
- }
- public override ECFieldElement MultiplyMinusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y)
- {
- return MultiplyPlusProduct(b, x, y);
- }
- public override ECFieldElement MultiplyPlusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y)
- {
- LongArray ax = this.x, bx = ((F2mFieldElement)b).x, xx = ((F2mFieldElement)x).x, yx = ((F2mFieldElement)y).x;
- LongArray ab = ax.Multiply(bx, m, ks);
- LongArray xy = xx.Multiply(yx, m, ks);
- if (ab == ax || ab == bx)
- {
- ab = (LongArray)ab.Copy();
- }
- ab.AddShiftedByWords(xy, 0);
- ab.Reduce(m, ks);
- return new F2mFieldElement(m, ks, ab);
- }
- public override ECFieldElement Divide(
- ECFieldElement b)
- {
- // There may be more efficient implementations
- ECFieldElement bInv = b.Invert();
- return Multiply(bInv);
- }
- public override ECFieldElement Negate()
- {
- // -x == x holds for all x in F2m
- return this;
- }
- public override ECFieldElement Square()
- {
- return new F2mFieldElement(m, ks, x.ModSquare(m, ks));
- }
- public override ECFieldElement SquareMinusProduct(ECFieldElement x, ECFieldElement y)
- {
- return SquarePlusProduct(x, y);
- }
- public override ECFieldElement SquarePlusProduct(ECFieldElement x, ECFieldElement y)
- {
- LongArray ax = this.x, xx = ((F2mFieldElement)x).x, yx = ((F2mFieldElement)y).x;
- LongArray aa = ax.Square(m, ks);
- LongArray xy = xx.Multiply(yx, m, ks);
- if (aa == ax)
- {
- aa = (LongArray)aa.Copy();
- }
- aa.AddShiftedByWords(xy, 0);
- aa.Reduce(m, ks);
- return new F2mFieldElement(m, ks, aa);
- }
- public override ECFieldElement SquarePow(int pow)
- {
- return pow < 1 ? this : new F2mFieldElement(m, ks, x.ModSquareN(pow, m, ks));
- }
- public override ECFieldElement Invert()
- {
- return new F2mFieldElement(this.m, this.ks, this.x.ModInverse(m, ks));
- }
- public override ECFieldElement Sqrt()
- {
- return (x.IsZero() || x.IsOne()) ? this : SquarePow(m - 1);
- }
- /**
- * @return the representation of the field
- * <code>F<sub>2<sup>m</sup></sub></code>, either of
- * {@link F2mFieldElement.Tpb} (trinomial
- * basis representation) or
- * {@link F2mFieldElement.Ppb} (pentanomial
- * basis representation).
- */
- public int Representation
- {
- get { return this.representation; }
- }
- /**
- * @return the degree <code>m</code> of the reduction polynomial
- * <code>f(z)</code>.
- */
- public int M
- {
- get { return this.m; }
- }
- /**
- * @return Tpb: The integer <code>k</code> where <code>x<sup>m</sup> +
- * x<sup>k</sup> + 1</code> represents the reduction polynomial
- * <code>f(z)</code>.<br/>
- * Ppb: The integer <code>k1</code> where <code>x<sup>m</sup> +
- * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
- * represents the reduction polynomial <code>f(z)</code>.<br/>
- */
- public int K1
- {
- get { return this.ks[0]; }
- }
- /**
- * @return Tpb: Always returns <code>0</code><br/>
- * Ppb: The integer <code>k2</code> where <code>x<sup>m</sup> +
- * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
- * represents the reduction polynomial <code>f(z)</code>.<br/>
- */
- public int K2
- {
- get { return this.ks.Length >= 2 ? this.ks[1] : 0; }
- }
- /**
- * @return Tpb: Always set to <code>0</code><br/>
- * Ppb: The integer <code>k3</code> where <code>x<sup>m</sup> +
- * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
- * represents the reduction polynomial <code>f(z)</code>.<br/>
- */
- public int K3
- {
- get { return this.ks.Length >= 3 ? this.ks[2] : 0; }
- }
- public override bool Equals(
- object obj)
- {
- if (obj == this)
- return true;
- F2mFieldElement other = obj as F2mFieldElement;
- if (other == null)
- return false;
- return Equals(other);
- }
- public virtual bool Equals(
- F2mFieldElement other)
- {
- return ((this.m == other.m)
- && (this.representation == other.representation)
- && Arrays.AreEqual(this.ks, other.ks)
- && (this.x.Equals(other.x)));
- }
- public override int GetHashCode()
- {
- return x.GetHashCode() ^ m ^ Arrays.GetHashCode(ks);
- }
- }
- }
- #endif
|