diff --git a/crypto/src/pqc/crypto/bike/BikeEngine.cs b/crypto/src/pqc/crypto/bike/BikeEngine.cs
index 7df2703c9..ecd7d7efe 100644
--- a/crypto/src/pqc/crypto/bike/BikeEngine.cs
+++ b/crypto/src/pqc/crypto/bike/BikeEngine.cs
@@ -1,11 +1,9 @@
-using Org.BouncyCastle.Crypto;
+using System;
+
+using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Digests;
-using Org.BouncyCastle.Pqc.Math.LinearAlgebra;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities;
-using System;
-using System.Collections.Generic;
-using System.Text;
namespace Org.BouncyCastle.Pqc.Crypto.Bike
{
@@ -32,8 +30,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Bike
// tau
private int tau;
- private GF2mField field;
- private PolynomialGF2mSmallM reductionPoly;
+ private BikePolynomial reductionPoly;
private int L_BYTE;
private int R_BYTE;
@@ -49,13 +46,8 @@ namespace Org.BouncyCastle.Pqc.Crypto.Bike
this.L_BYTE = l / 8;
this.R_BYTE = (r + 7) / 8;
- // finite field GF(2)
- GF2mField field = new GF2mField(1);
- this.field = field;
-
// generate reductionPoly (X^r + 1)
- PolynomialGF2mSmallM poly = new PolynomialGF2mSmallM(field, r);
- this.reductionPoly = poly.AddMonomial(0);
+ this.reductionPoly = new BikePolynomial(r);
}
public int GetSessionKeySize()
@@ -143,11 +135,11 @@ namespace Org.BouncyCastle.Pqc.Crypto.Bike
byte[] h1Cut = Utils.RemoveLast0Bits(h1Bits);
// 2. Compute h
- PolynomialGF2mSmallM h0Poly = new PolynomialGF2mSmallM(this.field, h0Cut);
- PolynomialGF2mSmallM h1Poly = new PolynomialGF2mSmallM(this.field, h1Cut);
+ BikePolynomial h0Poly = new BikePolynomial(h0Cut);
+ BikePolynomial h1Poly = new BikePolynomial(h1Cut);
- PolynomialGF2mSmallM h0Inv = h0Poly.ModInverseBigDeg(reductionPoly);
- PolynomialGF2mSmallM hPoly = h1Poly.ModKaratsubaMultiplyBigDeg(h0Inv, reductionPoly);
+ BikePolynomial h0Inv = h0Poly.ModInverseBigDeg(reductionPoly);
+ BikePolynomial hPoly = h1Poly.ModKaratsubaMultiplyBigDeg(h0Inv, reductionPoly);
// Get coefficients of hPoly
byte[] hTmp = hPoly.GetEncoded();
@@ -191,15 +183,15 @@ namespace Org.BouncyCastle.Pqc.Crypto.Bike
byte[] e0Cut = Utils.RemoveLast0Bits(e0Bits);
byte[] e1Cut = Utils.RemoveLast0Bits(e1Bits);
- PolynomialGF2mSmallM e0 = new PolynomialGF2mSmallM(field, e0Cut);
- PolynomialGF2mSmallM e1 = new PolynomialGF2mSmallM(field, e1Cut);
+ BikePolynomial e0 = new BikePolynomial(e0Cut);
+ BikePolynomial e1 = new BikePolynomial(e1Cut);
// 3. Calculate c
// calculate c0
byte[] h0Bits = new byte[r];
Utils.FromByteArrayToBitArray(h0Bits, h);
- PolynomialGF2mSmallM hPoly = new PolynomialGF2mSmallM(field, Utils.RemoveLast0Bits(h0Bits));
- PolynomialGF2mSmallM c0Poly = e0.add(e1.ModKaratsubaMultiplyBigDeg(hPoly, reductionPoly));
+ BikePolynomial hPoly = new BikePolynomial(Utils.RemoveLast0Bits(h0Bits));
+ BikePolynomial c0Poly = e0.Add(e1.ModKaratsubaMultiplyBigDeg(hPoly, reductionPoly));
byte[] c0Bits = c0Poly.GetEncoded();
byte[] c0Bytes = new byte[R_BYTE];
@@ -287,10 +279,10 @@ namespace Org.BouncyCastle.Pqc.Crypto.Bike
private byte[] ComputeSyndrome(byte[] h0, byte[] c0)
{
- PolynomialGF2mSmallM coPoly = new PolynomialGF2mSmallM(field, c0);
- PolynomialGF2mSmallM h0Poly = new PolynomialGF2mSmallM(field, h0);
+ BikePolynomial coPoly = new BikePolynomial(c0);
+ BikePolynomial h0Poly = new BikePolynomial(h0);
- PolynomialGF2mSmallM s = coPoly.ModKaratsubaMultiplyBigDeg(h0Poly, reductionPoly);
+ BikePolynomial s = coPoly.ModKaratsubaMultiplyBigDeg(h0Poly, reductionPoly);
byte[] transposedS = Transpose(s.GetEncoded());
return transposedS;
}
@@ -318,11 +310,11 @@ namespace Org.BouncyCastle.Pqc.Crypto.Bike
BFMaskedIter(s, e, gray, (hw + 1) / 2 + 1, h0Compact, h1Compact, h0CompactCol, h1CompactCol);
}
}
+
if (Utils.GetHammingWeight(s) == 0)
- {
return e;
- }
- else return null;
+
+ return null;
}
private byte[] Transpose(byte[] input)
@@ -336,6 +328,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Bike
}
return output;
}
+
private void BFIter(byte[] s, byte[] e, int T, int[] h0Compact, int[] h1Compact, int[] h0CompactCol, int[] h1CompactCol, byte[] black, byte[] gray)
{
int[] updatedIndices = new int[2 * r];
diff --git a/crypto/src/pqc/crypto/bike/BikeParameters.cs b/crypto/src/pqc/crypto/bike/BikeParameters.cs
index e5695c48f..e4d06b861 100644
--- a/crypto/src/pqc/crypto/bike/BikeParameters.cs
+++ b/crypto/src/pqc/crypto/bike/BikeParameters.cs
@@ -1,11 +1,11 @@
-using Org.BouncyCastle.Crypto;
-using System;
-using System.Collections.Generic;
-using System.Text;
+using System;
+
+using Org.BouncyCastle.Crypto;
namespace Org.BouncyCastle.Pqc.Crypto.Bike
{
- public class BikeParameters : ICipherParameters
+ public class BikeParameters
+ : ICipherParameters
{
// 128 bits security
public static BikeParameters bike128 = new BikeParameters("bike128", 12323, 142, 134, 256, 5, 3, 128);
@@ -26,7 +26,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Bike
private int defaultKeySize;
private BikeEngine bikeEngine;
- internal BikeParameters(String name, int r, int w, int t, int l, int nbIter, int tau, int defaultKeySize)
+ internal BikeParameters(string name, int r, int w, int t, int l, int nbIter, int tau, int defaultKeySize)
{
this.name = name;
this.r = r;
diff --git a/crypto/src/pqc/crypto/bike/BikePolynomial.cs b/crypto/src/pqc/crypto/bike/BikePolynomial.cs
new file mode 100644
index 000000000..0d66fe433
--- /dev/null
+++ b/crypto/src/pqc/crypto/bike/BikePolynomial.cs
@@ -0,0 +1,469 @@
+using System;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Pqc.Crypto.Bike
+{
+ internal class BikePolynomial
+ {
+ /**
+ * For the polynomial representation the map f: R->Z*,
+ * <tt>poly(X) -> [coef_0, coef_1, ...]</tt> is used, where
+ * <tt>coef_i</tt> is the <tt>i</tt>th coefficient of the polynomial
+ * represented as int (see {@link GF2mField}). The polynomials are stored
+ * as int arrays.
+ */
+ private readonly int[] m_coefficients;
+
+ /**
+ * Construct a monomial of the given degree over the finite field GF(2^m).
+ *
+ * @param field the finite field GF(2^m)
+ * @param degree the degree of the monomial
+ */
+ internal BikePolynomial(int degree)
+ {
+ // Initial value (X^r + 1)
+ this.m_coefficients = new int[degree + 1];
+ this.m_coefficients[degree] = 1;
+ this.m_coefficients[0] ^= 1;
+ }
+
+ /**
+ * Construct the polynomial over the given finite field GF(2^m) from the
+ * given coefficient vector.
+ *
+ * @param field finite field GF2m
+ * @param coeffs the coefficient vector
+ */
+ private BikePolynomial(int[] coeffs)
+ {
+ this.m_coefficients = NormalForm(coeffs);
+ }
+
+ /**
+ * Create a polynomial over the finite field GF(2^m).
+ *
+ * @param field the finite field GF(2^m)
+ * @param enc byte[] polynomial in byte array form
+ */
+ internal BikePolynomial(byte[] enc)
+ {
+ // decodes polynomial
+ this.m_coefficients = new int[enc.Length];
+ for (int i = 0; i < m_coefficients.Length; i++)
+ {
+ m_coefficients[i] = enc[i];
+ if ((m_coefficients[i] >> 1) != 0)
+ throw new ArgumentException(
+ "Error: byte array is not encoded polynomial over given finite field GF2m");
+ }
+ // if HC = 0 for non-zero polynomial, returns error
+ if ((m_coefficients.Length != 1) && (m_coefficients[m_coefficients.Length - 1] == 0))
+ throw new ArgumentException("Error: byte array is not encoded polynomial over given finite field GF2m");
+ }
+
+ /**
+ * Returns encoded polynomial, i.e., this polynomial in byte array form
+ *
+ * @return the encoded polynomial
+ */
+ internal byte[] GetEncoded()
+ {
+ byte[] res = new byte[m_coefficients.Length];
+ for (int i = 0; i < m_coefficients.Length; i++)
+ {
+ res[i] = (byte)m_coefficients[i];
+ }
+ return res;
+ }
+
+ /**
+ * Compute the sum of this polynomial and the given polynomial.
+ *
+ * @param addend the addend
+ * @return <tt>this + a</tt> (newly created)
+ */
+ internal BikePolynomial Add(BikePolynomial addend)
+ {
+ int[] resultCoeff = Add(m_coefficients, addend.m_coefficients);
+ return new BikePolynomial(resultCoeff);
+ }
+
+ /**
+ * Compute the sum of two polynomials a and b over the finite field
+ * <tt>GF(2^m)</tt>.
+ *
+ * @param a the first polynomial
+ * @param b the second polynomial
+ * @return a + b
+ */
+ private int[] Add(int[] a, int[] b)
+ {
+ int[] result, addend;
+ if (a.Length < b.Length)
+ {
+ result = new int[b.Length];
+ Array.Copy(b, 0, result, 0, b.Length);
+ addend = a;
+ }
+ else
+ {
+ result = new int[a.Length];
+ Array.Copy(a, 0, result, 0, a.Length);
+ addend = b;
+ }
+
+ for (int i = addend.Length - 1; i >= 0; i--)
+ {
+ result[i] ^= addend[i];
+ }
+
+ return result;
+ }
+
+ /**
+ * Compute the product of a polynomial a with an element from the finite
+ * field <tt>GF(2^m)</tt>.
+ *
+ * @param a the polynomial
+ * @param element an element of the finite field GF(2^m)
+ * @return <tt>a * element</tt>
+ */
+ private int[] MultWithElement(int[] a, int element)
+ {
+ return element == 0 ? new int[1] : Arrays.Clone(a);
+ }
+
+ /**
+ * Compute the product of a polynomial with a monomial X^k.
+ *
+ * @param a the polynomial
+ * @param k the degree of the monomial
+ * @return <tt>a * X^k</tt>
+ */
+ private static int[] MultWithMonomial(int[] a, int k)
+ {
+ int d = ComputeDegree(a);
+ if (d == -1)
+ return new int[1];
+
+ int[] result = new int[k + d + 1];
+ Array.Copy(a, 0, result, k, d + 1);
+ return result;
+ }
+
+ /**
+ * Compute the result of the division of two polynomials over the field
+ * <tt>GF(2^m)</tt>.
+ *
+ * @param a the first polynomial
+ * @param f the second polynomial
+ * @return int[][] {q,r}, where a = q*f+r and deg(r) < deg(f);
+ */
+ private int[][] Div(int[] a, int[] f)
+ {
+ int df = ComputeDegree(f);
+ if (df == -1)
+ throw new ArithmeticException("Division by zero.");
+
+ int degreeR1 = ComputeDegree(a);
+ int[][] result = new int[2][];
+ result[0] = new int[1]{ 0 };
+ result[1] = Arrays.CopyOf(a, degreeR1 + 1);
+
+ while (df <= degreeR1)
+ {
+ int[] q;
+ int[] coeff = new int[1];
+ coeff[0] = degreeR1 == -1 ? 0 : result[1][degreeR1];
+ q = MultWithElement(f, coeff[0]);
+ int n = degreeR1 - df;
+ q = MultWithMonomial(q, n);
+ coeff = MultWithMonomial(coeff, n);
+ result[0] = Add(coeff, result[0]);
+ result[1] = Add(q, result[1]);
+ degreeR1 = ComputeDegree(result[1]);
+ }
+ return result;
+ }
+
+ /**
+ * Compute the product of two polynomials over the field <tt>GF(2^m)</tt>
+ * using a Karatzuba like multiplication.
+ *
+ * @param a the first polynomial
+ * @param b the second polynomial
+ * @return a * b
+ */
+ private int[] Multiply(int[] a, int[] b)
+ {
+ int[] mult1, mult2;
+ if (ComputeDegree(a) < ComputeDegree(b))
+ {
+ mult1 = b;
+ mult2 = a;
+ }
+ else
+ {
+ mult1 = a;
+ mult2 = b;
+ }
+
+ mult1 = NormalForm(mult1);
+ mult2 = NormalForm(mult2);
+
+ if (mult2.Length == 1)
+ return MultWithElement(mult1, mult2[0]);
+
+ int d1 = mult1.Length;
+ int d2 = mult2.Length;
+ int[] result;
+
+ if (d2 != d1)
+ {
+ int[] res1 = new int[d2];
+ int[] res2 = new int[d1 - d2];
+ Array.Copy(mult1, 0, res1, 0, res1.Length);
+ Array.Copy(mult1, d2, res2, 0, res2.Length);
+ res1 = Multiply(res1, mult2);
+ res2 = Multiply(res2, mult2);
+ res2 = MultWithMonomial(res2, d2);
+ result = Add(res1, res2);
+ }
+ else
+ {
+ d2 = (int)((uint)(d1 + 1) >> 1);
+ int d = d1 - d2;
+ int[] firstPartMult1 = new int[d2];
+ int[] firstPartMult2 = new int[d2];
+ int[] secondPartMult1 = new int[d];
+ int[] secondPartMult2 = new int[d];
+ Array.Copy(mult1, 0, firstPartMult1, 0, firstPartMult1.Length);
+ Array.Copy(mult1, d2, secondPartMult1, 0, secondPartMult1.Length);
+ Array.Copy(mult2, 0, firstPartMult2, 0, firstPartMult2.Length);
+ Array.Copy(mult2, d2, secondPartMult2, 0, secondPartMult2.Length);
+ int[] helpPoly1 = Add(firstPartMult1, secondPartMult1);
+ int[] helpPoly2 = Add(firstPartMult2, secondPartMult2);
+ int[] res1 = Multiply(firstPartMult1, firstPartMult2);
+ int[] res2 = Multiply(helpPoly1, helpPoly2);
+ int[] res3 = Multiply(secondPartMult1, secondPartMult2);
+ res2 = Add(res2, res1);
+ res2 = Add(res2, res3);
+ res3 = MultWithMonomial(res3, d2);
+ result = Add(res2, res3);
+ result = MultWithMonomial(result, d2);
+ result = Add(result, res1);
+ }
+
+ return result;
+ }
+
+ /**
+ * Reduce a polynomial modulo another polynomial.
+ *
+ * @param a the polynomial
+ * @param f the reduction polynomial
+ * @return <tt>a mod f</tt>
+ */
+ private int[] Mod(int[] a, int[] f)
+ {
+ int df = ComputeDegree(f);
+ if (df == -1)
+ throw new ArithmeticException("Division by zero");
+
+ int degreeR = ComputeDegree(a);
+ int[] result = Arrays.CopyOf(a, degreeR + 1);
+
+ while (df <= degreeR)
+ {
+ int coeff = degreeR == -1 ? 0 : result[degreeR];
+ int[] q = MultWithMonomial(f, degreeR - df);
+ q = MultWithElement(q, coeff);
+ result = Add(q, result);
+ degreeR = ComputeDegree(result);
+ }
+ return result;
+ }
+
+ /**
+ * Compute the degree of a polynomial.
+ *
+ * @param a the polynomial
+ * @return the degree of the polynomial <tt>a</tt>. If <tt>a</tt> is
+ * the zero polynomial, return -1.
+ */
+ private static int ComputeDegree(int[] a)
+ {
+ int degree;
+ for (degree = a.Length - 1; degree >= 0 && a[degree] == 0; degree--)
+ {
+ }
+ return degree;
+ }
+
+ /**
+ * Strip leading zero coefficients from the given polynomial.
+ *
+ * @param a the polynomial
+ * @return the reduced polynomial
+ */
+ private static int[] NormalForm(int[] a)
+ {
+ int d = ComputeDegree(a);
+
+ // if a is the zero polynomial
+ if (d == -1)
+ {
+ // return new zero polynomial
+ return new int[1];
+ }
+
+ // if a already is in normal form
+ if (a.Length == d + 1)
+ {
+ // return a clone of a
+ return Arrays.Clone(a);
+ }
+
+ // else, reduce a
+ int[] result = new int[d + 1];
+ Array.Copy(a, 0, result, 0, d + 1);
+ return result;
+ }
+
+ /**
+ * Compute the product of this polynomial and another polynomial modulo a
+ * third polynomial.
+ *
+ * @param a another polynomial
+ * @param b the reduction polynomial
+ * @return <tt>this * a mod b</tt>
+ */
+ internal BikePolynomial ModKaratsubaMultiplyBigDeg(BikePolynomial a, BikePolynomial b)
+ {
+ int[] resultCoeff = ModKaratsubaMultiplyBigDeg(m_coefficients, a.m_coefficients, b.m_coefficients);
+ return new BikePolynomial(resultCoeff);
+ }
+
+ /**
+ * Compute the inverse of this polynomial modulo the given polynomial.
+ *
+ * @param a the reduction polynomial
+ * @return <tt>this^(-1) mod a</tt>
+ */
+ internal BikePolynomial ModInverseBigDeg(BikePolynomial a)
+ {
+ int[] resultCoeff = ModInvBigDeg(m_coefficients, a.m_coefficients);
+ return new BikePolynomial(resultCoeff);
+ }
+
+ private int[] ModInvBigDeg(int[] b, int[] g)
+ {
+ int[] r0 = NormalForm(g);
+ int[] r1 = Mod(b, g);
+ int[] s0 = { 0 };
+ int[] s1 = { 1 };
+ int[] s2;
+ int[][] q;
+ while (ComputeDegree(r1) != -1)
+ {
+ q = Div(r0, r1);
+ r0 = NormalForm(r1);
+ r1 = NormalForm(q[1]);
+ s2 = Add(s0, ModKaratsubaMultiplyBigDeg(q[0], s1, g));
+ s0 = NormalForm(s1);
+ s1 = NormalForm(s2);
+ }
+ return s0;
+ }
+
+ /**
+ * Compute the product of two polynomials modulo a third polynomial over the
+ * finite field <tt>GF(2^m)</tt>.
+ *
+ * @param aa the first polynomial
+ * @param bb the second polynomial
+ * @param g the reduction polynomial
+ * @return <tt>a * b mod g</tt>
+ */
+ private int[] ModKaratsubaMultiplyBigDeg(int[] aa, int[] bb, int[] g)
+ {
+ int[] a, b;
+ if (aa.Length >= bb.Length)
+ {
+ a = aa;
+ b = bb;
+ }
+ else
+ {
+ a = bb;
+ b = aa;
+ }
+
+ int n = a.Length;
+ int m = b.Length;
+
+ int[] D = new int[(n + m) / 2];
+ int[] S = new int[n + m - 1];
+ int[] T = new int[n + m - 1];
+ int[] C = new int[n + m - 1];
+
+ for (int i = 0; i < m; i++)
+ {
+ D[i] = a[i] * b[i];
+ }
+
+ for (int i = 1; i < n + m - 2; i++)
+ {
+ int pLimit = System.Math.Min(m, (i + 1) >> 1);
+ for (int p = 0; p < pLimit; p++)
+ {
+ int q = i - p;
+
+ int ap = a[p];
+ int aq = q < a.Length ? a[q] : 0;
+
+ int bp = b[p];
+ int dp = D[p];
+
+ if (q < m)
+ {
+ int bq = b[q];
+ int dq = D[q];
+
+ S[i] = S[i] + (ap + aq) * (bp + bq);
+ T[i] = T[i] + dp + dq;
+ }
+ else if (q < n)
+ {
+ S[i] = S[i] + ((ap + aq) * bp);
+ T[i] = T[i] + dp;
+ }
+ }
+ }
+
+ for (int i = 0; i < n + m - 1; i++)
+ {
+ if (i == 0)
+ {
+ C[i] = D[i] % 2;
+ }
+ else if (i == n + m - 2)
+ {
+ C[i] = (a[a.Length - 1] * b[b.Length - 1]) % 2;
+ }
+ else if (i % 2 == 1)
+ {
+ C[i] = (S[i] - T[i]) % 2;
+ }
+ else
+ {
+ C[i] = (S[i] - T[i] + D[i / 2]) % 2;
+ }
+ }
+
+ return Mod(C, g);
+ }
+ }
+}
diff --git a/crypto/src/pqc/crypto/bike/BikeRandomGenerator.cs b/crypto/src/pqc/crypto/bike/BikeRandomGenerator.cs
index 4d9a90252..7117c1d9d 100644
--- a/crypto/src/pqc/crypto/bike/BikeRandomGenerator.cs
+++ b/crypto/src/pqc/crypto/bike/BikeRandomGenerator.cs
@@ -1,40 +1,21 @@
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Utilities;
-using System;
-using System.Collections.Generic;
-using System.Text;
+using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Pqc.Crypto.Bike
{
- class BikeRandomGenerator
+ internal class BikeRandomGenerator
{
- private static int BitScanReverse(int t)
- {
- int res = 0;
- while (t != 0)
- {
- t >>= 1;
- res++;
- }
-
- return res;
- }
-
private static int GetRandomInMod(int mod, IXof digest)
{
- int mask = MaskNumber(BitScanReverse(mod));
- int res = -1;
+ int highest = Integers.HighestOneBit(mod);
+ int mask = highest | (highest - 1);
while (true)
{
- res = GetRandomNumber(digest);
- res &= mask;
-
+ int res = GetRandomNumber(digest) & mask;
if (res < mod)
- {
- break;
- }
+ return res;
}
- return res;
}
private static void GenerateRandomArray(byte[] res, int mod, int weight, IXof digest)
@@ -59,8 +40,6 @@ namespace Org.BouncyCastle.Pqc.Crypto.Bike
return ((a[index] >> (pos)) & 0x01);
}
-
-
private static void SetBit(byte[] a, int position)
{
int index = position / 8;
@@ -75,17 +54,11 @@ namespace Org.BouncyCastle.Pqc.Crypto.Bike
return res;
}
- private static int MaskNumber(int n)
- {
- return ((1 << n) - 1);
- }
-
private static int GetRandomNumber(IXof digest)
{
byte[] output = new byte[4];
digest.Output(output, 0, output.Length);
- int tmp = (int)Pack.LE_To_UInt32(output, 0);
- return tmp;
+ return (int)Pack.LE_To_UInt32(output, 0);
}
}
}
diff --git a/crypto/src/pqc/crypto/bike/Utils.cs b/crypto/src/pqc/crypto/bike/Utils.cs
index 8a1a05e37..5d151f522 100644
--- a/crypto/src/pqc/crypto/bike/Utils.cs
+++ b/crypto/src/pqc/crypto/bike/Utils.cs
@@ -1,10 +1,8 @@
using System;
-using System.Collections.Generic;
-using System.Text;
namespace Org.BouncyCastle.Pqc.Crypto.Bike
{
- class Utils
+ internal class Utils
{
internal static byte[] XorBytes(byte[] a, byte[] b, int size)
{
@@ -34,7 +32,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Bike
{
for (int j = 0; j != 8; j++)
{
- output[i * 8 + j] = (byte)UnsignedRightBitShiftInt(input[i] & (1 << j), j);
+ output[i * 8 + j] = (byte)((input[i] >> j) & 1);
}
}
if (output.Length % 8 != 0)
@@ -43,7 +41,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Bike
int count = 0;
while (off < output.Length)
{
- output[off++] = (byte)(UnsignedRightBitShiftInt(input[max] & (1 << count), count));
+ output[off++] = (byte)((input[max] >> count) & 1);
count++;
}
}
@@ -102,18 +100,5 @@ namespace Org.BouncyCastle.Pqc.Crypto.Bike
Array.Copy(input, 0, output, 0, input.Length);
return output;
}
- internal static int UnsignedRightBitShiftInt(int a, int b)
- {
- uint tmp = (uint)a;
- tmp >>= b;
- return (int)tmp;
- }
-
- internal static long UnsignedRightBitShiftLong(long a, int b)
- {
- ulong tmp = (ulong)a;
- tmp >>= b;
- return (long)tmp;
- }
}
}
diff --git a/crypto/src/pqc/math/linearalgebra/GF2mField.cs b/crypto/src/pqc/math/linearalgebra/GF2mField.cs
deleted file mode 100644
index e8182bf6f..000000000
--- a/crypto/src/pqc/math/linearalgebra/GF2mField.cs
+++ /dev/null
@@ -1,370 +0,0 @@
-using Org.BouncyCastle.Security;
-using System;
-
-namespace Org.BouncyCastle.Pqc.Math.LinearAlgebra
-{
- public class GF2mField
- {
-
- /*
- * degree - degree of the field polynomial - the field polynomial ring -
- * polynomial ring over the finite field GF(2)
- */
-
- private int degree = 0;
-
- private int polynomial;
-
- /**
- * create a finite field GF(2^m)
- *
- * @param degree the degree of the field
- */
- public GF2mField(int degree)
- {
- if (degree >= 32)
- {
- throw new ArgumentException(
- " Error: the degree of field is too large ");
- }
- if (degree < 1)
- {
- throw new ArgumentException(
- " Error: the degree of field is non-positive ");
- }
- this.degree = degree;
- polynomial = PolynomialRingGF2.GetIrreduciblePolynomial(degree);
- }
-
- /**
- * create a finite field GF(2^m) with the fixed field polynomial
- *
- * @param degree the degree of the field
- * @param poly the field polynomial
- */
- public GF2mField(int degree, int poly)
- {
- if (degree != PolynomialRingGF2.Degree(poly))
- {
- throw new ArgumentException(
- " Error: the degree is not correct");
- }
- if (!PolynomialRingGF2.IsIrreducible(poly))
- {
- throw new ArgumentException(
- " Error: given polynomial is reducible");
- }
- this.degree = degree;
- polynomial = poly;
-
- }
-
- public GF2mField(byte[] enc)
- {
- if (enc.Length != 4)
- {
- throw new ArgumentException(
- "byte array is not an encoded finite field");
- }
- polynomial = LittleEndianConversions.OS2IP(enc);
- if (!PolynomialRingGF2.IsIrreducible(polynomial))
- {
- throw new ArgumentException(
- "byte array is not an encoded finite field");
- }
-
- degree = PolynomialRingGF2.Degree(polynomial);
- }
-
- public GF2mField(GF2mField field)
- {
- degree = field.degree;
- polynomial = field.polynomial;
- }
-
- /**
- * return degree of the field
- *
- * @return degree of the field
- */
- public int GetDegree()
- {
- return degree;
- }
-
- /**
- * return the field polynomial
- *
- * @return the field polynomial
- */
- public int GetPolynomial()
- {
- return polynomial;
- }
-
- /**
- * return the encoded form of this field
- *
- * @return the field in byte array form
- */
- public byte[] GetEncoded()
- {
- return LittleEndianConversions.I2OSP(polynomial);
- }
-
- /**
- * Return sum of two elements
- *
- * @param a
- * @param b
- * @return a+b
- */
- public int add(int a, int b)
- {
- return a ^ b;
- }
-
- /**
- * Return product of two elements
- *
- * @param a
- * @param b
- * @return a*b
- */
- public int Mult(int a, int b)
- {
- return PolynomialRingGF2.modMultiply(a, b, polynomial);
- }
-
- /**
- * compute exponentiation a^k
- *
- * @param a a field element a
- * @param k k degree
- * @return a^k
- */
- public int Exp(int a, int k)
- {
- if (k == 0)
- {
- return 1;
- }
- if (a == 0)
- {
- return 0;
- }
- if (a == 1)
- {
- return 1;
- }
- int result = 1;
- if (k < 0)
- {
- a = Inverse(a);
- k = -k;
- }
- while (k != 0)
- {
- if ((k & 1) == 1)
- {
- result = Mult(result, a);
- }
- a = Mult(a, a);
- //k >>>= 1;
- uint kTmp = (uint)k;
- kTmp >>= 1;
- k = (int) kTmp;
- }
- return result;
- }
-
- /**
- * compute the multiplicative inverse of a
- *
- * @param a a field element a
- * @return a<sup>-1</sup>
- */
- public int Inverse(int a)
- {
- int d = (1 << degree) - 2;
-
- return Exp(a, d);
- }
-
- /**
- * compute the square root of an integer
- *
- * @param a a field element a
- * @return a<sup>1/2</sup>
- */
- public int SqRoot(int a)
- {
- for (int i = 1; i < degree; i++)
- {
- a = Mult(a, a);
- }
- return a;
- }
-
- /**
- * create a random field element using PRNG sr
- *
- * @param sr SecureRandom
- * @return a random element
- */
- public int GetRandomElement(SecureRandom sr)
- {
- int result = RandUtils.NextInt(sr, 1 << degree);
- return result;
- }
-
- /**
- * create a random non-zero field element
- *
- * @return a random element
- */
- //public int getRandomNonZeroElement()
- //{
- // return getRandomNonZeroElement(CryptoServicesRegistrar.getSecureRandom());
- //}
-
- /**
- * create a random non-zero field element using PRNG sr
- *
- * @param sr SecureRandom
- * @return a random non-zero element
- */
- public int GetRandomNonZeroElement(SecureRandom sr)
- {
- int controltime = 1 << 20;
- int count = 0;
- int result = RandUtils.NextInt(sr, 1 << degree);
- while ((result == 0) && (count < controltime))
- {
- result = RandUtils.NextInt(sr, 1 << degree);
- count++;
- }
- if (count == controltime)
- {
- result = 1;
- }
- return result;
- }
-
- /**
- * @return true if e is encoded element of this field and false otherwise
- */
- public bool IsElementOfThisField(int e)
- {
- // e is encoded element of this field iff 0<= e < |2^m|
- if (degree == 31)
- {
- return e >= 0;
- }
- return e >= 0 && e < (1 << degree);
- }
-
- /*
- * help method for visual control
- */
- public String ElementToStr(int a)
- {
- String s = "";
- for (int i = 0; i < degree; i++)
- {
- if (((byte)a & 0x01) == 0)
- {
- s = "0" + s;
- }
- else
- {
- s = "1" + s;
- }
- //a >>>= 1;
- uint aTmp = (uint)a;
- aTmp >>= 1;
- a = (int)aTmp;
- }
- return s;
- }
-
- /**
- * checks if given object is equal to this field.
- * <p>
- * The method returns false whenever the given object is not GF2m.
- *
- * @param other object
- * @return true or false
- */
- public bool Equals(Object other)
- {
- if ((other == null) || !(other is GF2mField))
- {
- return false;
- }
-
- GF2mField otherField = (GF2mField)other;
-
- if ((degree == otherField.degree)
- && (polynomial == otherField.polynomial))
- {
- return true;
- }
-
- return false;
- }
-
- public int HashCode()
- {
- return polynomial;
- }
-
- /**
- * Returns a human readable form of this field.
- *
- * @return a human readable form of this field.
- */
- public String ToString()
- {
- String str = "Finite Field GF(2^" + degree + ") = " + "GF(2)[X]/<"
- + PolyToString(polynomial) + "> ";
- return str;
- }
-
- private static String PolyToString(int p)
- {
- String str = "";
- if (p == 0)
- {
- str = "0";
- }
- else
- {
- byte b = (byte)(p & 0x01);
- if (b == 1)
- {
- str = "1";
- }
- //p >>>= 1;
- uint pTmp = (uint)p;
- pTmp >>= 1;
- p = (int)pTmp;
- int i = 1;
- while (p != 0)
- {
- b = (byte)(p & 0x01);
- if (b == 1)
- {
- str = str + "+x^" + i;
- }
- //p >>>= 1;
- pTmp = (uint) p;
- pTmp >>= 1;
- p = (int)pTmp;
- i++;
- }
- }
- return str;
- }
- }
-}
\ No newline at end of file
diff --git a/crypto/src/pqc/math/linearalgebra/GF2mVector.cs b/crypto/src/pqc/math/linearalgebra/GF2mVector.cs
deleted file mode 100644
index f0e44ebe6..000000000
--- a/crypto/src/pqc/math/linearalgebra/GF2mVector.cs
+++ /dev/null
@@ -1,221 +0,0 @@
-using System;
-
-namespace Org.BouncyCastle.Pqc.Math.LinearAlgebra
-{
- /**
- * This class implements vectors over the finite field
- * <tt>GF(2<sup>m</sup>)</tt> for small <tt>m</tt> (i.e.,
- * <tt>1<m<32</tt>). It extends the abstract class {@link Vector}.
- */
-public class GF2mVector : Vector
-{
-
- /**
- * the finite field this vector is defined over
- */
- private GF2mField field;
-
- /**
- * the element array
- */
- private int[] vector;
-
- /**
- * creates the vector over GF(2^m) of given length and with elements from
- * array v (beginning at the first bit)
- *
- * @param field finite field
- * @param v array with elements of vector
- */
- public GF2mVector(GF2mField field, byte[] v)
- {
- this.field = new GF2mField(field);
-
- // decode vector
- int d = 8;
- int count = 1;
- while (field.GetDegree() > d)
- {
- count++;
- d += 8;
- }
-
- if ((v.Length % count) != 0)
- {
- throw new ArgumentException(
- "Byte array is not an encoded vector over the given finite field.");
- }
-
- length = v.Length / count;
- vector = new int[length];
- count = 0;
- for (int i = 0; i < vector.Length; i++)
- {
- for (int j = 0; j < d; j += 8)
- {
- vector[i] |= (v[count++] & 0xff) << j;
- }
- if (!field.IsElementOfThisField(vector[i]))
- {
- throw new ArgumentException(
- "Byte array is not an encoded vector over the given finite field.");
- }
- }
- }
-
- /**
- * Create a new vector over <tt>GF(2<sup>m</sup>)</tt> of the given
- * length and element array.
- *
- * @param field the finite field <tt>GF(2<sup>m</sup>)</tt>
- * @param vector the element array
- */
- public GF2mVector(GF2mField field, int[] vector)
- {
- this.field = field;
- length = vector.Length;
- for (int i = vector.Length - 1; i >= 0; i--)
- {
- if (!field.IsElementOfThisField(vector[i]))
- {
- throw new ArithmeticException(
- "Element array is not specified over the given finite field.");
- }
- }
- this.vector = IntUtils.Clone(vector);
- }
-
- /**
- * Copy constructor.
- *
- * @param other another {@link GF2mVector}
- */
- public GF2mVector(GF2mVector other)
- {
- field = new GF2mField(other.field);
- length = other.length;
- vector = IntUtils.Clone(other.vector);
- }
-
- /**
- * @return the finite field this vector is defined over
- */
- public GF2mField GetField()
- {
- return field;
- }
-
- /**
- * @return int[] form of this vector
- */
- public int[] GetIntArrayForm()
- {
- return IntUtils.Clone(vector);
- }
-
- /**
- * @return a byte array encoding of this vector
- */
- public override byte[] GetEncoded()
- {
- int d = 8;
- int count = 1;
- while (field.GetDegree() > d)
- {
- count++;
- d += 8;
- }
-
- byte[] res = new byte[vector.Length * count];
- count = 0;
- for (int i = 0; i < vector.Length; i++)
- {
- for (int j = 0; j < d; j += 8)
- {
- res[count++] = (byte)(Utils.UnsignedRightBitShiftInt(vector[i], j));
- }
- }
-
- return res;
- }
-
- /**
- * @return whether this is the zero vector (i.e., all elements are zero)
- */
- public override bool IsZero()
- {
- for (int i = vector.Length - 1; i >= 0; i--)
- {
- if (vector[i] != 0)
- {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Add another vector to this vector. Method is not yet implemented.
- *
- * @param addend the other vector
- * @return <tt>this + addend</tt>
- * @throws ArithmeticException if the other vector is not defined over the same field as
- * this vector.
- * <p>
- * TODO: implement this method
- */
- public override Vector Add(Vector addend)
- {
- throw new SystemException("not implemented");
- }
-
- /**
- * Multiply this vector with a permutation.
- *
- * @param p the permutation
- * @return <tt>this*p = p*this</tt>
- */
- public override Vector Multiply(Permutation p)
- {
- int[] pVec = p.GetVector();
- if (length != pVec.Length)
- {
- throw new ArithmeticException(
- "permutation size and vector size mismatch");
- }
-
- int[] result = new int[length];
- for (int i = 0; i < pVec.Length; i++)
- {
- result[i] = vector[pVec[i]];
- }
-
- return new GF2mVector(field, result);
- }
-
- /**
- * Compare this vector with another object.
- *
- * @param other the other object
- * @return the result of the comparison
- */
- public override bool Equals(Object other)
- {
-
- if (!(other is GF2mVector))
- {
- return false;
- }
- GF2mVector otherVec = (GF2mVector)other;
-
- if (!field.Equals(otherVec.field))
- {
- return false;
- }
-
- return IntUtils.Equals(vector, otherVec.vector);
- }
-
-
- }
-}
diff --git a/crypto/src/pqc/math/linearalgebra/IntUtils.cs b/crypto/src/pqc/math/linearalgebra/IntUtils.cs
deleted file mode 100644
index 0a7671df6..000000000
--- a/crypto/src/pqc/math/linearalgebra/IntUtils.cs
+++ /dev/null
@@ -1,159 +0,0 @@
-using Org.BouncyCastle.Utilities;
-using System;
-
-namespace Org.BouncyCastle.Pqc.Math.LinearAlgebra
-{
- public class IntUtils
- {
-
- /**
- * Default constructor (private).
- */
- private IntUtils()
- {
- // empty
- }
-
- /**
- * Compare two int arrays. No null checks are performed.
- *
- * @param left the first int array
- * @param right the second int array
- * @return the result of the comparison
- */
- public static bool Equals(int[] left, int[] right)
- {
- return Arrays.AreEqual(left, right);
- }
-
- /**
- * Return a clone of the given int array. No null checks are performed.
- *
- * @param array the array to clone
- * @return the clone of the given array
- */
- public static int[] Clone(int[] array)
- {
- return Arrays.Clone(array);
- }
-
- /**
- * Fill the given int array with the given value.
- *
- * @param array the array
- * @param value the value
- */
- public static void Fill(int[] array, int value)
- {
- Arrays.Fill(array, value);
- }
-
- /**
- * Sorts this array of integers according to the Quicksort algorithm. After
- * calling this method this array is sorted in ascending order with the
- * smallest integer taking position 0 in the array.
- * <p>
- * This implementation is based on the quicksort algorithm as described in
- * <code>Data Structures In Java</code> by Thomas A. Standish, Chapter 10,
- * ISBN 0-201-30564-X.
- *
- * @param source the array of integers that needs to be sorted.
- */
- public static void Quicksort(int[] source)
- {
- Quicksort(source, 0, source.Length - 1);
- }
-
- /**
- * Sort a subarray of a source array. The subarray is specified by its start
- * and end index.
- *
- * @param source the int array to be sorted
- * @param left the start index of the subarray
- * @param right the end index of the subarray
- */
- public static void Quicksort(int[] source, int left, int right)
- {
- if (right > left)
- {
- int index = Partition(source, left, right, right);
- Quicksort(source, left, index - 1);
- Quicksort(source, index + 1, right);
- }
- }
-
- /**
- * Split a subarray of a source array into two partitions. The left
- * partition contains elements that have value less than or equal to the
- * pivot element, the right partition contains the elements that have larger
- * value.
- *
- * @param source the int array whose subarray will be splitted
- * @param left the start position of the subarray
- * @param right the end position of the subarray
- * @param pivotIndex the index of the pivot element inside the array
- * @return the new index of the pivot element inside the array
- */
- private static int Partition(int[] source, int left, int right,
- int pivotIndex)
- {
-
- int pivot = source[pivotIndex];
- source[pivotIndex] = source[right];
- source[right] = pivot;
-
- int index = left;
- int tmp = 0;
- for (int i = left; i < right; i++)
- {
- if (source[i] <= pivot)
- {
- tmp = source[index];
- source[index] = source[i];
- source[i] = tmp;
- index++;
- }
- }
-
- tmp = source[index];
- source[index] = source[right];
- source[right] = tmp;
-
- return index;
- }
-
- /**
- * Generates a subarray of a given int array.
- *
- * @param input -
- * the input int array
- * @param start -
- * the start index
- * @param end -
- * the end index
- * @return a subarray of <tt>input</tt>, ranging from <tt>start</tt> to
- * <tt>end</tt>
- */
- public static int[] SubArray( int[] input, int start,
- int end)
- {
- int[] result = new int[end - start];
- Array.Copy(input, start, result, 0, end - start);
- return result;
- }
-
- /**
- * @param input an int array
- * @return a human readable form of the given int array
- */
- public static String ToString(int[] input)
- {
- String result = "";
- for (int i = 0; i < input.Length; i++)
- {
- result += input[i] + " ";
- }
- return result;
- }
- }
-}
diff --git a/crypto/src/pqc/math/linearalgebra/LittleEndianConversions.cs b/crypto/src/pqc/math/linearalgebra/LittleEndianConversions.cs
deleted file mode 100644
index 5b3215070..000000000
--- a/crypto/src/pqc/math/linearalgebra/LittleEndianConversions.cs
+++ /dev/null
@@ -1,195 +0,0 @@
-
-using Org.BouncyCastle.Crypto.Utilities;
-
-namespace Org.BouncyCastle.Pqc.Math.LinearAlgebra
-{
- /**
- * This is a utility class containing data type conversions using little-endian
- * byte order.
- *
- */
- class LittleEndianConversions
- {
- /**
- * Default constructor (private).
- */
- private LittleEndianConversions()
- {
- // empty
- }
-
- /**
- * Convert an octet string of length 4 to an integer. No length checking is
- * performed.
- *
- * @param input the byte array holding the octet string
- * @return an integer representing the octet string <tt>input</tt>
- * @throws ArithmeticException if the length of the given octet string is larger than 4.
- */
- public static int OS2IP(byte[] input)
- {
- return (int)Pack.LE_To_UInt32(input);
- }
-
- /**
- * Convert an byte array of length 4 beginning at <tt>offset</tt> into an
- * integer.
- *
- * @param input the byte array
- * @param inOff the offset into the byte array
- * @return the resulting integer
- */
- public static int OS2IP(byte[] input, int inOff)
- {
- return (int)Pack.LE_To_UInt32(input, inOff);
- }
-
- /**
- * Convert a byte array of the given length beginning at <tt>offset</tt>
- * into an integer.
- *
- * @param input the byte array
- * @param inOff the offset into the byte array
- * @param inLen the length of the encoding
- * @return the resulting integer
- */
- public static int OS2IP(byte[] input, int inOff, int inLen)
- {
- int result = 0;
- for (int i = inLen - 1; i >= 0; i--)
- {
- result |= (input[inOff + i] & 0xff) << (8 * i);
- }
- return result;
- }
-
- /**
- * Convert a byte array of length 8 beginning at <tt>inOff</tt> into a
- * long integer.
- *
- * @param input the byte array
- * @param inOff the offset into the byte array
- * @return the resulting long integer
- */
- public static long OS2LIP(byte[] input, int inOff)
- {
- return (long)Pack.LE_To_UInt64(input, inOff);
- }
-
- /**
- * Convert an integer to an octet string of length 4.
- *
- * @param x the integer to convert
- * @return the converted integer
- */
- public static byte[] I2OSP(int x)
- {
- return Pack.UInt32_To_LE((uint)x);
- }
-
- /**
- * Convert an integer into a byte array beginning at the specified offset.
- *
- * @param value the integer to convert
- * @param output the byte array to hold the result
- * @param outOff the integer offset into the byte array
- */
- public static void I2OSP(int value, byte[] output, int outOff)
- {
- Pack.UInt32_To_LE((uint)value, output, outOff);
- }
-
- /**
- * Convert an integer to a byte array beginning at the specified offset. No
- * length checking is performed (i.e., if the integer cannot be encoded with
- * <tt>length</tt> octets, it is truncated).
- *
- * @param value the integer to convert
- * @param output the byte array to hold the result
- * @param outOff the integer offset into the byte array
- * @param outLen the length of the encoding
- */
- public static void I2OSP(int value, byte[] output, int outOff, int outLen)
- {
- uint valueTmp = (uint)value;
- for (int i = outLen - 1; i >= 0; i--)
- {
- output[outOff + i] = (byte)(valueTmp >> (8 * i));
- }
- }
-
- /**
- * Convert an integer to a byte array of length 8.
- *
- * @param input the integer to convert
- * @return the converted integer
- */
- public static byte[] I2OSP(long input)
- {
- return Pack.UInt64_To_LE((ulong)input);
- }
-
- /**
- * Convert an integer to a byte array of length 8.
- *
- * @param input the integer to convert
- * @param output byte array holding the output
- * @param outOff offset in output array where the result is stored
- */
- public static void I2OSP(long input, byte[] output, int outOff)
- {
- Pack.UInt64_To_LE((ulong)input, output, outOff);
- }
-
- /**
- * Convert an int array to a byte array of the specified length. No length
- * checking is performed (i.e., if the last integer cannot be encoded with
- * <tt>length % 4</tt> octets, it is truncated).
- *
- * @param input the int array
- * @param outLen the length of the converted array
- * @return the converted array
- */
- public static byte[] ToByteArray(int[] input, int outLen)
- {
- int intLen = input.Length;
- byte[] result = new byte[outLen];
- int index = 0;
- for (int i = 0; i <= intLen - 2; i++, index += 4)
- {
- I2OSP(input[i], result, index);
- }
- I2OSP(input[intLen - 1], result, index, outLen - index);
- return result;
- }
-
- /**
- * Convert a byte array to an int array.
- *
- * @param input the byte array
- * @return the converted array
- */
- public static int[] ToIntArray(byte[] input)
- {
- int intLen = (input.Length + 3) / 4;
- int lastLen = input.Length & 0x03;
- int[] result = new int[intLen];
-
- int index = 0;
- for (int i = 0; i <= intLen - 2; i++, index += 4)
- {
- result[i] = OS2IP(input, index);
- }
- if (lastLen != 0)
- {
- result[intLen - 1] = OS2IP(input, index, lastLen);
- }
- else
- {
- result[intLen - 1] = OS2IP(input, index);
- }
-
- return result;
- }
- }
-}
diff --git a/crypto/src/pqc/math/linearalgebra/Permutation.cs b/crypto/src/pqc/math/linearalgebra/Permutation.cs
deleted file mode 100644
index 0d36958c9..000000000
--- a/crypto/src/pqc/math/linearalgebra/Permutation.cs
+++ /dev/null
@@ -1,192 +0,0 @@
-using Org.BouncyCastle.Security;
-using System;
-
-namespace Org.BouncyCastle.Pqc.Math.LinearAlgebra
-{
- /**
- * This class implements permutations of the set {0,1,...,n-1} for some given n
- * > 0, i.e., ordered sequences containing each number <tt>m</tt> (<tt>0 <=
- * m < n</tt>)
- * once and only once.
- */
- public class Permutation
- {
-
- /**
- * perm holds the elements of the permutation vector, i.e. <tt>[perm(0),
- * perm(1), ..., perm(n-1)]</tt>
- */
- private int[] perm;
-
- /**
- * Create the identity permutation of the given size.
- *
- * @param n the size of the permutation
- */
- public Permutation(int n)
- {
- if (n <= 0)
- {
- throw new ArgumentException("invalid length");
- }
-
- perm = new int[n];
- for (int i = n - 1; i >= 0; i--)
- {
- perm[i] = i;
- }
- }
-
- /**
- * Create a permutation using the given permutation vector.
- *
- * @param perm the permutation vector
- */
- public Permutation(int[] perm)
- {
- if (!IsPermutation(perm))
- {
- throw new ArgumentException(
- "array is not a permutation vector");
- }
-
- this.perm = IntUtils.Clone(perm);
- }
-
- /**
- * Create a random permutation of the given size.
- *
- * @param n the size of the permutation
- * @param sr the source of randomness
- */
- public Permutation(int n, SecureRandom sr)
- {
- if (n <= 0)
- {
- throw new ArgumentException("invalid length");
- }
-
- perm = new int[n];
-
- int[] help = new int[n];
- for (int i = 0; i < n; i++)
- {
- help[i] = i;
- }
-
- int k = n;
- for (int j = 0; j < n; j++)
- {
- int i = RandUtils.NextInt(sr, k);
- k--;
- perm[j] = help[i];
- help[i] = help[k];
- }
- }
-
-
- /**
- * @return the permutation vector <tt>(perm(0),perm(1),...,perm(n-1))</tt>
- */
- public int[] GetVector()
- {
- return IntUtils.Clone(perm);
- }
-
- /**
- * Compute the inverse permutation <tt>P<sup>-1</sup></tt>.
- *
- * @return <tt>this<sup>-1</sup></tt>
- */
- public Permutation ComputeInverse()
- {
- Permutation result = new Permutation(perm.Length);
- for (int i = perm.Length - 1; i >= 0; i--)
- {
- result.perm[perm[i]] = i;
- }
- return result;
- }
-
- /**
- * Compute the product of this permutation and another permutation.
- *
- * @param p the other permutation
- * @return <tt>this * p</tt>
- */
- public Permutation RightMultiply(Permutation p)
- {
- if (p.perm.Length != perm.Length)
- {
- throw new ArgumentException("length mismatch");
- }
- Permutation result = new Permutation(perm.Length);
- for (int i = perm.Length - 1; i >= 0; i--)
- {
- result.perm[i] = perm[p.perm[i]];
- }
- return result;
- }
-
- /**
- * checks if given object is equal to this permutation.
- * <p>
- * The method returns false whenever the given object is not permutation.
- *
- * @param other -
- * permutation
- * @return true or false
- */
- public bool equals(Object other)
- {
-
- if (!(other is Permutation))
- {
- return false;
- }
- Permutation otherPerm = (Permutation)other;
-
- return IntUtils.Equals(perm, otherPerm.perm);
- }
-
- /**
- * @return a human readable form of the permutation
- */
- public String ToString()
- {
- String result = "[" + perm[0];
- for (int i = 1; i < perm.Length; i++)
- {
- result += ", " + perm[i];
- }
- result += "]";
- return result;
- }
-
- /**
- * Check that the given array corresponds to a permutation of the set
- * <tt>{0, 1, ..., n-1}</tt>.
- *
- * @param perm permutation vector
- * @return true if perm represents an n-permutation and false otherwise
- */
- private bool IsPermutation(int[] perm)
- {
- int n = perm.Length;
- bool[] onlyOnce = new bool[n];
-
- for (int i = 0; i < n; i++)
- {
- if ((perm[i] < 0) || (perm[i] >= n) || onlyOnce[perm[i]])
- {
- return false;
- }
- onlyOnce[perm[i]] = true;
- }
-
- return true;
- }
-
- }
-
-}
diff --git a/crypto/src/pqc/math/linearalgebra/PolynomialGF2mSmallM.cs b/crypto/src/pqc/math/linearalgebra/PolynomialGF2mSmallM.cs
deleted file mode 100644
index 9dca71bee..000000000
--- a/crypto/src/pqc/math/linearalgebra/PolynomialGF2mSmallM.cs
+++ /dev/null
@@ -1,1266 +0,0 @@
-using Org.BouncyCastle.Security;
-using Org.BouncyCastle.Utilities;
-using System;
-
-namespace Org.BouncyCastle.Pqc.Math.LinearAlgebra
-{
- public class PolynomialGF2mSmallM
- {
-
- /**
- * the finite field GF(2^m)
- */
- private GF2mField field;
-
- /**
- * the degree of this polynomial
- */
- private int degree;
-
- /**
- * For the polynomial representation the map f: R->Z*,
- * <tt>poly(X) -> [coef_0, coef_1, ...]</tt> is used, where
- * <tt>coef_i</tt> is the <tt>i</tt>th coefficient of the polynomial
- * represented as int (see {@link GF2mField}). The polynomials are stored
- * as int arrays.
- */
- private int[] coefficients;
-
- /*
- * some types of polynomials
- */
-
- /**
- * Constant used for polynomial construction (see constructor
- * {@link #PolynomialGF2mSmallM(GF2mField, int, char, SecureRandom)}).
- */
- public const char RANDOM_IRREDUCIBLE_POLYNOMIAL = 'I';
-
- /**
- * Construct the zero polynomial over the finite field GF(2^m).
- *
- * @param field the finite field GF(2^m)
- */
- public PolynomialGF2mSmallM(GF2mField field)
- {
- this.field = field;
- degree = -1;
- coefficients = new int[1];
- }
-
- /**
- * Construct a polynomial over the finite field GF(2^m).
- *
- * @param field the finite field GF(2^m)
- * @param deg degree of polynomial
- * @param typeOfPolynomial type of polynomial
- * @param sr PRNG
- */
- public PolynomialGF2mSmallM(GF2mField field, int deg,
- char typeOfPolynomial, SecureRandom sr)
- {
- this.field = field;
-
- switch (typeOfPolynomial)
- {
- case PolynomialGF2mSmallM.RANDOM_IRREDUCIBLE_POLYNOMIAL:
- coefficients = CreateRandomIrreduciblePolynomial(deg, sr);
- break;
- default:
- throw new ArgumentException(" Error: type "
- + typeOfPolynomial
- + " is not defined for GF2smallmPolynomial");
- }
- ComputeDegree();
- }
-
- /**
- * Create an irreducible polynomial with the given degree over the field
- * <tt>GF(2^m)</tt>.
- *
- * @param deg polynomial degree
- * @param sr source of randomness
- * @return the generated irreducible polynomial
- */
- private int[] CreateRandomIrreduciblePolynomial(int deg, SecureRandom sr)
- {
- int[] resCoeff = new int[deg + 1];
- resCoeff[deg] = 1;
- resCoeff[0] = field.GetRandomNonZeroElement(sr);
- for (int i = 1; i < deg; i++)
- {
- resCoeff[i] = field.GetRandomElement(sr);
- }
- while (!IsIrreducible(resCoeff))
- {
- int n = RandUtils.NextInt(sr, deg);
- if (n == 0)
- {
- resCoeff[0] = field.GetRandomNonZeroElement(sr);
- }
- else
- {
- resCoeff[n] = field.GetRandomElement(sr);
- }
- }
- return resCoeff;
- }
-
- /**
- * Construct a monomial of the given degree over the finite field GF(2^m).
- *
- * @param field the finite field GF(2^m)
- * @param degree the degree of the monomial
- */
- public PolynomialGF2mSmallM(GF2mField field, int degree)
- {
- this.field = field;
- this.degree = degree;
- coefficients = new int[degree + 1];
- coefficients[degree] = 1;
- }
-
- /**
- * Construct the polynomial over the given finite field GF(2^m) from the
- * given coefficient vector.
- *
- * @param field finite field GF2m
- * @param coeffs the coefficient vector
- */
- public PolynomialGF2mSmallM(GF2mField field, int[] coeffs)
- {
- this.field = field;
- coefficients = NormalForm(coeffs);
- ComputeDegree();
- }
-
- /**
- * Create a polynomial over the finite field GF(2^m).
- *
- * @param field the finite field GF(2^m)
- * @param enc byte[] polynomial in byte array form
- */
- public PolynomialGF2mSmallM(GF2mField field, byte[] enc)
- {
- this.field = field;
-
- // decodes polynomial
- int d = 8;
- int count = 1;
- while (field.GetDegree() > d)
- {
- count++;
- d += 8;
- }
-
- if ((enc.Length % count) != 0)
- {
- throw new ArgumentException(
- " Error: byte array is not encoded polynomial over given finite field GF2m");
- }
-
- coefficients = new int[enc.Length / count];
- count = 0;
- for (int i = 0; i < coefficients.Length; i++)
- {
- for (int j = 0; j < d; j += 8)
- {
- coefficients[i] ^= (enc[count++] & 0x000000ff) << j;
- }
- if (!this.field.IsElementOfThisField(coefficients[i]))
- {
- throw new ArgumentException(
- " Error: byte array is not encoded polynomial over given finite field GF2m");
- }
- }
- // if HC = 0 for non-zero polynomial, returns error
- if ((coefficients.Length != 1)
- && (coefficients[coefficients.Length - 1] == 0))
- {
- throw new ArgumentException(
- " Error: byte array is not encoded polynomial over given finite field GF2m");
- }
- ComputeDegree();
- }
-
- /**
- * Copy constructor.
- *
- * @param other another {@link PolynomialGF2mSmallM}
- */
- public PolynomialGF2mSmallM(PolynomialGF2mSmallM other)
- {
- // field needs not to be cloned since it is immutable
- field = other.field;
- degree = other.degree;
- coefficients = IntUtils.Clone(other.coefficients);
- }
-
- /**
- * Create a polynomial over the finite field GF(2^m) out of the given
- * coefficient vector. The finite field is also obtained from the
- * {@link GF2mVector}.
- *
- * @param vect the coefficient vector
- */
- public PolynomialGF2mSmallM(GF2mVector vect)
- {
- new PolynomialGF2mSmallM(vect.GetField(), vect.GetIntArrayForm());
- }
-
- /*
- * ------------------------
- */
-
- /**
- * Return the degree of this polynomial
- *
- * @return int degree of this polynomial if this is zero polynomial return
- * -1
- */
- public int GetDegree()
- {
- int d = coefficients.Length - 1;
- if (coefficients[d] == 0)
- {
- return -1;
- }
- return d;
- }
-
- /**
- * @return the head coefficient of this polynomial
- */
- public int GetHeadCoefficient()
- {
- if (degree == -1)
- {
- return 0;
- }
- return coefficients[degree];
- }
-
- /**
- * Return the head coefficient of a polynomial.
- *
- * @param a the polynomial
- * @return the head coefficient of <tt>a</tt>
- */
- private static int HeadCoefficient(int[] a)
- {
- int degree = ComputeDegree(a);
- if (degree == -1)
- {
- return 0;
- }
- return a[degree];
- }
-
- /**
- * Return the coefficient with the given index.
- *
- * @param index the index
- * @return the coefficient with the given index
- */
- public int GetCoefficient(int index)
- {
- if ((index < 0) || (index > degree))
- {
- return 0;
- }
- return coefficients[index];
- }
-
- /**
- * Returns encoded polynomial, i.e., this polynomial in byte array form
- *
- * @return the encoded polynomial
- */
- public byte[] GetEncoded()
- {
- int d = 8;
- int count = 1;
- while (field.GetDegree() > d)
- {
- count++;
- d += 8;
- }
-
- byte[] res = new byte[coefficients.Length * count];
- count = 0;
- for (int i = 0; i < coefficients.Length; i++)
- {
- for (int j = 0; j < d; j += 8)
- {
- res[count++] = (byte)(Utils.UnsignedRightBitShiftInt(coefficients[i], j));
- }
- }
-
- return res;
- }
-
- /**
- * Evaluate this polynomial <tt>p</tt> at a value <tt>e</tt> (in
- * <tt>GF(2^m)</tt>) with the Horner scheme.
- *
- * @param e the element of the finite field GF(2^m)
- * @return <tt>this(e)</tt>
- */
- public int evaluateAt(int e)
- {
- int result = coefficients[degree];
- for (int i = degree - 1; i >= 0; i--)
- {
- result = field.Mult(result, e) ^ coefficients[i];
- }
- return result;
- }
-
- /**
- * Compute the sum of this polynomial and the given polynomial.
- *
- * @param addend the addend
- * @return <tt>this + a</tt> (newly created)
- */
- public PolynomialGF2mSmallM add(PolynomialGF2mSmallM addend)
- {
- int[] resultCoeff = Add(coefficients, addend.coefficients);
- return new PolynomialGF2mSmallM(field, resultCoeff);
- }
-
- /**
- * Add the given polynomial to this polynomial (overwrite this).
- *
- * @param addend the addend
- */
- public void AddToThis(PolynomialGF2mSmallM addend)
- {
- coefficients = Add(coefficients, addend.coefficients);
- ComputeDegree();
- }
-
- /**
- * Compute the sum of two polynomials a and b over the finite field
- * <tt>GF(2^m)</tt>.
- *
- * @param a the first polynomial
- * @param b the second polynomial
- * @return a + b
- */
- private int[] Add(int[] a, int[] b)
- {
- int[] result, addend;
- if (a.Length < b.Length)
- {
- result = new int[b.Length];
- Array.Copy(b, 0, result, 0, b.Length);
- addend = a;
- }
- else
- {
- result = new int[a.Length];
- Array.Copy(a, 0, result, 0, a.Length);
- addend = b;
- }
-
- for (int i = addend.Length - 1; i >= 0; i--)
- {
- result[i] = field.add(result[i], addend[i]);
- }
-
- return result;
- }
-
- /**
- * Compute the sum of this polynomial and the monomial of the given degree.
- *
- * @param degree the degree of the monomial
- * @return <tt>this + X^k</tt>
- */
- public PolynomialGF2mSmallM AddMonomial(int degree)
- {
- int[] monomial = new int[degree + 1];
- monomial[degree] = 1;
- int[] resultCoeff = Add(coefficients, monomial);
- return new PolynomialGF2mSmallM(field, resultCoeff);
- }
-
- /**
- * Compute the product of this polynomial with an element from GF(2^m).
- *
- * @param element an element of the finite field GF(2^m)
- * @return <tt>this * element</tt> (newly created)
- * @throws ArithmeticException if <tt>element</tt> is not an element of the finite
- * field this polynomial is defined over.
- */
- public PolynomialGF2mSmallM MultWithElement(int element)
- {
- if (!field.IsElementOfThisField(element))
- {
- throw new ArithmeticException(
- "Not an element of the finite field this polynomial is defined over.");
- }
- int[] resultCoeff = MultWithElement(coefficients, element);
- return new PolynomialGF2mSmallM(field, resultCoeff);
- }
-
- /**
- * Multiply this polynomial with an element from GF(2^m).
- *
- * @param element an element of the finite field GF(2^m)
- * @throws ArithmeticException if <tt>element</tt> is not an element of the finite
- * field this polynomial is defined over.
- */
- public void MultThisWithElement(int element)
- {
- if (!field.IsElementOfThisField(element))
- {
- throw new ArithmeticException(
- "Not an element of the finite field this polynomial is defined over.");
- }
- coefficients = MultWithElement(coefficients, element);
- ComputeDegree();
- }
-
- /**
- * Compute the product of a polynomial a with an element from the finite
- * field <tt>GF(2^m)</tt>.
- *
- * @param a the polynomial
- * @param element an element of the finite field GF(2^m)
- * @return <tt>a * element</tt>
- */
- private int[] MultWithElement(int[] a, int element)
- {
- int degree = ComputeDegree(a);
- if (degree == -1 || element == 0)
- {
- return new int[1];
- }
-
- if (element == 1)
- {
- return IntUtils.Clone(a);
- }
-
- int[] result = new int[degree + 1];
- for (int i = degree; i >= 0; i--)
- {
- result[i] = field.Mult(a[i], element);
- }
-
- return result;
- }
-
- /**
- * Compute the product of this polynomial with a monomial X^k.
- *
- * @param k the degree of the monomial
- * @return <tt>this * X^k</tt>
- */
- public PolynomialGF2mSmallM MultWithMonomial(int k)
- {
- int[] resultCoeff = MultWithMonomial(coefficients, k);
- return new PolynomialGF2mSmallM(field, resultCoeff);
- }
-
- /**
- * Compute the product of a polynomial with a monomial X^k.
- *
- * @param a the polynomial
- * @param k the degree of the monomial
- * @return <tt>a * X^k</tt>
- */
- private static int[] MultWithMonomial(int[] a, int k)
- {
- int d = ComputeDegree(a);
- if (d == -1)
- {
- return new int[1];
- }
- int[] result = new int[d + k + 1];
- Array.Copy(a, 0, result, k, d + 1);
- return result;
- }
-
- /**
- * Divide this polynomial by the given polynomial.
- *
- * @param f a polynomial
- * @return polynomial pair = {q,r} where this = q*f+r and deg(r) <
- * deg(f);
- */
- public PolynomialGF2mSmallM[] Div(PolynomialGF2mSmallM f)
- {
- int[][] resultCoeffs = Div(coefficients, f.coefficients);
- return new PolynomialGF2mSmallM[]{
- new PolynomialGF2mSmallM(field, resultCoeffs[0]),
- new PolynomialGF2mSmallM(field, resultCoeffs[1])};
- }
-
- /**
- * Compute the result of the division of two polynomials over the field
- * <tt>GF(2^m)</tt>.
- *
- * @param a the first polynomial
- * @param f the second polynomial
- * @return int[][] {q,r}, where a = q*f+r and deg(r) < deg(f);
- */
- private int[][] Div(int[] a, int[] f)
- {
- int df = ComputeDegree(f);
- int da = ComputeDegree(a) + 1;
- if (df == -1)
- {
- throw new ArithmeticException("Division by zero.");
- }
- int[][] result = new int[2][];
- result[0] = new int[1];
- result[1] = new int[da];
- int hc = HeadCoefficient(f);
- hc = field.Inverse(hc);
- result[0][0] = 0;
- Array.Copy(a, 0, result[1], 0, result[1].Length);
- while (df <= ComputeDegree(result[1]))
- {
- int[] q;
- int[] coeff = new int[1];
- coeff[0] = field.Mult(HeadCoefficient(result[1]), hc);
- q = MultWithElement(f, coeff[0]);
- int n = ComputeDegree(result[1]) - df;
- q = MultWithMonomial(q, n);
- coeff = MultWithMonomial(coeff, n);
- result[0] = Add(coeff, result[0]);
- result[1] = Add(q, result[1]);
- }
- return result;
- }
-
- /**
- * Return the greatest common divisor of this and a polynomial <i>f</i>
- *
- * @param f polynomial
- * @return GCD(this, f)
- */
- public PolynomialGF2mSmallM Gcd(PolynomialGF2mSmallM f)
- {
- int[] resultCoeff = Gcd(coefficients, f.coefficients);
- return new PolynomialGF2mSmallM(field, resultCoeff);
- }
-
- /**
- * Return the greatest common divisor of two polynomials over the field
- * <tt>GF(2^m)</tt>.
- *
- * @param f the first polynomial
- * @param g the second polynomial
- * @return <tt>gcd(f, g)</tt>
- */
- private int[] Gcd(int[] f, int[] g)
- {
- int[] a = f;
- int[] b = g;
- if (ComputeDegree(a) == -1)
- {
- return b;
- }
- while (ComputeDegree(b) != -1)
- {
- int[] c = Mod(a, b);
- a = new int[b.Length];
- Array.Copy(b, 0, a, 0, a.Length);
- b = new int[c.Length];
- Array.Copy(c, 0, b, 0, b.Length);
- }
- int coeff = field.Inverse(HeadCoefficient(a));
- return MultWithElement(a, coeff);
- }
-
- /**
- * Compute the product of this polynomial and the given factor using a
- * Karatzuba like scheme.
- *
- * @param factor the polynomial
- * @return <tt>this * factor</tt>
- */
- public PolynomialGF2mSmallM Multiply(PolynomialGF2mSmallM factor)
- {
- int[] resultCoeff = Multiply(coefficients, factor.coefficients);
- return new PolynomialGF2mSmallM(field, resultCoeff);
- }
-
- /**
- * Compute the product of two polynomials over the field <tt>GF(2^m)</tt>
- * using a Karatzuba like multiplication.
- *
- * @param a the first polynomial
- * @param b the second polynomial
- * @return a * b
- */
- private int[] Multiply(int[] a, int[] b)
- {
- int[] mult1, mult2;
- if (ComputeDegree(a) < ComputeDegree(b))
- {
- mult1 = b;
- mult2 = a;
- }
- else
- {
- mult1 = a;
- mult2 = b;
- }
-
- mult1 = NormalForm(mult1);
- mult2 = NormalForm(mult2);
-
- if (mult2.Length == 1)
- {
- return MultWithElement(mult1, mult2[0]);
- }
-
- int d1 = mult1.Length;
- int d2 = mult2.Length;
- int[] result = new int[d1 + d2 - 1];
-
- if (d2 != d1)
- {
- int[] res1 = new int[d2];
- int[] res2 = new int[d1 - d2];
- Array.Copy(mult1, 0, res1, 0, res1.Length);
- Array.Copy(mult1, d2, res2, 0, res2.Length);
- res1 = Multiply(res1, mult2);
- res2 = Multiply(res2, mult2);
- res2 = MultWithMonomial(res2, d2);
- result = Add(res1, res2);
- }
- else
- {
- d2 = Utils.UnsignedRightBitShiftInt(d1 + 1, 1);
- int d = d1 - d2;
- int[] firstPartMult1 = new int[d2];
- int[] firstPartMult2 = new int[d2];
- int[] secondPartMult1 = new int[d];
- int[] secondPartMult2 = new int[d];
- Array.Copy(mult1, 0, firstPartMult1, 0,
- firstPartMult1.Length);
- Array.Copy(mult1, d2, secondPartMult1, 0,
- secondPartMult1.Length);
- Array.Copy(mult2, 0, firstPartMult2, 0,
- firstPartMult2.Length);
- Array.Copy(mult2, d2, secondPartMult2, 0,
- secondPartMult2.Length);
- int[] helpPoly1 = Add(firstPartMult1, secondPartMult1);
- int[] helpPoly2 = Add(firstPartMult2, secondPartMult2);
- int[] res1 = Multiply(firstPartMult1, firstPartMult2);
- int[] res2 = Multiply(helpPoly1, helpPoly2);
- int[] res3 = Multiply(secondPartMult1, secondPartMult2);
- res2 = Add(res2, res1);
- res2 = Add(res2, res3);
- res3 = MultWithMonomial(res3, d2);
- result = Add(res2, res3);
- result = MultWithMonomial(result, d2);
- result = Add(result, res1);
- }
-
- return result;
- }
-
- /*
- * ---------------- PART II ----------------
- *
- */
-
- /**
- * Check a polynomial for irreducibility over the field <tt>GF(2^m)</tt>.
- *
- * @param a the polynomial to check
- * @return true if a is irreducible, false otherwise
- */
- private bool IsIrreducible(int[] a)
- {
- if (a[0] == 0)
- {
- return false;
- }
- int d = ComputeDegree(a) >> 1;
- int[] u = { 0, 1 };
- int[] Y = { 0, 1 };
- int fieldDegree = field.GetDegree();
- for (int i = 0; i < d; i++)
- {
- for (int j = fieldDegree - 1; j >= 0; j--)
- {
- u = ModMultiply(u, u, a);
- }
- u = NormalForm(u);
- int[] g = Gcd(Add(u, Y), a);
- if (ComputeDegree(g) != 0)
- {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Reduce this polynomial modulo another polynomial.
- *
- * @param f the reduction polynomial
- * @return <tt>this mod f</tt>
- */
- public PolynomialGF2mSmallM Mod(PolynomialGF2mSmallM f)
- {
- int[] resultCoeff = Mod(coefficients, f.coefficients);
- return new PolynomialGF2mSmallM(field, resultCoeff);
- }
-
- /**
- * Reduce a polynomial modulo another polynomial.
- *
- * @param a the polynomial
- * @param f the reduction polynomial
- * @return <tt>a mod f</tt>
- */
- private int[] Mod(int[] a, int[] f)
- {
- int df = ComputeDegree(f);
- if (df == -1)
- {
- throw new ArithmeticException("Division by zero");
- }
- int[] result = new int[a.Length];
- int hc = HeadCoefficient(f);
- hc = field.Inverse(hc);
- Array.Copy(a, 0, result, 0, result.Length);
- while (df <= ComputeDegree(result))
- {
- int[] q;
- int coeff = field.Mult(HeadCoefficient(result), hc);
- q = MultWithMonomial(f, ComputeDegree(result) - df);
- q = MultWithElement(q, coeff);
- result = Add(q, result);
- }
- return result;
- }
-
- /**
- * Compute the product of this polynomial and another polynomial modulo a
- * third polynomial.
- *
- * @param a another polynomial
- * @param b the reduction polynomial
- * @return <tt>this * a mod b</tt>
- */
- public PolynomialGF2mSmallM ModMultiply(PolynomialGF2mSmallM a,
- PolynomialGF2mSmallM b)
- {
- int[] resultCoeff = ModMultiply(coefficients, a.coefficients,
- b.coefficients);
- return new PolynomialGF2mSmallM(field, resultCoeff);
- }
-
-
-
- /**
- * Square this polynomial using a squaring matrix.
- *
- * @param matrix the squaring matrix
- * @return <tt>this^2</tt> modulo the reduction polynomial implicitly
- * given via the squaring matrix
- */
- public PolynomialGF2mSmallM ModSquareMatrix(PolynomialGF2mSmallM[] matrix)
- {
-
- int length = matrix.Length;
-
- int[] resultCoeff = new int[length];
- int[] thisSquare = new int[length];
-
- // square each entry of this polynomial
- for (int i = 0; i < coefficients.Length; i++)
- {
- thisSquare[i] = field.Mult(coefficients[i], coefficients[i]);
- }
-
- // do matrix-vector multiplication
- for (int i = 0; i < length; i++)
- {
- // compute scalar product of i-th row and coefficient vector
- for (int j = 0; j < length; j++)
- {
- if (i >= matrix[j].coefficients.Length)
- {
- continue;
- }
- int scalarTerm = field.Mult(matrix[j].coefficients[i],
- thisSquare[j]);
- resultCoeff[i] = field.add(resultCoeff[i], scalarTerm);
- }
- }
-
- return new PolynomialGF2mSmallM(field, resultCoeff);
- }
-
- /**
- * Compute the product of two polynomials modulo a third polynomial over the
- * finite field <tt>GF(2^m)</tt>.
- *
- * @param a the first polynomial
- * @param b the second polynomial
- * @param g the reduction polynomial
- * @return <tt>a * b mod g</tt>
- */
- private int[] ModMultiply(int[] a, int[] b, int[] g)
- {
- return Mod(Multiply(a, b), g);
- }
-
- /**
- * Compute the square root of this polynomial modulo the given polynomial.
- *
- * @param a the reduction polynomial
- * @return <tt>this^(1/2) mod a</tt>
- */
- public PolynomialGF2mSmallM ModSquareRoot(PolynomialGF2mSmallM a)
- {
- int[] resultCoeff = IntUtils.Clone(coefficients);
- int[] help = ModMultiply(resultCoeff, resultCoeff, a.coefficients);
- while (!IsEqual(help, coefficients))
- {
- resultCoeff = NormalForm(help);
- help = ModMultiply(resultCoeff, resultCoeff, a.coefficients);
- }
-
- return new PolynomialGF2mSmallM(field, resultCoeff);
- }
-
- /**
- * Compute the square root of this polynomial using a square root matrix.
- *
- * @param matrix the matrix for computing square roots in
- * <tt>(GF(2^m))^t</tt> the polynomial ring defining the
- * square root matrix
- * @return <tt>this^(1/2)</tt> modulo the reduction polynomial implicitly
- * given via the square root matrix
- */
- public PolynomialGF2mSmallM ModSquareRootMatrix(
- PolynomialGF2mSmallM[] matrix)
- {
-
- int length = matrix.Length;
-
- int[] resultCoeff = new int[length];
-
- // do matrix multiplication
- for (int i = 0; i < length; i++)
- {
- // compute scalar product of i-th row and j-th column
- for (int j = 0; j < length; j++)
- {
- if (i >= matrix[j].coefficients.Length)
- {
- continue;
- }
- if (j < coefficients.Length)
- {
- int scalarTerm = field.Mult(matrix[j].coefficients[i],
- coefficients[j]);
- resultCoeff[i] = field.add(resultCoeff[i], scalarTerm);
- }
- }
- }
-
- // compute the square root of each entry of the result coefficients
- for (int i = 0; i < length; i++)
- {
- resultCoeff[i] = field.SqRoot(resultCoeff[i]);
- }
-
- return new PolynomialGF2mSmallM(field, resultCoeff);
- }
-
- /**
- * Compute the result of the division of this polynomial by another
- * polynomial modulo a third polynomial.
- *
- * @param divisor the divisor
- * @param modulus the reduction polynomial
- * @return <tt>this * divisor^(-1) mod modulus</tt>
- */
- public PolynomialGF2mSmallM ModDiv(PolynomialGF2mSmallM divisor,
- PolynomialGF2mSmallM modulus)
- {
- int[] resultCoeff = ModDiv(coefficients, divisor.coefficients,
- modulus.coefficients);
- return new PolynomialGF2mSmallM(field, resultCoeff);
- }
-
- /**
- * Compute the result of the division of two polynomials modulo a third
- * polynomial over the field <tt>GF(2^m)</tt>.
- *
- * @param a the first polynomial
- * @param b the second polynomial
- * @param g the reduction polynomial
- * @return <tt>a * b^(-1) mod g</tt>
- */
- private int[] ModDiv(int[] a, int[] b, int[] g)
- {
- int[] r0 = NormalForm(g);
- int[] r1 = Mod(b, g);
- int[] s0 = { 0 };
- int[] s1 = Mod(a, g);
- int[] s2;
- int[][] q;
- while (ComputeDegree(r1) != -1)
- {
- q = Div(r0, r1);
- r0 = NormalForm(r1);
- r1 = NormalForm(q[1]);
- s2 = Add(s0, ModMultiply(q[0], s1, g));
- s0 = NormalForm(s1);
- s1 = NormalForm(s2);
-
- }
- int hc = HeadCoefficient(r0);
- s0 = MultWithElement(s0, field.Inverse(hc));
- return s0;
- }
-
- /**
- * Compute the inverse of this polynomial modulo the given polynomial.
- *
- * @param a the reduction polynomial
- * @return <tt>this^(-1) mod a</tt>
- */
- public PolynomialGF2mSmallM ModInverse(PolynomialGF2mSmallM a)
- {
- int[] unit = { 1 };
- int[] resultCoeff = ModDiv(unit, coefficients, a.coefficients);
- return new PolynomialGF2mSmallM(field, resultCoeff);
- }
-
- /**
- * Compute a polynomial pair (a,b) from this polynomial and the given
- * polynomial g with the property b*this = a mod g and deg(a)<=deg(g)/2.
- *
- * @param g the reduction polynomial
- * @return PolynomialGF2mSmallM[] {a,b} with b*this = a mod g and deg(a)<=
- * deg(g)/2
- */
- public PolynomialGF2mSmallM[] ModPolynomialToFracton(PolynomialGF2mSmallM g)
- {
- int dg = g.degree >> 1;
- int[] a0 = NormalForm(g.coefficients);
- int[] a1 = Mod(coefficients, g.coefficients);
- int[] b0 = { 0 };
- int[] b1 = { 1 };
- while (ComputeDegree(a1) > dg)
- {
- int[][] q = Div(a0, a1);
- a0 = a1;
- a1 = q[1];
- int[] b2 = Add(b0, ModMultiply(q[0], b1, g.coefficients));
- b0 = b1;
- b1 = b2;
- }
-
- return new PolynomialGF2mSmallM[]{
- new PolynomialGF2mSmallM(field, a1),
- new PolynomialGF2mSmallM(field, b1)};
- }
-
- /**
- * checks if given object is equal to this polynomial.
- * <p>
- * The method returns false whenever the given object is not polynomial over
- * GF(2^m).
- *
- * @param other object
- * @return true or false
- */
- public bool equals(Object other)
- {
-
- if (other == null || !(other is PolynomialGF2mSmallM))
- {
- return false;
- }
-
- PolynomialGF2mSmallM p = (PolynomialGF2mSmallM)other;
-
- if ((field.Equals(p.field)) && (degree == p.degree)
- && (IsEqual(coefficients, p.coefficients)))
- {
- return true;
- }
-
- return false;
- }
-
- /**
- * Compare two polynomials given as int arrays.
- *
- * @param a the first polynomial
- * @param b the second polynomial
- * @return <tt>true</tt> if <tt>a</tt> and <tt>b</tt> represent the
- * same polynomials, <tt>false</tt> otherwise
- */
- private static bool IsEqual(int[] a, int[] b)
- {
- int da = ComputeDegree(a);
- int db = ComputeDegree(b);
- if (da != db)
- {
- return false;
- }
- for (int i = 0; i <= da; i++)
- {
- if (a[i] != b[i])
- {
- return false;
- }
- }
- return true;
- }
-
- /**
- * @return the hash code of this polynomial
- */
- public int HashCode()
- {
- int hash = field.HashCode();
- for (int j = 0; j < coefficients.Length; j++)
- {
- hash = hash * 31 + coefficients[j];
- }
- return hash;
- }
-
- /**
- * Returns a human readable form of the polynomial.
- *
- * @return a human readable form of the polynomial.
- */
- public String toString()
- {
- String str = " Polynomial over " + field.ToString() + ": \n";
-
- for (int i = 0; i < coefficients.Length; i++)
- {
- str = str + field.ElementToStr(coefficients[i]) + "Y^" + i + "+";
- }
- str = str + ";";
-
- return str;
- }
-
- /**
- * Compute the degree of this polynomial. If this is the zero polynomial,
- * the degree is -1.
- */
- private void ComputeDegree()
- {
- for (degree = coefficients.Length - 1; degree >= 0
- && coefficients[degree] == 0; degree--)
- {
- ;
- }
- }
-
- /**
- * Compute the degree of a polynomial.
- *
- * @param a the polynomial
- * @return the degree of the polynomial <tt>a</tt>. If <tt>a</tt> is
- * the zero polynomial, return -1.
- */
- private static int ComputeDegree(int[] a)
- {
- int degree;
- for (degree = a.Length - 1; degree >= 0 && a[degree] == 0; degree--)
- {
- ;
- }
- return degree;
- }
-
- /**
- * Strip leading zero coefficients from the given polynomial.
- *
- * @param a the polynomial
- * @return the reduced polynomial
- */
- private static int[] NormalForm(int[] a)
- {
- int d = ComputeDegree(a);
-
- // if a is the zero polynomial
- if (d == -1)
- {
- // return new zero polynomial
- return new int[1];
- }
-
- // if a already is in normal form
- if (a.Length == d + 1)
- {
- // return a clone of a
- return IntUtils.Clone(a);
- }
-
- // else, reduce a
- int[] result = new int[d + 1];
- Array.Copy(a, 0, result, 0, d + 1);
- return result;
- }
-
- /**
- * Compute the product of this polynomial and another polynomial modulo a
- * third polynomial.
- *
- * @param a another polynomial
- * @param b the reduction polynomial
- * @return <tt>this * a mod b</tt>
- */
- public PolynomialGF2mSmallM ModKaratsubaMultiplyBigDeg(PolynomialGF2mSmallM a,
- PolynomialGF2mSmallM b)
- {
- int[] resultCoeff = ModKaratsubaMultiplyBigDeg(coefficients, a.coefficients,
- b.coefficients);
- return new PolynomialGF2mSmallM(field, resultCoeff);
- }
-
- /**
- * Compute the inverse of this polynomial modulo the given polynomial.
- *
- * @param a the reduction polynomial
- * @return <tt>this^(-1) mod a</tt>
- */
- public PolynomialGF2mSmallM ModInverseBigDeg(PolynomialGF2mSmallM a)
- {
- int[] unit = { 1 };
- int[] resultCoeff = ModDivBigDeg(unit, coefficients, a.coefficients);
- return new PolynomialGF2mSmallM(field, resultCoeff);
- }
-
- private int[] ModDivBigDeg(int[] a, int[] b, int[] g)
- {
- int[] r0 = NormalForm(g);
- int[] r1 = Mod(b, g);
- int[] s0 = { 0 };
- int[] s1 = Mod(a, g);
- int[] s2;
- int[][] q;
- while (ComputeDegree(r1) != -1)
- {
- q = Div(r0, r1);
- r0 = NormalForm(r1);
- r1 = NormalForm(q[1]);
- s2 = Add(s0, ModKaratsubaMultiplyBigDeg(q[0], s1, g));
- s0 = NormalForm(s1);
- s1 = NormalForm(s2);
- }
- int hc = HeadCoefficient(r0);
- s0 = MultWithElement(s0, field.Inverse(hc));
- return s0;
- }
-
- /**
- * Compute the product of two polynomials modulo a third polynomial over the
- * finite field <tt>GF(2^m)</tt>.
- *
- * @param aa the first polynomial
- * @param bb the second polynomial
- * @param g the reduction polynomial
- * @return <tt>a * b mod g</tt>
- */
- private int[] ModKaratsubaMultiplyBigDeg(int[] aa, int[] bb, int[] g)
- {
- int[] a, b;
- if (aa.Length >= bb.Length)
- {
- a = Arrays.Clone(aa);
- b = Arrays.Clone(bb);
- }
- else
- {
- a = Arrays.Clone(bb);
- b = Arrays.Clone(aa);
- }
-
- int n = a.Length;
- int m = b.Length;
-
- int[] D = new int[(n + m) / 2];
- int[] S = new int[n + m - 1];
- int[] T = new int[n + m - 1];
- int[] C = new int[n + m - 1];
-
- for (int i = 0; i < m; i++)
- {
- D[i] = a[i] * b[i];
- }
-
- for (int i = 1; i < n + m - 2; i++)
- {
- for (int p = 0; p < System.Math.Min(m, i); p++)
- {
- int q = i - p;
- if (p >= q)
- {
- break;
- }
-
- int ap = a[p];
- int aq = 0;
-
- if (q < a.Length)
- {
- aq = a[q];
- }
-
- int bp = b[p];
- int dp = D[p];
-
- if (q < m && p < m)
- {
- int bq = b[q];
- int dq = D[q];
-
- S[i] = S[i] + (ap + aq) * (bp + bq);
- T[i] = T[i] + dp + dq;
- }
- else if (q >= m && q < n)
- {
- S[i] = S[i] + ((ap + aq) * bp);
- T[i] = T[i] + dp;
- }
- }
- }
-
- for (int i = 0; i < n + m - 1; i++)
- {
- if (i == 0)
- {
- C[i] = D[i] % 2;
- }
- else if (i == n + m - 2)
- {
- C[i] = (a[a.Length - 1] * b[b.Length - 1]) % 2;
- }
- else if (i % 2 == 1)
- {
- C[i] = (S[i] - T[i]) % 2;
- }
- else
- {
- C[i] = (S[i] - T[i] + D[i / 2]) % 2;
- }
- }
- int[] res = Mod(C, g);
- return res;
- }
- }
-}
diff --git a/crypto/src/pqc/math/linearalgebra/PolynomialRingGF2.cs b/crypto/src/pqc/math/linearalgebra/PolynomialRingGF2.cs
deleted file mode 100644
index 9bc3fcd31..000000000
--- a/crypto/src/pqc/math/linearalgebra/PolynomialRingGF2.cs
+++ /dev/null
@@ -1,286 +0,0 @@
-using System;
-
-namespace Org.BouncyCastle.Pqc.Math.LinearAlgebra
-{
- /**
- * This class describes operations with polynomials over finite field GF(2), i e
- * polynomial ring R = GF(2)[X]. All operations are defined only for polynomials
- * with degree <=32. For the polynomial representation the map f: R->Z,
- * poly(X)->poly(2) is used, where integers have the binary representation. For
- * example: X^7+X^3+X+1 -> (00...0010001011)=139 Also for polynomials type
- * Integer is used.
- *
- * @see GF2mField
- */
- public class PolynomialRingGF2
- {
-
- /**
- * Default constructor (private).
- */
- private PolynomialRingGF2()
- {
- // empty
- }
-
- /**
- * Return sum of two polyomials
- *
- * @param p polynomial
- * @param q polynomial
- * @return p+q
- */
-
- public static int Add(int p, int q)
- {
- return p ^ q;
- }
-
- /**
- * Return product of two polynomials
- *
- * @param p polynomial
- * @param q polynomial
- * @return p*q
- */
-
- public static long Multiply(int p, int q)
- {
- long result = 0;
- if (q != 0)
- {
- long q1 = q & 0x00000000ffffffffL;
-
- while (p != 0)
- {
- byte b = (byte)(p & 0x01);
- if (b == 1)
- {
- result ^= q1;
- }
- p = Utils.UnsignedRightBitShiftInt(p, 1);
- q1 <<= 1;
-
- }
- }
- return result;
- }
-
- /**
- * Compute the product of two polynomials modulo a third polynomial.
- *
- * @param a the first polynomial
- * @param b the second polynomial
- * @param r the reduction polynomial
- * @return <tt>a * b mod r</tt>
- */
- public static int modMultiply(int a, int b, int r)
- {
- int result = 0;
- int p = Remainder(a, r);
- int q = Remainder(b, r);
- if (q != 0)
- {
- int d = 1 << Degree(r);
-
- while (p != 0)
- {
- byte pMod2 = (byte)(p & 0x01);
- if (pMod2 == 1)
- {
- result ^= q;
- }
- p = Utils.UnsignedRightBitShiftInt(p, 1);
- q <<= 1;
- if (q >= d)
- {
- q ^= r;
- }
- }
- }
- return result;
- }
-
- /**
- * Return the degree of a polynomial
- *
- * @param p polynomial p
- * @return degree(p)
- */
-
- public static int Degree(int p)
- {
- int result = -1;
- while (p != 0)
- {
- result++;
- p = Utils.UnsignedRightBitShiftInt(p, 1);
- }
- return result;
- }
-
- /**
- * Return the degree of a polynomial
- *
- * @param p polynomial p
- * @return degree(p)
- */
-
- public static int Degree(long p)
- {
- int result = 0;
- while (p != 0)
- {
- result++;
- p = Utils.UnsignedRightBitShiftLong(p, 1);
- }
- return result - 1;
- }
-
- /**
- * Return the remainder of a polynomial division of two polynomials.
- *
- * @param p dividend
- * @param q divisor
- * @return <tt>p mod q</tt>
- */
- public static int Remainder(int p, int q)
- {
- int result = p;
-
- if (q == 0)
- {
- // -DM Console.Error.WriteLine
- Console.Error.WriteLine("Error: to be divided by 0");
- return 0;
- }
-
- while (Degree(result) >= Degree(q))
- {
- result ^= q << (Degree(result) - Degree(q));
- }
-
- return result;
- }
-
- /**
- * Return the rest of devision two polynomials
- *
- * @param p polinomial
- * @param q polinomial
- * @return p mod q
- */
-
- public static int Rest(long p, int q)
- {
- long p1 = p;
- if (q == 0)
- {
- // -DM Console.Error.WriteLine
- Console.Error.WriteLine("Error: to be divided by 0");
- return 0;
- }
- long q1 = q & 0x00000000ffffffffL;
-
- while ((Utils.UnsignedRightBitShiftLong(p1, 32)) != 0)
- {
- p1 ^= q1 << (Degree(p1) - Degree(q1));
- }
-
- int result = (int)(p1 & 0xffffffff);
- while (Degree(result) >= Degree(q))
- {
- result ^= q << (Degree(result) - Degree(q));
- }
-
- return result;
- }
-
- /**
- * Return the greatest common divisor of two polynomials
- *
- * @param p polinomial
- * @param q polinomial
- * @return GCD(p, q)
- */
-
- public static int Gcd(int p, int q)
- {
- int a, b, c;
- a = p;
- b = q;
- while (b != 0)
- {
- c = Remainder(a, b);
- a = b;
- b = c;
-
- }
- return a;
- }
-
- /**
- * Checking polynomial for irreducibility
- *
- * @param p polinomial
- * @return true if p is irreducible and false otherwise
- */
-
- public static bool IsIrreducible(int p)
- {
- if (p == 0)
- {
- return false;
- }
- uint tmpDeg = (uint)Degree(p);
- int d = (int) tmpDeg >> 1;
- int u = 2;
- for (int i = 0; i < d; i++)
- {
- u = modMultiply(u, u, p);
- if (Gcd(u ^ 2, p) != 1)
- {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Creates irreducible polynomial with degree d
- *
- * @param deg polynomial degree
- * @return irreducible polynomial p
- */
- public static int GetIrreduciblePolynomial(int deg)
- {
- if (deg < 0)
- {
- // -DM Console.Error.WriteLine
- Console.Error.WriteLine("The Degree is negative");
- return 0;
- }
- if (deg > 31)
- {
- // -DM Console.Error.WriteLine
- Console.Error.WriteLine("The Degree is more then 31");
- return 0;
- }
- if (deg == 0)
- {
- return 1;
- }
- int a = 1 << deg;
- a++;
- int b = 1 << (deg + 1);
- for (int i = a; i < b; i += 2)
- {
- if (IsIrreducible(i))
- {
- return i;
- }
- }
- return 0;
- }
- }
-}
diff --git a/crypto/src/pqc/math/linearalgebra/RandUtils.cs b/crypto/src/pqc/math/linearalgebra/RandUtils.cs
deleted file mode 100644
index f7b7b8588..000000000
--- a/crypto/src/pqc/math/linearalgebra/RandUtils.cs
+++ /dev/null
@@ -1,27 +0,0 @@
-using Org.BouncyCastle.Security;
-
-namespace Org.BouncyCastle.Pqc.Math.LinearAlgebra
-{
- public class RandUtils
- {
- public static int NextInt(SecureRandom rand, int n)
- {
-
- if ((n & -n) == n) // i.e., n is a power of 2
- {
- return (int)((n * (long)(Utils.UnsignedRightBitShiftInt(rand.NextInt(), 1))) >> 31);
- }
-
- int bits, value;
- do
- {
- bits = Utils.UnsignedRightBitShiftInt(rand.NextInt() ,1);
- value = bits % n;
- }
- while (bits - value + (n - 1) < 0);
-
- return value;
- }
- }
-
-}
diff --git a/crypto/src/pqc/math/linearalgebra/Utils.cs b/crypto/src/pqc/math/linearalgebra/Utils.cs
deleted file mode 100644
index eb2760f82..000000000
--- a/crypto/src/pqc/math/linearalgebra/Utils.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-
-namespace Org.BouncyCastle.Pqc.Math.LinearAlgebra
-{
- class Utils
- {
- internal static int UnsignedRightBitShiftInt(int a, int b)
- {
- uint tmp = (uint) a;
- tmp >>= b;
- return (int) tmp;
- }
-
- internal static long UnsignedRightBitShiftLong(long a, int b)
- {
- ulong tmp = (ulong)a;
- tmp >>= b;
- return (long) tmp;
- }
- }
-}
diff --git a/crypto/src/pqc/math/linearalgebra/Vector.cs b/crypto/src/pqc/math/linearalgebra/Vector.cs
deleted file mode 100644
index e50c54792..000000000
--- a/crypto/src/pqc/math/linearalgebra/Vector.cs
+++ /dev/null
@@ -1,62 +0,0 @@
-using System;
-
-namespace Org.BouncyCastle.Pqc.Math.LinearAlgebra
-{
- /**
- * This abstract class defines vectors. It holds the length of vector.
- */
- public abstract class Vector
- {
-
- /**
- * the length of this vector
- */
- protected int length;
-
- /**
- * @return the length of this vector
- */
- public int GetLength()
- {
- return length;
- }
-
- /**
- * @return this vector as byte array
- */
- public abstract byte[] GetEncoded();
-
- /**
- * Return whether this is the zero vector (i.e., all elements are zero).
- *
- * @return <tt>true</tt> if this is the zero vector, <tt>false</tt>
- * otherwise
- */
- public abstract bool IsZero();
-
- /**
- * Add another vector to this vector.
- *
- * @param addend the other vector
- * @return <tt>this + addend</tt>
- */
- public abstract Vector Add(Vector addend);
-
- /**
- * Multiply this vector with a permutation.
- *
- * @param p the permutation
- * @return <tt>this*p = p*this</tt>
- */
- public abstract Vector Multiply(Permutation p);
-
- /**
- * Check if the given object is equal to this vector.
- *
- * @param other vector
- * @return the result of the comparison
- */
- public abstract bool Equals(Object other);
-
- }
-}
|