public virtual ECFieldElement HalfTrace() { int m = FieldSize; if ((m & 1) == 0) { throw new InvalidOperationException("Half-trace only defined for odd m"); } //ECFieldElement ht = this; //for (int i = 1; i < m; i += 2) //{ // ht = ht.SquarePow(2).Add(this); //} int n = (m + 1) >> 1; int k = 31 - Integers.NumberOfLeadingZeros(n); int nk = 1; ECFieldElement ht = this; while (k > 0) { ht = ht.SquarePow(nk << 1).Add(ht); nk = n >> --k; if (0 != (nk & 1)) { ht = ht.SquarePow(2).Add(this); } } return(ht); }
public virtual int Trace() { int m = FieldSize; //ECFieldElement tr = this; //for (int i = 1; i < m; ++i) //{ // tr = tr.Square().Add(this); //} int k = 31 - Integers.NumberOfLeadingZeros(m); int mk = 1; ECFieldElement tr = this; while (k > 0) { tr = tr.SquarePow(mk).Add(tr); mk = m >> --k; if (0 != (mk & 1)) { tr = tr.Square().Add(this); } } if (tr.IsZero) { return(0); } if (tr.IsOne) { return(1); } throw new InvalidOperationException("Internal error in trace calculation"); }
/** * Encodes an int array whose elements are between 0 and <code>q</code>, * to a byte array leaving no gaps between bits.<br> * <code>q</code> must be a power of 2. * * @param a the input array * @param q the modulus * @return the encoded array */ public static byte[] EncodeModQ(int[] a, int q) { int bitsPerCoeff = 31 - Integers.NumberOfLeadingZeros(q); int numBits = a.Length * bitsPerCoeff; int numBytes = (numBits + 7) / 8; byte[] data = new byte[numBytes]; int bitIndex = 0; int byteIndex = 0; for (int i = 0; i < a.Length; i++) { for (int j = 0; j < bitsPerCoeff; j++) { int currentBit = (a[i] >> j) & 1; data[byteIndex] = (byte)(data[byteIndex] | currentBit << bitIndex); if (bitIndex == 7) { bitIndex = 0; byteIndex++; } else { bitIndex++; } } } return(data); }
/** * Decodes data encoded with {@link #encodeModQ(int[], int)} back to an <code>int</code> array.<br> * <code>N</code> is the number of coefficients. <code>q</code> must be a power of <code>2</code>.<br> * Ignores any excess bytes. * * @param is an encoded ternary polynomial * @param N number of coefficients * @param q * @return the decoded polynomial */ public static int[] DecodeModQ(Stream stream, int N, int q) { int qBits = 31 - Integers.NumberOfLeadingZeros(q); int size = (N * qBits + 7) / 8; byte[] arr = Util.ReadFullLength(stream, size); return(DecodeModQ(arr, N, q)); }
public static uint ModOddInverse(uint[] m, uint[] x, uint[] z) { int len32 = m.Length; Debug.Assert(len32 > 0); Debug.Assert((m[0] & 1) != 0); Debug.Assert(m[len32 - 1] != 0); int bits = (len32 << 5) - Integers.NumberOfLeadingZeros((int)m[len32 - 1]); int len30 = (bits + 29) / 30; int[] t = new int[4]; int[] D = new int[len30]; int[] E = new int[len30]; int[] F = new int[len30]; int[] G = new int[len30]; int[] M = new int[len30]; E[0] = 1; Encode30(bits, x, 0, G, 0); Encode30(bits, m, 0, M, 0); Array.Copy(M, 0, F, 0, len30); int eta = -1; int m0Inv32 = (int)Inverse32((uint)M[0]); int maxDivsteps = GetMaximumDivsteps(bits); for (int divSteps = 0; divSteps < maxDivsteps; divSteps += 30) { eta = Divsteps30(eta, F[0], G[0], t); UpdateDE30(len30, D, E, t, m0Inv32, M); UpdateFG30(len30, F, G, t); } int signF = F[len30 - 1] >> 31; /* * D is in the range (-2.M, M). First, conditionally add M if D is negative, to bring it * into the range (-M, M). Then normalize by conditionally negating (according to signF) * and/or then adding M, to bring it into the range [0, M). */ int signD = D[len30 - 1] >> 31; signD = CAdd30(len30, signD, D, M); CNormalize30(len30, signF, D, M); Decode30(bits, D, 0, z, 0); Debug.Assert(0 != Nat.LessThan(len32, z, m)); signF = CNegate30(len30, signF, F); Debug.Assert(0 == signF); return((uint)(EqualTo(len30, F, 1) & EqualToZero(len30, G))); }
public void TestNumberOfLeadingZeros() { for (int i = 0; i < 31; ++i) { Assert.AreEqual(i, Integers.NumberOfLeadingZeros((int)(0x80000000U >> i))); Assert.AreEqual(i, Integers.NumberOfLeadingZeros((int)(0xFFFFFFFFU >> i))); } Assert.AreEqual(31, Integers.NumberOfLeadingZeros(1)); Assert.AreEqual(32, Integers.NumberOfLeadingZeros(0)); }
public static uint ModOddInverse(uint[] m, uint[] x, uint[] z) { int len32 = m.Length; Debug.Assert(len32 > 0); Debug.Assert((m[0] & 1) != 0); Debug.Assert(m[len32 - 1] != 0); int bits = (len32 << 5) - Integers.NumberOfLeadingZeros((int)m[len32 - 1]); int len30 = (bits + 29) / 30; int m0Inv30x4 = -(int)Inverse32(m[0]) << 2; int[] t = new int[4]; int[] D = new int[len30]; int[] E = new int[len30]; int[] F = new int[len30]; int[] G = new int[len30]; int[] M = new int[len30]; E[0] = 1; Encode30(bits, x, 0, G, 0); Encode30(bits, m, 0, M, 0); Array.Copy(M, 0, F, 0, len30); int eta = -1; int maxDivsteps = GetMaximumDivsteps(bits); for (int divSteps = 0; divSteps < maxDivsteps; divSteps += 30) { eta = Divsteps30(eta, F[0], G[0], t); UpdateDE30(len30, D, E, t, m0Inv30x4, M); UpdateFG30(len30, F, G, t); } int signF = F[len30 - 1] >> 31; Debug.Assert(-1 == signF | 0 == signF); CNegate30(len30, signF, F); CNegate30(len30, signF, D); Decode30(bits, D, 0, z, 0); int signD = D[len30 - 1] >> 31; Debug.Assert(-1 == signD | 0 == signD); signD += (int)Nat.CAdd(len32, signD, z, m, z); Debug.Assert(0 == signD & 0 != Nat.LessThan(len32, z, m)); return((uint)(EqualTo(len30, F, 1) & EqualToZero(len30, G))); }
/** * Decodes a byte array encoded with {@link #toBinary()} to a ploynomial. * * @param is an input stream containing an encoded polynomial * @param N number of coefficients including zeros * @param numOnes number of coefficients equal to 1 * @param numNegOnes number of coefficients equal to -1 * @return the decoded polynomial * @throws IOException */ public static SparseTernaryPolynomial FromBinary(Stream stream, int N, int numOnes, int numNegOnes) { int maxIndex = 1 << BITS_PER_INDEX; int bitsPerIndex = 32 - Integers.NumberOfLeadingZeros(maxIndex - 1); int data1Len = (numOnes * bitsPerIndex + 7) / 8; byte[] data1 = Util.Util.ReadFullLength(stream, data1Len); int[] ones = ArrayEncoder.DecodeModQ(data1, numOnes, maxIndex); int data2Len = (numNegOnes * bitsPerIndex + 7) / 8; byte[] data2 = Util.Util.ReadFullLength(stream, data2Len); int[] negOnes = ArrayEncoder.DecodeModQ(data2, numNegOnes, maxIndex); return(new SparseTernaryPolynomial(N, ones, negOnes)); }
/** * Decodes a <code>byte</code> array encoded with {@link #encodeModQ(int[], int)} back to an <code>int</code> array.<br> * <code>N</code> is the number of coefficients. <code>q</code> must be a power of <code>2</code>.<br> * Ignores any excess bytes. * * @param data an encoded ternary polynomial * @param N number of coefficients * @param q * @return an array containing <code>N</code> coefficients between <code>0</code> and <code>q-1</code> */ public static int[] DecodeModQ(byte[] data, int N, int q) { int[] coeffs = new int[N]; int bitsPerCoeff = 31 - Integers.NumberOfLeadingZeros(q); int numBits = N * bitsPerCoeff; int coeffIndex = 0; for (int bitIndex = 0; bitIndex < numBits; bitIndex++) { if (bitIndex > 0 && bitIndex % bitsPerCoeff == 0) { coeffIndex++; } int bit = GetBit(data, bitIndex); coeffs[coeffIndex] += bit << (bitIndex % bitsPerCoeff); } return(coeffs); }
private void ImplAddSubtractMultiplyTwiceEncodingTest(ECCurve curve, ECPoint q, BigInteger n) { // Get point at infinity on the curve ECPoint infinity = curve.Infinity; ImplTestAddSubtract(q, infinity); ImplTestMultiply(q, n.BitLength); ImplTestMultiply(infinity, n.BitLength); int logSize = 32 - Integers.NumberOfLeadingZeros(curve.FieldSize - 1); int rounds = System.Math.Max(2, System.Math.Min(10, 32 - 3 * logSize)); ECPoint p = q; for (int i = 0; ;) { ImplTestEncoding(p); if (++i == rounds) { break; } p = p.Twice(); } }
public static bool ModOddInverseVar(uint[] m, uint[] x, uint[] z) { int len32 = m.Length; Debug.Assert(len32 > 0); Debug.Assert((m[0] & 1) != 0); Debug.Assert(m[len32 - 1] != 0); int bits = (len32 << 5) - Integers.NumberOfLeadingZeros((int)m[len32 - 1]); int len30 = (bits + 29) / 30; int m0Inv30x4 = -(int)Inverse32(m[0]) << 2; int[] t = new int[4]; int[] D = new int[len30]; int[] E = new int[len30]; int[] F = new int[len30]; int[] G = new int[len30]; int[] M = new int[len30]; E[0] = 1; Encode30(bits, x, 0, G, 0); Encode30(bits, m, 0, M, 0); Array.Copy(M, 0, F, 0, len30); int clzG = Integers.NumberOfLeadingZeros(G[len30 - 1] | 1) - (len30 * 30 + 2 - bits); int eta = -1 - clzG; int lenDE = len30, lenFG = len30; int maxDivsteps = GetMaximumDivsteps(bits); int divsteps = 0; while (!IsZero(lenFG, G)) { if (divsteps >= maxDivsteps) { return(false); } divsteps += 30; eta = Divsteps30Var(eta, F[0], G[0], t); UpdateDE30(lenDE, D, E, t, m0Inv30x4, M); UpdateFG30(lenFG, F, G, t); int fn = F[lenFG - 1]; int gn = G[lenFG - 1]; int cond = (lenFG - 2) >> 31; cond |= fn ^ (fn >> 31); cond |= gn ^ (gn >> 31); if (cond == 0) { F[lenFG - 2] |= fn << 30; G[lenFG - 2] |= gn << 30; --lenFG; } } int signF = F[lenFG - 1] >> 31; Debug.Assert(-1 == signF | 0 == signF); if (0 != signF) { Negate30(lenFG, F); Negate30(lenDE, D); } if (!IsOne(lenFG, F)) { return(false); } Decode30(bits, D, 0, z, 0); int signD = D[lenDE - 1] >> 31; Debug.Assert(-1 == signD | 0 == signD); if (signD < 0) { signD += (int)Nat.AddTo(len32, m, z); } Debug.Assert(0 == signD && !Nat.Gte(len32, z, m)); return(true); }
/** * Multiplies <code>this</code> by an integer <code>k</code> using the * Window NAF method. * @param k The integer by which <code>this</code> is multiplied. * @return A new <code>ECPoint</code> which equals <code>this</code> * multiplied by <code>k</code>. */ protected override ECPoint MultiplyPositive(ECPoint p, BigInteger k) { int minWidth = WNafUtilities.GetWindowSize(k.BitLength); WNafPreCompInfo info = WNafUtilities.Precompute(p, minWidth, true); ECPoint[] preComp = info.PreComp; ECPoint[] preCompNeg = info.PreCompNeg; int width = info.Width; int[] wnaf = WNafUtilities.GenerateCompactWindowNaf(width, k); ECPoint R = p.Curve.Infinity; int i = wnaf.Length; /* * NOTE: We try to optimize the first window using the precomputed points to substitute an * addition for 2 or more doublings. */ if (i > 1) { int wi = wnaf[--i]; int digit = wi >> 16, zeroes = wi & 0xFFFF; int n = System.Math.Abs(digit); ECPoint[] table = digit < 0 ? preCompNeg : preComp; // Optimization can only be used for values in the lower half of the table if ((n << 2) < (1 << width)) { int highest = 32 - Integers.NumberOfLeadingZeros(n); // TODO Get addition/doubling cost ratio from curve and compare to 'scale' to see if worth substituting? int scale = width - highest; int lowBits = n ^ (1 << (highest - 1)); int i1 = ((1 << (width - 1)) - 1); int i2 = (lowBits << scale) + 1; R = table[i1 >> 1].Add(table[i2 >> 1]); zeroes -= scale; //Console.WriteLine("Optimized: 2^" + scale + " * " + n + " = " + i1 + " + " + i2); } else { R = table[n >> 1]; } R = R.TimesPow2(zeroes); } while (i > 0) { int wi = wnaf[--i]; int digit = wi >> 16, zeroes = wi & 0xFFFF; int n = System.Math.Abs(digit); ECPoint[] table = digit < 0 ? preCompNeg : preComp; ECPoint r = table[n >> 1]; R = R.TwicePlus(r); R = R.TimesPow2(zeroes); } return(R); }
public static bool ModOddInverseVar(uint[] m, uint[] x, uint[] z) { int len32 = m.Length; Debug.Assert(len32 > 0); Debug.Assert((m[0] & 1) != 0); Debug.Assert(m[len32 - 1] != 0); int bits = (len32 << 5) - Integers.NumberOfLeadingZeros((int)m[len32 - 1]); int len30 = (bits + 29) / 30; int[] t = new int[4]; int[] D = new int[len30]; int[] E = new int[len30]; int[] F = new int[len30]; int[] G = new int[len30]; int[] M = new int[len30]; E[0] = 1; Encode30(bits, x, 0, G, 0); Encode30(bits, m, 0, M, 0); Array.Copy(M, 0, F, 0, len30); int clzG = Integers.NumberOfLeadingZeros(G[len30 - 1] | 1) - (len30 * 30 + 2 - bits); int eta = -1 - clzG; int lenDE = len30, lenFG = len30; int m0Inv32 = (int)Inverse32((uint)M[0]); int maxDivsteps = GetMaximumDivsteps(bits); int divsteps = 0; while (!IsZero(lenFG, G)) { if (divsteps >= maxDivsteps) { return(false); } divsteps += 30; eta = Divsteps30Var(eta, F[0], G[0], t); UpdateDE30(lenDE, D, E, t, m0Inv32, M); UpdateFG30(lenFG, F, G, t); int fn = F[lenFG - 1]; int gn = G[lenFG - 1]; int cond = (lenFG - 2) >> 31; cond |= fn ^ (fn >> 31); cond |= gn ^ (gn >> 31); if (cond == 0) { F[lenFG - 2] |= fn << 30; G[lenFG - 2] |= gn << 30; --lenFG; } } int signF = F[lenFG - 1] >> 31; /* * D is in the range (-2.M, M). First, conditionally add M if D is negative, to bring it * into the range (-M, M). Then normalize by conditionally negating (according to signF) * and/or then adding M, to bring it into the range [0, M). */ int signD = D[lenDE - 1] >> 31; if (signD < 0) { signD = Add30(lenDE, D, M); } if (signF < 0) { signD = Negate30(lenDE, D); signF = Negate30(lenFG, F); } Debug.Assert(0 == signF); if (!IsOne(lenFG, F)) { return(false); } if (signD < 0) { signD = Add30(lenDE, D, M); } Debug.Assert(0 == signD); Decode30(bits, D, 0, z, 0); Debug.Assert(!Nat.Gte(len32, z, m)); return(true); }