summaryrefslogtreecommitdiffstats
path: root/bcprov/src/main/java/org/bouncycastle/pqc/math
diff options
context:
space:
mode:
Diffstat (limited to 'bcprov/src/main/java/org/bouncycastle/pqc/math')
-rw-r--r--bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/BigEndianConversions.java306
-rw-r--r--bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/BigIntUtils.java138
-rw-r--r--bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/ByteUtils.java414
-rw-r--r--bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/CharUtils.java98
-rw-r--r--bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2Matrix.java1323
-rw-r--r--bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2Polynomial.java2039
-rw-r--r--bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2Vector.java539
-rw-r--r--bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2mField.java369
-rw-r--r--bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2mMatrix.java377
-rw-r--r--bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2mVector.java256
-rw-r--r--bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2nElement.java186
-rw-r--r--bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2nField.java292
-rw-r--r--bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2nONBElement.java1154
-rw-r--r--bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2nONBField.java546
-rw-r--r--bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2nPolynomial.java587
-rw-r--r--bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2nPolynomialElement.java1021
-rw-r--r--bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2nPolynomialField.java553
-rw-r--r--bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GFElement.java158
-rw-r--r--bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GoppaCode.java310
-rw-r--r--bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/IntUtils.java202
-rw-r--r--bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/IntegerFunctions.java1423
-rw-r--r--bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/LittleEndianConversions.java230
-rw-r--r--bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/Matrix.java131
-rw-r--r--bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/Permutation.java247
-rw-r--r--bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/PolynomialGF2mSmallM.java1124
-rw-r--r--bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/PolynomialRingGF2.java278
-rw-r--r--bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/PolynomialRingGF2m.java175
-rw-r--r--bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/RandUtils.java25
-rw-r--r--bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/Vector.java69
-rw-r--r--bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/euclid/BigIntEuclidean.java54
-rw-r--r--bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/euclid/IntEuclidean.java51
-rw-r--r--bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/euclid/test/AllTests.java24
-rw-r--r--bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/euclid/test/BigIntEuclideanTest.java23
-rw-r--r--bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/euclid/test/IntEuclideanTest.java43
-rw-r--r--bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/BigDecimalPolynomial.java258
-rw-r--r--bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/BigIntPolynomial.java394
-rw-r--r--bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/Constants.java12
-rw-r--r--bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/DenseTernaryPolynomial.java142
-rw-r--r--bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/IntegerPolynomial.java1358
-rw-r--r--bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/LongPolynomial2.java255
-rw-r--r--bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/LongPolynomial5.java149
-rw-r--r--bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/ModularResultant.java46
-rw-r--r--bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/Polynomial.java42
-rw-r--r--bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/ProductFormPolynomial.java153
-rw-r--r--bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/Resultant.java28
-rw-r--r--bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/SparseTernaryPolynomial.java320
-rw-r--r--bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/TernaryPolynomial.java25
-rw-r--r--bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/test/AllTests.java29
-rw-r--r--bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/test/BigDecimalPolynomialTest.java47
-rw-r--r--bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/test/BigIntPolynomialTest.java26
-rw-r--r--bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/test/IntegerPolynomialTest.java230
-rw-r--r--bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/test/LongPolynomial2Test.java60
-rw-r--r--bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/test/LongPolynomial5Test.java62
-rw-r--r--bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/test/PolynomialGenerator.java27
-rw-r--r--bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/test/ProductFormPolynomialTest.java47
-rw-r--r--bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/test/SparseTernaryPolynomialTest.java45
-rw-r--r--bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/util/ArrayEncoder.java294
-rw-r--r--bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/util/Util.java158
-rw-r--r--bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/util/test/AllTests.java23
-rw-r--r--bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/util/test/ArrayEncoderTest.java42
60 files changed, 0 insertions, 19037 deletions
diff --git a/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/BigEndianConversions.java b/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/BigEndianConversions.java
deleted file mode 100644
index 90926f6..0000000
--- a/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/BigEndianConversions.java
+++ /dev/null
@@ -1,306 +0,0 @@
-package org.bouncycastle.pqc.math.linearalgebra;
-
-
-/**
- * This is a utility class containing data type conversions using big-endian
- * byte order.
- *
- * @see LittleEndianConversions
- */
-public final class BigEndianConversions
-{
-
- /**
- * Default constructor (private).
- */
- private BigEndianConversions()
- {
- // empty
- }
-
- /**
- * Convert an integer to an octet string of length 4 according to IEEE 1363,
- * Section 5.5.3.
- *
- * @param x the integer to convert
- * @return the converted integer
- */
- public static byte[] I2OSP(int x)
- {
- byte[] result = new byte[4];
- result[0] = (byte)(x >>> 24);
- result[1] = (byte)(x >>> 16);
- result[2] = (byte)(x >>> 8);
- result[3] = (byte)x;
- return result;
- }
-
- /**
- * Convert an integer to an octet string according to IEEE 1363, Section
- * 5.5.3. Length checking is performed.
- *
- * @param x the integer to convert
- * @param oLen the desired length of the octet string
- * @return an octet string of length <tt>oLen</tt> representing the
- * integer <tt>x</tt>, or <tt>null</tt> if the integer is
- * negative
- * @throws ArithmeticException if <tt>x</tt> can't be encoded into <tt>oLen</tt>
- * octets.
- */
- public static byte[] I2OSP(int x, int oLen)
- throws ArithmeticException
- {
- if (x < 0)
- {
- return null;
- }
- int octL = IntegerFunctions.ceilLog256(x);
- if (octL > oLen)
- {
- throw new ArithmeticException(
- "Cannot encode given integer into specified number of octets.");
- }
- byte[] result = new byte[oLen];
- for (int i = oLen - 1; i >= oLen - octL; i--)
- {
- result[i] = (byte)(x >>> (8 * (oLen - 1 - i)));
- }
- return result;
- }
-
- /**
- * Convert an integer to an octet string of length 4 according to IEEE 1363,
- * Section 5.5.3.
- *
- * @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(int input, byte[] output, int outOff)
- {
- output[outOff++] = (byte)(input >>> 24);
- output[outOff++] = (byte)(input >>> 16);
- output[outOff++] = (byte)(input >>> 8);
- output[outOff] = (byte)input;
- }
-
- /**
- * Convert an integer to an octet string of length 8 according to IEEE 1363,
- * Section 5.5.3.
- *
- * @param input the integer to convert
- * @return the converted integer
- */
- public static byte[] I2OSP(long input)
- {
- byte[] output = new byte[8];
- output[0] = (byte)(input >>> 56);
- output[1] = (byte)(input >>> 48);
- output[2] = (byte)(input >>> 40);
- output[3] = (byte)(input >>> 32);
- output[4] = (byte)(input >>> 24);
- output[5] = (byte)(input >>> 16);
- output[6] = (byte)(input >>> 8);
- output[7] = (byte)input;
- return output;
- }
-
- /**
- * Convert an integer to an octet string of length 8 according to IEEE 1363,
- * Section 5.5.3.
- *
- * @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)
- {
- output[outOff++] = (byte)(input >>> 56);
- output[outOff++] = (byte)(input >>> 48);
- output[outOff++] = (byte)(input >>> 40);
- output[outOff++] = (byte)(input >>> 32);
- output[outOff++] = (byte)(input >>> 24);
- output[outOff++] = (byte)(input >>> 16);
- output[outOff++] = (byte)(input >>> 8);
- output[outOff] = (byte)input;
- }
-
- /**
- * Convert an integer to an octet string of the specified length according
- * to IEEE 1363, Section 5.5.3. No length checking is performed (i.e., if
- * the integer cannot be encoded into <tt>length</tt> octets, it is
- * truncated).
- *
- * @param input the integer to convert
- * @param output byte array holding the output
- * @param outOff offset in output array where the result is stored
- * @param length the length of the encoding
- */
- public static void I2OSP(int input, byte[] output, int outOff, int length)
- {
- for (int i = length - 1; i >= 0; i--)
- {
- output[outOff + i] = (byte)(input >>> (8 * (length - 1 - i)));
- }
- }
-
- /**
- * Convert an octet string to an integer according to IEEE 1363, Section
- * 5.5.3.
- *
- * @param input the byte array holding the octet string
- * @return an integer representing the octet string <tt>input</tt>, or
- * <tt>0</tt> if the represented integer is negative or too large
- * or the byte array is empty
- * @throws ArithmeticException if the length of the given octet string is larger than 4.
- */
- public static int OS2IP(byte[] input)
- {
- if (input.length > 4)
- {
- throw new ArithmeticException("invalid input length");
- }
- if (input.length == 0)
- {
- return 0;
- }
- int result = 0;
- for (int j = 0; j < input.length; j++)
- {
- result |= (input[j] & 0xff) << (8 * (input.length - 1 - j));
- }
- return result;
- }
-
- /**
- * Convert a 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)
- {
- int result = (input[inOff++] & 0xff) << 24;
- result |= (input[inOff++] & 0xff) << 16;
- result |= (input[inOff++] & 0xff) << 8;
- result |= input[inOff] & 0xff;
- return result;
- }
-
- /**
- * Convert an octet string to an integer according to IEEE 1363, Section
- * 5.5.3.
- *
- * @param input the byte array holding the octet string
- * @param inOff the offset in the input byte array where the octet string
- * starts
- * @param inLen the length of the encoded integer
- * @return an integer representing the octet string <tt>bytes</tt>, or
- * <tt>0</tt> if the represented integer is negative or too large
- * or the byte array is empty
- */
- public static int OS2IP(byte[] input, int inOff, int inLen)
- {
- if ((input.length == 0) || input.length < inOff + inLen - 1)
- {
- return 0;
- }
- int result = 0;
- for (int j = 0; j < inLen; j++)
- {
- result |= (input[inOff + j] & 0xff) << (8 * (inLen - j - 1));
- }
- 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)
- {
- long result = ((long)input[inOff++] & 0xff) << 56;
- result |= ((long)input[inOff++] & 0xff) << 48;
- result |= ((long)input[inOff++] & 0xff) << 40;
- result |= ((long)input[inOff++] & 0xff) << 32;
- result |= ((long)input[inOff++] & 0xff) << 24;
- result |= (input[inOff++] & 0xff) << 16;
- result |= (input[inOff++] & 0xff) << 8;
- result |= input[inOff] & 0xff;
- return result;
- }
-
- /**
- * Convert an int array into a byte array.
- *
- * @param input the int array
- * @return the converted array
- */
- public static byte[] toByteArray(final int[] input)
- {
- byte[] result = new byte[input.length << 2];
- for (int i = 0; i < input.length; i++)
- {
- I2OSP(input[i], result, i << 2);
- }
- return result;
- }
-
- /**
- * Convert an int array into a byte array of the specified length. No length
- * checking is performed (i.e., if the last integer cannot be encoded into
- * <tt>length % 4</tt> octets, it is truncated).
- *
- * @param input the int array
- * @param length the length of the converted array
- * @return the converted array
- */
- public static byte[] toByteArray(final int[] input, int length)
- {
- final int intLen = input.length;
- byte[] result = new byte[length];
- int index = 0;
- for (int i = 0; i <= intLen - 2; i++, index += 4)
- {
- I2OSP(input[i], result, index);
- }
- I2OSP(input[intLen - 1], result, index, length - index);
- return result;
- }
-
- /**
- * Convert a byte array into an int array.
- *
- * @param input the byte array
- * @return the converted array
- */
- public static int[] toIntArray(byte[] input)
- {
- final int intLen = (input.length + 3) / 4;
- final 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/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/BigIntUtils.java b/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/BigIntUtils.java
deleted file mode 100644
index b99ed41..0000000
--- a/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/BigIntUtils.java
+++ /dev/null
@@ -1,138 +0,0 @@
-package org.bouncycastle.pqc.math.linearalgebra;
-
-import java.math.BigInteger;
-
-/**
- * FIXME: is this really necessary?!
- */
-public final class BigIntUtils
-{
-
- /**
- * Default constructor (private).
- */
- private BigIntUtils()
- {
- // empty
- }
-
- /**
- * Checks if two BigInteger arrays contain the same entries
- *
- * @param a first BigInteger array
- * @param b second BigInteger array
- * @return true or false
- */
- public static boolean equals(BigInteger[] a, BigInteger[] b)
- {
- int flag = 0;
-
- if (a.length != b.length)
- {
- return false;
- }
- for (int i = 0; i < a.length; i++)
- {
- // avoid branches here!
- // problem: compareTo on BigIntegers is not
- // guaranteed constant-time!
- flag |= a[i].compareTo(b[i]);
- }
- return flag == 0;
- }
-
- /**
- * Fill the given BigInteger array with the given value.
- *
- * @param array the array
- * @param value the value
- */
- public static void fill(BigInteger[] array, BigInteger value)
- {
- for (int i = array.length - 1; i >= 0; i--)
- {
- array[i] = value;
- }
- }
-
- /**
- * Generates a subarray of a given BigInteger array.
- *
- * @param input -
- * the input BigInteger 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 BigInteger[] subArray(BigInteger[] input, int start, int end)
- {
- BigInteger[] result = new BigInteger[end - start];
- System.arraycopy(input, start, result, 0, end - start);
- return result;
- }
-
- /**
- * Converts a BigInteger array into an integer array
- *
- * @param input -
- * the BigInteger array
- * @return the integer array
- */
- public static int[] toIntArray(BigInteger[] input)
- {
- int[] result = new int[input.length];
- for (int i = 0; i < input.length; i++)
- {
- result[i] = input[i].intValue();
- }
- return result;
- }
-
- /**
- * Converts a BigInteger array into an integer array, reducing all
- * BigIntegers mod q.
- *
- * @param q -
- * the modulus
- * @param input -
- * the BigInteger array
- * @return the integer array
- */
- public static int[] toIntArrayModQ(int q, BigInteger[] input)
- {
- BigInteger bq = BigInteger.valueOf(q);
- int[] result = new int[input.length];
- for (int i = 0; i < input.length; i++)
- {
- result[i] = input[i].mod(bq).intValue();
- }
- return result;
- }
-
- /**
- * Return the value of <tt>big</tt> as a byte array. Although BigInteger
- * has such a method, it uses an extra bit to indicate the sign of the
- * number. For elliptic curve cryptography, the numbers usually are
- * positive. Thus, this helper method returns a byte array of minimal
- * length, ignoring the sign of the number.
- *
- * @param value the <tt>BigInteger</tt> value to be converted to a byte
- * array
- * @return the value <tt>big</tt> as byte array
- */
- public static byte[] toMinimalByteArray(BigInteger value)
- {
- byte[] valBytes = value.toByteArray();
- if ((valBytes.length == 1) || (value.bitLength() & 0x07) != 0)
- {
- return valBytes;
- }
- byte[] result = new byte[value.bitLength() >> 3];
- System.arraycopy(valBytes, 1, result, 0, result.length);
- return result;
- }
-
-}
diff --git a/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/ByteUtils.java b/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/ByteUtils.java
deleted file mode 100644
index 5ad91f4..0000000
--- a/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/ByteUtils.java
+++ /dev/null
@@ -1,414 +0,0 @@
-package org.bouncycastle.pqc.math.linearalgebra;
-
-/**
- * This class is a utility class for manipulating byte arrays.
- */
-public final class ByteUtils
-{
-
- private static final char[] HEX_CHARS = {'0', '1', '2', '3', '4', '5',
- '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
-
- /**
- * Default constructor (private)
- */
- private ByteUtils()
- {
- // empty
- }
-
- /**
- * Compare two byte arrays (perform null checks beforehand).
- *
- * @param left the first byte array
- * @param right the second byte array
- * @return the result of the comparison
- */
- public static boolean equals(byte[] left, byte[] right)
- {
- if (left == null)
- {
- return right == null;
- }
- if (right == null)
- {
- return false;
- }
-
- if (left.length != right.length)
- {
- return false;
- }
- boolean result = true;
- for (int i = left.length - 1; i >= 0; i--)
- {
- result &= left[i] == right[i];
- }
- return result;
- }
-
- /**
- * Compare two two-dimensional byte arrays. No null checks are performed.
- *
- * @param left the first byte array
- * @param right the second byte array
- * @return the result of the comparison
- */
- public static boolean equals(byte[][] left, byte[][] right)
- {
- if (left.length != right.length)
- {
- return false;
- }
-
- boolean result = true;
- for (int i = left.length - 1; i >= 0; i--)
- {
- result &= ByteUtils.equals(left[i], right[i]);
- }
-
- return result;
- }
-
- /**
- * Compare two three-dimensional byte arrays. No null checks are performed.
- *
- * @param left the first byte array
- * @param right the second byte array
- * @return the result of the comparison
- */
- public static boolean equals(byte[][][] left, byte[][][] right)
- {
- if (left.length != right.length)
- {
- return false;
- }
-
- boolean result = true;
- for (int i = left.length - 1; i >= 0; i--)
- {
- if (left[i].length != right[i].length)
- {
- return false;
- }
- for (int j = left[i].length - 1; j >= 0; j--)
- {
- result &= ByteUtils.equals(left[i][j], right[i][j]);
- }
- }
-
- return result;
- }
-
- /**
- * Computes a hashcode based on the contents of a one-dimensional byte array
- * rather than its identity.
- *
- * @param array the array to compute the hashcode of
- * @return the hashcode
- */
- public static int deepHashCode(byte[] array)
- {
- int result = 1;
- for (int i = 0; i < array.length; i++)
- {
- result = 31 * result + array[i];
- }
- return result;
- }
-
- /**
- * Computes a hashcode based on the contents of a two-dimensional byte array
- * rather than its identity.
- *
- * @param array the array to compute the hashcode of
- * @return the hashcode
- */
- public static int deepHashCode(byte[][] array)
- {
- int result = 1;
- for (int i = 0; i < array.length; i++)
- {
- result = 31 * result + deepHashCode(array[i]);
- }
- return result;
- }
-
- /**
- * Computes a hashcode based on the contents of a three-dimensional byte
- * array rather than its identity.
- *
- * @param array the array to compute the hashcode of
- * @return the hashcode
- */
- public static int deepHashCode(byte[][][] array)
- {
- int result = 1;
- for (int i = 0; i < array.length; i++)
- {
- result = 31 * result + deepHashCode(array[i]);
- }
- return result;
- }
-
-
- /**
- * Return a clone of the given byte array (performs null check beforehand).
- *
- * @param array the array to clone
- * @return the clone of the given array, or <tt>null</tt> if the array is
- * <tt>null</tt>
- */
- public static byte[] clone(byte[] array)
- {
- if (array == null)
- {
- return null;
- }
- byte[] result = new byte[array.length];
- System.arraycopy(array, 0, result, 0, array.length);
- return result;
- }
-
- /**
- * Convert a string containing hexadecimal characters to a byte-array.
- *
- * @param s a hex string
- * @return a byte array with the corresponding value
- */
- public static byte[] fromHexString(String s)
- {
- char[] rawChars = s.toUpperCase().toCharArray();
-
- int hexChars = 0;
- for (int i = 0; i < rawChars.length; i++)
- {
- if ((rawChars[i] >= '0' && rawChars[i] <= '9')
- || (rawChars[i] >= 'A' && rawChars[i] <= 'F'))
- {
- hexChars++;
- }
- }
-
- byte[] byteString = new byte[(hexChars + 1) >> 1];
-
- int pos = hexChars & 1;
-
- for (int i = 0; i < rawChars.length; i++)
- {
- if (rawChars[i] >= '0' && rawChars[i] <= '9')
- {
- byteString[pos >> 1] <<= 4;
- byteString[pos >> 1] |= rawChars[i] - '0';
- }
- else if (rawChars[i] >= 'A' && rawChars[i] <= 'F')
- {
- byteString[pos >> 1] <<= 4;
- byteString[pos >> 1] |= rawChars[i] - 'A' + 10;
- }
- else
- {
- continue;
- }
- pos++;
- }
-
- return byteString;
- }
-
- /**
- * Convert a byte array to the corresponding hexstring.
- *
- * @param input the byte array to be converted
- * @return the corresponding hexstring
- */
- public static String toHexString(byte[] input)
- {
- String result = "";
- for (int i = 0; i < input.length; i++)
- {
- result += HEX_CHARS[(input[i] >>> 4) & 0x0f];
- result += HEX_CHARS[(input[i]) & 0x0f];
- }
- return result;
- }
-
- /**
- * Convert a byte array to the corresponding hex string.
- *
- * @param input the byte array to be converted
- * @param prefix the prefix to put at the beginning of the hex string
- * @param seperator a separator string
- * @return the corresponding hex string
- */
- public static String toHexString(byte[] input, String prefix,
- String seperator)
- {
- String result = new String(prefix);
- for (int i = 0; i < input.length; i++)
- {
- result += HEX_CHARS[(input[i] >>> 4) & 0x0f];
- result += HEX_CHARS[(input[i]) & 0x0f];
- if (i < input.length - 1)
- {
- result += seperator;
- }
- }
- return result;
- }
-
- /**
- * Convert a byte array to the corresponding bit string.
- *
- * @param input the byte array to be converted
- * @return the corresponding bit string
- */
- public static String toBinaryString(byte[] input)
- {
- String result = "";
- int i;
- for (i = 0; i < input.length; i++)
- {
- int e = input[i];
- for (int ii = 0; ii < 8; ii++)
- {
- int b = (e >>> ii) & 1;
- result += b;
- }
- if (i != input.length - 1)
- {
- result += " ";
- }
- }
- return result;
- }
-
- /**
- * Compute the bitwise XOR of two arrays of bytes. The arrays have to be of
- * same length. No length checking is performed.
- *
- * @param x1 the first array
- * @param x2 the second array
- * @return x1 XOR x2
- */
- public static byte[] xor(byte[] x1, byte[] x2)
- {
- byte[] out = new byte[x1.length];
-
- for (int i = x1.length - 1; i >= 0; i--)
- {
- out[i] = (byte)(x1[i] ^ x2[i]);
- }
- return out;
- }
-
- /**
- * Concatenate two byte arrays. No null checks are performed.
- *
- * @param x1 the first array
- * @param x2 the second array
- * @return (x2||x1) (little-endian order, i.e. x1 is at lower memory
- * addresses)
- */
- public static byte[] concatenate(byte[] x1, byte[] x2)
- {
- byte[] result = new byte[x1.length + x2.length];
-
- System.arraycopy(x1, 0, result, 0, x1.length);
- System.arraycopy(x2, 0, result, x1.length, x2.length);
-
- return result;
- }
-
- /**
- * Convert a 2-dimensional byte array into a 1-dimensional byte array by
- * concatenating all entries.
- *
- * @param array a 2-dimensional byte array
- * @return the concatenated input array
- */
- public static byte[] concatenate(byte[][] array)
- {
- int rowLength = array[0].length;
- byte[] result = new byte[array.length * rowLength];
- int index = 0;
- for (int i = 0; i < array.length; i++)
- {
- System.arraycopy(array[i], 0, result, index, rowLength);
- index += rowLength;
- }
- return result;
- }
-
- /**
- * Split a byte array <tt>input</tt> into two arrays at <tt>index</tt>,
- * i.e. the first array will have the lower <tt>index</tt> bytes, the
- * second one the higher <tt>input.length - index</tt> bytes.
- *
- * @param input the byte array to be split
- * @param index the index where the byte array is split
- * @return the splitted input array as an array of two byte arrays
- * @throws ArrayIndexOutOfBoundsException if <tt>index</tt> is out of bounds
- */
- public static byte[][] split(byte[] input, int index)
- throws ArrayIndexOutOfBoundsException
- {
- if (index > input.length)
- {
- throw new ArrayIndexOutOfBoundsException();
- }
- byte[][] result = new byte[2][];
- result[0] = new byte[index];
- result[1] = new byte[input.length - index];
- System.arraycopy(input, 0, result[0], 0, index);
- System.arraycopy(input, index, result[1], 0, input.length - index);
- return result;
- }
-
- /**
- * Generate a subarray of a given byte array.
- *
- * @param input the input byte array
- * @param start the start index
- * @param end the end index
- * @return a subarray of <tt>input</tt>, ranging from <tt>start</tt>
- * (inclusively) to <tt>end</tt> (exclusively)
- */
- public static byte[] subArray(byte[] input, int start, int end)
- {
- byte[] result = new byte[end - start];
- System.arraycopy(input, start, result, 0, end - start);
- return result;
- }
-
- /**
- * Generate a subarray of a given byte array.
- *
- * @param input the input byte array
- * @param start the start index
- * @return a subarray of <tt>input</tt>, ranging from <tt>start</tt> to
- * the end of the array
- */
- public static byte[] subArray(byte[] input, int start)
- {
- return subArray(input, start, input.length);
- }
-
- /**
- * Rewrite a byte array as a char array
- *
- * @param input -
- * the byte array
- * @return char array
- */
- public static char[] toCharArray(byte[] input)
- {
- char[] result = new char[input.length];
- for (int i = 0; i < input.length; i++)
- {
- result[i] = (char)input[i];
- }
- return result;
- }
-
-}
diff --git a/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/CharUtils.java b/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/CharUtils.java
deleted file mode 100644
index 1800685..0000000
--- a/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/CharUtils.java
+++ /dev/null
@@ -1,98 +0,0 @@
-package org.bouncycastle.pqc.math.linearalgebra;
-
-public final class CharUtils
-{
-
- /**
- * Default constructor (private)
- */
- private CharUtils()
- {
- // empty
- }
-
- /**
- * Return a clone of the given char array. No null checks are performed.
- *
- * @param array the array to clone
- * @return the clone of the given array
- */
- public static char[] clone(char[] array)
- {
- char[] result = new char[array.length];
- System.arraycopy(array, 0, result, 0, array.length);
- return result;
- }
-
- /**
- * Convert the given char array into a byte array.
- *
- * @param chars the char array
- * @return the converted array
- */
- public static byte[] toByteArray(char[] chars)
- {
- byte[] result = new byte[chars.length];
- for (int i = chars.length - 1; i >= 0; i--)
- {
- result[i] = (byte)chars[i];
- }
- return result;
- }
-
- /**
- * Convert the given char array into a
- * byte array for use with PBE encryption.
- *
- * @param chars the char array
- * @return the converted array
- */
- public static byte[] toByteArrayForPBE(char[] chars)
- {
-
- byte[] out = new byte[chars.length];
-
- for (int i = 0; i < chars.length; i++)
- {
- out[i] = (byte)chars[i];
- }
-
- int length = out.length * 2;
- byte[] ret = new byte[length + 2];
-
- int j = 0;
- for (int i = 0; i < out.length; i++)
- {
- j = i * 2;
- ret[j] = 0;
- ret[j + 1] = out[i];
- }
-
- ret[length] = 0;
- ret[length + 1] = 0;
-
- return ret;
- }
-
- /**
- * Compare two char arrays. No null checks are performed.
- *
- * @param left the char byte array
- * @param right the second char array
- * @return the result of the comparison
- */
- public static boolean equals(char[] left, char[] right)
- {
- if (left.length != right.length)
- {
- return false;
- }
- boolean result = true;
- for (int i = left.length - 1; i >= 0; i--)
- {
- result &= left[i] == right[i];
- }
- return result;
- }
-
-}
diff --git a/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2Matrix.java b/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2Matrix.java
deleted file mode 100644
index a61f950..0000000
--- a/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2Matrix.java
+++ /dev/null
@@ -1,1323 +0,0 @@
-package org.bouncycastle.pqc.math.linearalgebra;
-
-import java.security.SecureRandom;
-
-/**
- * This class describes some operations with matrices over finite field GF(2)
- * and is used in ecc and MQ-PKC (also has some specific methods and
- * implementation)
- */
-public class GF2Matrix
- extends Matrix
-{
-
- /**
- * For the matrix representation the array of type int[][] is used, thus one
- * element of the array keeps 32 elements of the matrix (from one row and 32
- * columns)
- */
- private int[][] matrix;
-
- /**
- * the length of each array representing a row of this matrix, computed as
- * <tt>(numColumns + 31) / 32</tt>
- */
- private int length;
-
- /**
- * Create the matrix from encoded form.
- *
- * @param enc the encoded matrix
- */
- public GF2Matrix(byte[] enc)
- {
- if (enc.length < 9)
- {
- throw new ArithmeticException(
- "given array is not an encoded matrix over GF(2)");
- }
-
- numRows = LittleEndianConversions.OS2IP(enc, 0);
- numColumns = LittleEndianConversions.OS2IP(enc, 4);
-
- int n = ((numColumns + 7) >>> 3) * numRows;
-
- if ((numRows <= 0) || (n != (enc.length - 8)))
- {
- throw new ArithmeticException(
- "given array is not an encoded matrix over GF(2)");
- }
-
- length = (numColumns + 31) >>> 5;
- matrix = new int[numRows][length];
-
- // number of "full" integer
- int q = numColumns >> 5;
- // number of bits in non-full integer
- int r = numColumns & 0x1f;
-
- int count = 8;
- for (int i = 0; i < numRows; i++)
- {
- for (int j = 0; j < q; j++, count += 4)
- {
- matrix[i][j] = LittleEndianConversions.OS2IP(enc, count);
- }
- for (int j = 0; j < r; j += 8)
- {
- matrix[i][q] ^= (enc[count++] & 0xff) << j;
- }
- }
- }
-
- /**
- * Create the matrix with the contents of the given array. The matrix is not
- * copied. Unused coefficients are masked out.
- *
- * @param numColumns the number of columns
- * @param matrix the element array
- */
- public GF2Matrix(int numColumns, int[][] matrix)
- {
- if (matrix[0].length != (numColumns + 31) >> 5)
- {
- throw new ArithmeticException(
- "Int array does not match given number of columns.");
- }
- this.numColumns = numColumns;
- numRows = matrix.length;
- length = matrix[0].length;
- int rest = numColumns & 0x1f;
- int bitMask;
- if (rest == 0)
- {
- bitMask = 0xffffffff;
- }
- else
- {
- bitMask = (1 << rest) - 1;
- }
- for (int i = 0; i < numRows; i++)
- {
- matrix[i][length - 1] &= bitMask;
- }
- this.matrix = matrix;
- }
-
- /**
- * Create an nxn matrix of the given type.
- *
- * @param n the number of rows (and columns)
- * @param typeOfMatrix the martix type (see {@link Matrix} for predefined
- * constants)
- */
- public GF2Matrix(int n, char typeOfMatrix)
- {
- this(n, typeOfMatrix, new java.security.SecureRandom());
- }
-
- /**
- * Create an nxn matrix of the given type.
- *
- * @param n the matrix size
- * @param typeOfMatrix the matrix type
- * @param sr the source of randomness
- */
- public GF2Matrix(int n, char typeOfMatrix, SecureRandom sr)
- {
- if (n <= 0)
- {
- throw new ArithmeticException("Size of matrix is non-positive.");
- }
-
- switch (typeOfMatrix)
- {
-
- case Matrix.MATRIX_TYPE_ZERO:
- assignZeroMatrix(n, n);
- break;
-
- case Matrix.MATRIX_TYPE_UNIT:
- assignUnitMatrix(n);
- break;
-
- case Matrix.MATRIX_TYPE_RANDOM_LT:
- assignRandomLowerTriangularMatrix(n, sr);
- break;
-
- case Matrix.MATRIX_TYPE_RANDOM_UT:
- assignRandomUpperTriangularMatrix(n, sr);
- break;
-
- case Matrix.MATRIX_TYPE_RANDOM_REGULAR:
- assignRandomRegularMatrix(n, sr);
- break;
-
- default:
- throw new ArithmeticException("Unknown matrix type.");
- }
- }
-
- /**
- * Copy constructor.
- *
- * @param a another {@link GF2Matrix}
- */
- public GF2Matrix(GF2Matrix a)
- {
- numColumns = a.getNumColumns();
- numRows = a.getNumRows();
- length = a.length;
- matrix = new int[a.matrix.length][];
- for (int i = 0; i < matrix.length; i++)
- {
- matrix[i] = IntUtils.clone(a.matrix[i]);
- }
-
- }
-
- /**
- * create the mxn zero matrix
- */
- private GF2Matrix(int m, int n)
- {
- if ((n <= 0) || (m <= 0))
- {
- throw new ArithmeticException("size of matrix is non-positive");
- }
-
- assignZeroMatrix(m, n);
- }
-
- /**
- * Create the mxn zero matrix.
- *
- * @param m number of rows
- * @param n number of columns
- */
- private void assignZeroMatrix(int m, int n)
- {
- numRows = m;
- numColumns = n;
- length = (n + 31) >>> 5;
- matrix = new int[numRows][length];
- for (int i = 0; i < numRows; i++)
- {
- for (int j = 0; j < length; j++)
- {
- matrix[i][j] = 0;
- }
- }
- }
-
- /**
- * Create the mxn unit matrix.
- *
- * @param n number of rows (and columns)
- */
- private void assignUnitMatrix(int n)
- {
- numRows = n;
- numColumns = n;
- length = (n + 31) >>> 5;
- matrix = new int[numRows][length];
- for (int i = 0; i < numRows; i++)
- {
- for (int j = 0; j < length; j++)
- {
- matrix[i][j] = 0;
- }
- }
- for (int i = 0; i < numRows; i++)
- {
- int rest = i & 0x1f;
- matrix[i][i >>> 5] = 1 << rest;
- }
- }
-
- /**
- * Create a nxn random lower triangular matrix.
- *
- * @param n number of rows (and columns)
- * @param sr source of randomness
- */
- private void assignRandomLowerTriangularMatrix(int n, SecureRandom sr)
- {
- numRows = n;
- numColumns = n;
- length = (n + 31) >>> 5;
- matrix = new int[numRows][length];
- for (int i = 0; i < numRows; i++)
- {
- int q = i >>> 5;
- int r = i & 0x1f;
- int s = 31 - r;
- r = 1 << r;
- for (int j = 0; j < q; j++)
- {
- matrix[i][j] = sr.nextInt();
- }
- matrix[i][q] = (sr.nextInt() >>> s) | r;
- for (int j = q + 1; j < length; j++)
- {
- matrix[i][j] = 0;
- }
-
- }
-
- }
-
- /**
- * Create a nxn random upper triangular matrix.
- *
- * @param n number of rows (and columns)
- * @param sr source of randomness
- */
- private void assignRandomUpperTriangularMatrix(int n, SecureRandom sr)
- {
- numRows = n;
- numColumns = n;
- length = (n + 31) >>> 5;
- matrix = new int[numRows][length];
- int rest = n & 0x1f;
- int help;
- if (rest == 0)
- {
- help = 0xffffffff;
- }
- else
- {
- help = (1 << rest) - 1;
- }
- for (int i = 0; i < numRows; i++)
- {
- int q = i >>> 5;
- int r = i & 0x1f;
- int s = r;
- r = 1 << r;
- for (int j = 0; j < q; j++)
- {
- matrix[i][j] = 0;
- }
- matrix[i][q] = (sr.nextInt() << s) | r;
- for (int j = q + 1; j < length; j++)
- {
- matrix[i][j] = sr.nextInt();
- }
- matrix[i][length - 1] &= help;
- }
-
- }
-
- /**
- * Create an nxn random regular matrix.
- *
- * @param n number of rows (and columns)
- * @param sr source of randomness
- */
- private void assignRandomRegularMatrix(int n, SecureRandom sr)
- {
- numRows = n;
- numColumns = n;
- length = (n + 31) >>> 5;
- matrix = new int[numRows][length];
- GF2Matrix lm = new GF2Matrix(n, Matrix.MATRIX_TYPE_RANDOM_LT, sr);
- GF2Matrix um = new GF2Matrix(n, Matrix.MATRIX_TYPE_RANDOM_UT, sr);
- GF2Matrix rm = (GF2Matrix)lm.rightMultiply(um);
- Permutation perm = new Permutation(n, sr);
- int[] p = perm.getVector();
- for (int i = 0; i < n; i++)
- {
- System.arraycopy(rm.matrix[i], 0, matrix[p[i]], 0, length);
- }
- }
-
- /**
- * Create a nxn random regular matrix and its inverse.
- *
- * @param n number of rows (and columns)
- * @param sr source of randomness
- * @return the created random regular matrix and its inverse
- */
- public static GF2Matrix[] createRandomRegularMatrixAndItsInverse(int n,
- SecureRandom sr)
- {
-
- GF2Matrix[] result = new GF2Matrix[2];
-
- // ------------------------------------
- // First part: create regular matrix
- // ------------------------------------
-
- // ------
- int length = (n + 31) >> 5;
- GF2Matrix lm = new GF2Matrix(n, Matrix.MATRIX_TYPE_RANDOM_LT, sr);
- GF2Matrix um = new GF2Matrix(n, Matrix.MATRIX_TYPE_RANDOM_UT, sr);
- GF2Matrix rm = (GF2Matrix)lm.rightMultiply(um);
- Permutation p = new Permutation(n, sr);
- int[] pVec = p.getVector();
-
- int[][] matrix = new int[n][length];
- for (int i = 0; i < n; i++)
- {
- System.arraycopy(rm.matrix[pVec[i]], 0, matrix[i], 0, length);
- }
-
- result[0] = new GF2Matrix(n, matrix);
-
- // ------------------------------------
- // Second part: create inverse matrix
- // ------------------------------------
-
- // inverse to lm
- GF2Matrix invLm = new GF2Matrix(n, Matrix.MATRIX_TYPE_UNIT);
- for (int i = 0; i < n; i++)
- {
- int rest = i & 0x1f;
- int q = i >>> 5;
- int r = 1 << rest;
- for (int j = i + 1; j < n; j++)
- {
- int b = (lm.matrix[j][q]) & r;
- if (b != 0)
- {
- for (int k = 0; k <= q; k++)
- {
- invLm.matrix[j][k] ^= invLm.matrix[i][k];
- }
- }
- }
- }
- // inverse to um
- GF2Matrix invUm = new GF2Matrix(n, Matrix.MATRIX_TYPE_UNIT);
- for (int i = n - 1; i >= 0; i--)
- {
- int rest = i & 0x1f;
- int q = i >>> 5;
- int r = 1 << rest;
- for (int j = i - 1; j >= 0; j--)
- {
- int b = (um.matrix[j][q]) & r;
- if (b != 0)
- {
- for (int k = q; k < length; k++)
- {
- invUm.matrix[j][k] ^= invUm.matrix[i][k];
- }
- }
- }
- }
-
- // inverse matrix
- result[1] = (GF2Matrix)invUm.rightMultiply(invLm.rightMultiply(p));
-
- return result;
- }
-
- /**
- * @return the array keeping the matrix elements
- */
- public int[][] getIntArray()
- {
- return matrix;
- }
-
- /**
- * @return the length of each array representing a row of this matrix
- */
- public int getLength()
- {
- return length;
- }
-
- /**
- * Return the row of this matrix with the given index.
- *
- * @param index the index
- * @return the row of this matrix with the given index
- */
- public int[] getRow(int index)
- {
- return matrix[index];
- }
-
- /**
- * Returns encoded matrix, i.e., this matrix in byte array form
- *
- * @return the encoded matrix
- */
- public byte[] getEncoded()
- {
- int n = (numColumns + 7) >>> 3;
- n *= numRows;
- n += 8;
- byte[] enc = new byte[n];
-
- LittleEndianConversions.I2OSP(numRows, enc, 0);
- LittleEndianConversions.I2OSP(numColumns, enc, 4);
-
- // number of "full" integer
- int q = numColumns >>> 5;
- // number of bits in non-full integer
- int r = numColumns & 0x1f;
-
- int count = 8;
- for (int i = 0; i < numRows; i++)
- {
- for (int j = 0; j < q; j++, count += 4)
- {
- LittleEndianConversions.I2OSP(matrix[i][j], enc, count);
- }
- for (int j = 0; j < r; j += 8)
- {
- enc[count++] = (byte)((matrix[i][q] >>> j) & 0xff);
- }
-
- }
- return enc;
- }
-
-
- /**
- * Returns the percentage of the number of "ones" in this matrix.
- *
- * @return the Hamming weight of this matrix (as a ratio).
- */
- public double getHammingWeight()
- {
- double counter = 0.0;
- double elementCounter = 0.0;
- int rest = numColumns & 0x1f;
- int d;
- if (rest == 0)
- {
- d = length;
- }
- else
- {
- d = length - 1;
- }
-
- for (int i = 0; i < numRows; i++)
- {
-
- for (int j = 0; j < d; j++)
- {
- int a = matrix[i][j];
- for (int k = 0; k < 32; k++)
- {
- int b = (a >>> k) & 1;
- counter = counter + b;
- elementCounter = elementCounter + 1;
- }
- }
- int a = matrix[i][length - 1];
- for (int k = 0; k < rest; k++)
- {
- int b = (a >>> k) & 1;
- counter = counter + b;
- elementCounter = elementCounter + 1;
- }
- }
-
- return counter / elementCounter;
- }
-
- /**
- * Check if this is the zero matrix (i.e., all entries are zero).
- *
- * @return <tt>true</tt> if this is the zero matrix
- */
- public boolean isZero()
- {
- for (int i = 0; i < numRows; i++)
- {
- for (int j = 0; j < length; j++)
- {
- if (matrix[i][j] != 0)
- {
- return false;
- }
- }
- }
- return true;
- }
-
- /**
- * Get the quadratic submatrix of this matrix consisting of the leftmost
- * <tt>numRows</tt> columns.
- *
- * @return the <tt>(numRows x numRows)</tt> submatrix
- */
- public GF2Matrix getLeftSubMatrix()
- {
- if (numColumns <= numRows)
- {
- throw new ArithmeticException("empty submatrix");
- }
- int length = (numRows + 31) >> 5;
- int[][] result = new int[numRows][length];
- int bitMask = (1 << (numRows & 0x1f)) - 1;
- if (bitMask == 0)
- {
- bitMask = -1;
- }
- for (int i = numRows - 1; i >= 0; i--)
- {
- System.arraycopy(matrix[i], 0, result[i], 0, length);
- result[i][length - 1] &= bitMask;
- }
- return new GF2Matrix(numRows, result);
- }
-
- /**
- * Compute the full form matrix <tt>(this | Id)</tt> from this matrix in
- * left compact form, where <tt>Id</tt> is the <tt>k x k</tt> identity
- * matrix and <tt>k</tt> is the number of rows of this matrix.
- *
- * @return <tt>(this | Id)</tt>
- */
- public GF2Matrix extendLeftCompactForm()
- {
- int newNumColumns = numColumns + numRows;
- GF2Matrix result = new GF2Matrix(numRows, newNumColumns);
-
- int ind = numRows - 1 + numColumns;
- for (int i = numRows - 1; i >= 0; i--, ind--)
- {
- // copy this matrix to first columns
- System.arraycopy(matrix[i], 0, result.matrix[i], 0, length);
- // store the identity in last columns
- result.matrix[i][ind >> 5] |= 1 << (ind & 0x1f);
- }
-
- return result;
- }
-
- /**
- * Get the submatrix of this matrix consisting of the rightmost
- * <tt>numColumns-numRows</tt> columns.
- *
- * @return the <tt>(numRows x (numColumns-numRows))</tt> submatrix
- */
- public GF2Matrix getRightSubMatrix()
- {
- if (numColumns <= numRows)
- {
- throw new ArithmeticException("empty submatrix");
- }
-
- int q = numRows >> 5;
- int r = numRows & 0x1f;
-
- GF2Matrix result = new GF2Matrix(numRows, numColumns - numRows);
-
- for (int i = numRows - 1; i >= 0; i--)
- {
- // if words have to be shifted
- if (r != 0)
- {
- int ind = q;
- // process all but last word
- for (int j = 0; j < result.length - 1; j++)
- {
- // shift to correct position
- result.matrix[i][j] = (matrix[i][ind++] >>> r)
- | (matrix[i][ind] << (32 - r));
- }
- // process last word
- result.matrix[i][result.length - 1] = matrix[i][ind++] >>> r;
- if (ind < length)
- {
- result.matrix[i][result.length - 1] |= matrix[i][ind] << (32 - r);
- }
- }
- else
- {
- // no shifting necessary
- System.arraycopy(matrix[i], q, result.matrix[i], 0,
- result.length);
- }
- }
- return result;
- }
-
- /**
- * Compute the full form matrix <tt>(Id | this)</tt> from this matrix in
- * right compact form, where <tt>Id</tt> is the <tt>k x k</tt> identity
- * matrix and <tt>k</tt> is the number of rows of this matrix.
- *
- * @return <tt>(Id | this)</tt>
- */
- public GF2Matrix extendRightCompactForm()
- {
- GF2Matrix result = new GF2Matrix(numRows, numRows + numColumns);
-
- int q = numRows >> 5;
- int r = numRows & 0x1f;
-
- for (int i = numRows - 1; i >= 0; i--)
- {
- // store the identity in first columns
- result.matrix[i][i >> 5] |= 1 << (i & 0x1f);
-
- // copy this matrix to last columns
-
- // if words have to be shifted
- if (r != 0)
- {
- int ind = q;
- // process all but last word
- for (int j = 0; j < length - 1; j++)
- {
- // obtain matrix word
- int mw = matrix[i][j];
- // shift to correct position
- result.matrix[i][ind++] |= mw << r;
- result.matrix[i][ind] |= mw >>> (32 - r);
- }
- // process last word
- int mw = matrix[i][length - 1];
- result.matrix[i][ind++] |= mw << r;
- if (ind < result.length)
- {
- result.matrix[i][ind] |= mw >>> (32 - r);
- }
- }
- else
- {
- // no shifting necessary
- System.arraycopy(matrix[i], 0, result.matrix[i], q, length);
- }
- }
-
- return result;
- }
-
- /**
- * Compute the transpose of this matrix.
- *
- * @return <tt>(this)<sup>T</sup></tt>
- */
- public Matrix computeTranspose()
- {
- int[][] result = new int[numColumns][(numRows + 31) >>> 5];
- for (int i = 0; i < numRows; i++)
- {
- for (int j = 0; j < numColumns; j++)
- {
- int qs = j >>> 5;
- int rs = j & 0x1f;
- int b = (matrix[i][qs] >>> rs) & 1;
- int qt = i >>> 5;
- int rt = i & 0x1f;
- if (b == 1)
- {
- result[j][qt] |= 1 << rt;
- }
- }
- }
-
- return new GF2Matrix(numRows, result);
- }
-
- /**
- * Compute the inverse of this matrix.
- *
- * @return the inverse of this matrix (newly created).
- * @throws ArithmeticException if this matrix is not invertible.
- */
- public Matrix computeInverse()
- {
- if (numRows != numColumns)
- {
- throw new ArithmeticException("Matrix is not invertible.");
- }
-
- // clone this matrix
- int[][] tmpMatrix = new int[numRows][length];
- for (int i = numRows - 1; i >= 0; i--)
- {
- tmpMatrix[i] = IntUtils.clone(matrix[i]);
- }
-
- // initialize inverse matrix as unit matrix
- int[][] invMatrix = new int[numRows][length];
- for (int i = numRows - 1; i >= 0; i--)
- {
- int q = i >> 5;
- int r = i & 0x1f;
- invMatrix[i][q] = 1 << r;
- }
-
- // simultaneously compute Gaussian reduction of tmpMatrix and unit
- // matrix
- for (int i = 0; i < numRows; i++)
- {
- // i = q * 32 + (i mod 32)
- int q = i >> 5;
- int bitMask = 1 << (i & 0x1f);
- // if diagonal element is zero
- if ((tmpMatrix[i][q] & bitMask) == 0)
- {
- boolean foundNonZero = false;
- // find a non-zero element in the same column
- for (int j = i + 1; j < numRows; j++)
- {
- if ((tmpMatrix[j][q] & bitMask) != 0)
- {
- // found it, swap rows ...
- foundNonZero = true;
- swapRows(tmpMatrix, i, j);
- swapRows(invMatrix, i, j);
- // ... and quit searching
- j = numRows;
- continue;
- }
- }
- // if no non-zero element was found ...
- if (!foundNonZero)
- {
- // ... the matrix is not invertible
- throw new ArithmeticException("Matrix is not invertible.");
- }
- }
-
- // normalize all but i-th row
- for (int j = numRows - 1; j >= 0; j--)
- {
- if ((j != i) && ((tmpMatrix[j][q] & bitMask) != 0))
- {
- addToRow(tmpMatrix[i], tmpMatrix[j], q);
- addToRow(invMatrix[i], invMatrix[j], 0);
- }
- }
- }
-
- return new GF2Matrix(numColumns, invMatrix);
- }
-
- /**
- * Compute the product of a permutation matrix (which is generated from an
- * n-permutation) and this matrix.
- *
- * @param p the permutation
- * @return {@link GF2Matrix} <tt>P*this</tt>
- */
- public Matrix leftMultiply(Permutation p)
- {
- int[] pVec = p.getVector();
- if (pVec.length != numRows)
- {
- throw new ArithmeticException("length mismatch");
- }
-
- int[][] result = new int[numRows][];
-
- for (int i = numRows - 1; i >= 0; i--)
- {
- result[i] = IntUtils.clone(matrix[pVec[i]]);
- }
-
- return new GF2Matrix(numRows, result);
- }
-
- /**
- * compute product a row vector and this matrix
- *
- * @param vec a vector over GF(2)
- * @return Vector product a*matrix
- */
- public Vector leftMultiply(Vector vec)
- {
-
- if (!(vec instanceof GF2Vector))
- {
- throw new ArithmeticException("vector is not defined over GF(2)");
- }
-
- if (vec.length != numRows)
- {
- throw new ArithmeticException("length mismatch");
- }
-
- int[] v = ((GF2Vector)vec).getVecArray();
- int[] res = new int[length];
-
- int q = numRows >> 5;
- int r = 1 << (numRows & 0x1f);
-
- // compute scalar products with full words of vector
- int row = 0;
- for (int i = 0; i < q; i++)
- {
- int bitMask = 1;
- do
- {
- int b = v[i] & bitMask;
- if (b != 0)
- {
- for (int j = 0; j < length; j++)
- {
- res[j] ^= matrix[row][j];
- }
- }
- row++;
- bitMask <<= 1;
- }
- while (bitMask != 0);
- }
-
- // compute scalar products with last word of vector
- int bitMask = 1;
- while (bitMask != r)
- {
- int b = v[q] & bitMask;
- if (b != 0)
- {
- for (int j = 0; j < length; j++)
- {
- res[j] ^= matrix[row][j];
- }
- }
- row++;
- bitMask <<= 1;
- }
-
- return new GF2Vector(res, numColumns);
- }
-
- /**
- * Compute the product of the matrix <tt>(this | Id)</tt> and a column
- * vector, where <tt>Id</tt> is a <tt>(numRows x numRows)</tt> unit
- * matrix.
- *
- * @param vec the vector over GF(2)
- * @return <tt>(this | Id)*vector</tt>
- */
- public Vector leftMultiplyLeftCompactForm(Vector vec)
- {
- if (!(vec instanceof GF2Vector))
- {
- throw new ArithmeticException("vector is not defined over GF(2)");
- }
-
- if (vec.length != numRows)
- {
- throw new ArithmeticException("length mismatch");
- }
-
- int[] v = ((GF2Vector)vec).getVecArray();
- int[] res = new int[(numRows + numColumns + 31) >>> 5];
-
- // process full words of vector
- int words = numRows >>> 5;
- int row = 0;
- for (int i = 0; i < words; i++)
- {
- int bitMask = 1;
- do
- {
- int b = v[i] & bitMask;
- if (b != 0)
- {
- // compute scalar product part
- for (int j = 0; j < length; j++)
- {
- res[j] ^= matrix[row][j];
- }
- // set last bit
- int q = (numColumns + row) >>> 5;
- int r = (numColumns + row) & 0x1f;
- res[q] |= 1 << r;
- }
- row++;
- bitMask <<= 1;
- }
- while (bitMask != 0);
- }
-
- // process last word of vector
- int rem = 1 << (numRows & 0x1f);
- int bitMask = 1;
- while (bitMask != rem)
- {
- int b = v[words] & bitMask;
- if (b != 0)
- {
- // compute scalar product part
- for (int j = 0; j < length; j++)
- {
- res[j] ^= matrix[row][j];
- }
- // set last bit
- int q = (numColumns + row) >>> 5;
- int r = (numColumns + row) & 0x1f;
- res[q] |= 1 << r;
- }
- row++;
- bitMask <<= 1;
- }
-
- return new GF2Vector(res, numRows + numColumns);
- }
-
- /**
- * Compute the product of this matrix and a matrix A over GF(2).
- *
- * @param mat a matrix A over GF(2)
- * @return matrix product <tt>this*matrixA</tt>
- */
- public Matrix rightMultiply(Matrix mat)
- {
- if (!(mat instanceof GF2Matrix))
- {
- throw new ArithmeticException("matrix is not defined over GF(2)");
- }
-
- if (mat.numRows != numColumns)
- {
- throw new ArithmeticException("length mismatch");
- }
-
- GF2Matrix a = (GF2Matrix)mat;
- GF2Matrix result = new GF2Matrix(numRows, mat.numColumns);
-
- int d;
- int rest = numColumns & 0x1f;
- if (rest == 0)
- {
- d = length;
- }
- else
- {
- d = length - 1;
- }
- for (int i = 0; i < numRows; i++)
- {
- int count = 0;
- for (int j = 0; j < d; j++)
- {
- int e = matrix[i][j];
- for (int h = 0; h < 32; h++)
- {
- int b = e & (1 << h);
- if (b != 0)
- {
- for (int g = 0; g < a.length; g++)
- {
- result.matrix[i][g] ^= a.matrix[count][g];
- }
- }
- count++;
- }
- }
- int e = matrix[i][length - 1];
- for (int h = 0; h < rest; h++)
- {
- int b = e & (1 << h);
- if (b != 0)
- {
- for (int g = 0; g < a.length; g++)
- {
- result.matrix[i][g] ^= a.matrix[count][g];
- }
- }
- count++;
- }
-
- }
-
- return result;
- }
-
- /**
- * Compute the product of this matrix and a permutation matrix which is
- * generated from an n-permutation.
- *
- * @param p the permutation
- * @return {@link GF2Matrix} <tt>this*P</tt>
- */
- public Matrix rightMultiply(Permutation p)
- {
-
- int[] pVec = p.getVector();
- if (pVec.length != numColumns)
- {
- throw new ArithmeticException("length mismatch");
- }
-
- GF2Matrix result = new GF2Matrix(numRows, numColumns);
-
- for (int i = numColumns - 1; i >= 0; i--)
- {
- int q = i >>> 5;
- int r = i & 0x1f;
- int pq = pVec[i] >>> 5;
- int pr = pVec[i] & 0x1f;
- for (int j = numRows - 1; j >= 0; j--)
- {
- result.matrix[j][q] |= ((matrix[j][pq] >>> pr) & 1) << r;
- }
- }
-
- return result;
- }
-
- /**
- * Compute the product of this matrix and the given column vector.
- *
- * @param vec the vector over GF(2)
- * @return <tt>this*vector</tt>
- */
- public Vector rightMultiply(Vector vec)
- {
- if (!(vec instanceof GF2Vector))
- {
- throw new ArithmeticException("vector is not defined over GF(2)");
- }
-
- if (vec.length != numColumns)
- {
- throw new ArithmeticException("length mismatch");
- }
-
- int[] v = ((GF2Vector)vec).getVecArray();
- int[] res = new int[(numRows + 31) >>> 5];
-
- for (int i = 0; i < numRows; i++)
- {
- // compute full word scalar products
- int help = 0;
- for (int j = 0; j < length; j++)
- {
- help ^= matrix[i][j] & v[j];
- }
- // compute single word scalar product
- int bitValue = 0;
- for (int j = 0; j < 32; j++)
- {
- bitValue ^= (help >>> j) & 1;
- }
- // set result bit
- if (bitValue == 1)
- {
- res[i >>> 5] |= 1 << (i & 0x1f);
- }
- }
-
- return new GF2Vector(res, numRows);
- }
-
- /**
- * Compute the product of the matrix <tt>(Id | this)</tt> and a column
- * vector, where <tt>Id</tt> is a <tt>(numRows x numRows)</tt> unit
- * matrix.
- *
- * @param vec the vector over GF(2)
- * @return <tt>(Id | this)*vector</tt>
- */
- public Vector rightMultiplyRightCompactForm(Vector vec)
- {
- if (!(vec instanceof GF2Vector))
- {
- throw new ArithmeticException("vector is not defined over GF(2)");
- }
-
- if (vec.length != numColumns + numRows)
- {
- throw new ArithmeticException("length mismatch");
- }
-
- int[] v = ((GF2Vector)vec).getVecArray();
- int[] res = new int[(numRows + 31) >>> 5];
-
- int q = numRows >> 5;
- int r = numRows & 0x1f;
-
- // for all rows
- for (int i = 0; i < numRows; i++)
- {
- // get vector bit
- int help = (v[i >> 5] >>> (i & 0x1f)) & 1;
-
- // compute full word scalar products
- int vInd = q;
- // if words have to be shifted
- if (r != 0)
- {
- int vw = 0;
- // process all but last word
- for (int j = 0; j < length - 1; j++)
- {
- // shift to correct position
- vw = (v[vInd++] >>> r) | (v[vInd] << (32 - r));
- help ^= matrix[i][j] & vw;
- }
- // process last word
- vw = v[vInd++] >>> r;
- if (vInd < v.length)
- {
- vw |= v[vInd] << (32 - r);
- }
- help ^= matrix[i][length - 1] & vw;
- }
- else
- {
- // no shifting necessary
- for (int j = 0; j < length; j++)
- {
- help ^= matrix[i][j] & v[vInd++];
- }
- }
-
- // compute single word scalar product
- int bitValue = 0;
- for (int j = 0; j < 32; j++)
- {
- bitValue ^= help & 1;
- help >>>= 1;
- }
-
- // set result bit
- if (bitValue == 1)
- {
- res[i >> 5] |= 1 << (i & 0x1f);
- }
- }
-
- return new GF2Vector(res, numRows);
- }
-
- /**
- * Compare this matrix with another object.
- *
- * @param other another object
- * @return the result of the comparison
- */
- public boolean equals(Object other)
- {
-
- if (!(other instanceof GF2Matrix))
- {
- return false;
- }
- GF2Matrix otherMatrix = (GF2Matrix)other;
-
- if ((numRows != otherMatrix.numRows)
- || (numColumns != otherMatrix.numColumns)
- || (length != otherMatrix.length))
- {
- return false;
- }
-
- for (int i = 0; i < numRows; i++)
- {
- if (!IntUtils.equals(matrix[i], otherMatrix.matrix[i]))
- {
- return false;
- }
- }
-
- return true;
- }
-
- /**
- * @return the hash code of this matrix
- */
- public int hashCode()
- {
- int hash = (numRows * 31 + numColumns) * 31 + length;
- for (int i = 0; i < numRows; i++)
- {
- hash = hash * 31 + matrix[i].hashCode();
- }
- return hash;
- }
-
- /**
- * @return a human readable form of the matrix
- */
- public String toString()
- {
- int rest = numColumns & 0x1f;
- int d;
- if (rest == 0)
- {
- d = length;
- }
- else
- {
- d = length - 1;
- }
-
- StringBuffer buf = new StringBuffer();
- for (int i = 0; i < numRows; i++)
- {
- buf.append(i + ": ");
- for (int j = 0; j < d; j++)
- {
- int a = matrix[i][j];
- for (int k = 0; k < 32; k++)
- {
- int b = (a >>> k) & 1;
- if (b == 0)
- {
- buf.append('0');
- }
- else
- {
- buf.append('1');
- }
- }
- buf.append(' ');
- }
- int a = matrix[i][length - 1];
- for (int k = 0; k < rest; k++)
- {
- int b = (a >>> k) & 1;
- if (b == 0)
- {
- buf.append('0');
- }
- else
- {
- buf.append('1');
- }
- }
- buf.append('\n');
- }
-
- return buf.toString();
- }
-
- /**
- * Swap two rows of the given matrix.
- *
- * @param matrix the matrix
- * @param first the index of the first row
- * @param second the index of the second row
- */
- private static void swapRows(int[][] matrix, int first, int second)
- {
- int[] tmp = matrix[first];
- matrix[first] = matrix[second];
- matrix[second] = tmp;
- }
-
- /**
- * Partially add one row to another.
- *
- * @param fromRow the addend
- * @param toRow the row to add to
- * @param startIndex the array index to start from
- */
- private static void addToRow(int[] fromRow, int[] toRow, int startIndex)
- {
- for (int i = toRow.length - 1; i >= startIndex; i--)
- {
- toRow[i] = fromRow[i] ^ toRow[i];
- }
- }
-
-}
diff --git a/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2Polynomial.java b/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2Polynomial.java
deleted file mode 100644
index 445a9ea..0000000
--- a/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2Polynomial.java
+++ /dev/null
@@ -1,2039 +0,0 @@
-package org.bouncycastle.pqc.math.linearalgebra;
-
-
-import java.math.BigInteger;
-import java.util.Random;
-
-
-/**
- * This class stores very long strings of bits and does some basic arithmetics.
- * It is used by <tt>GF2nField</tt>, <tt>GF2nPolynomialField</tt> and
- * <tt>GFnPolynomialElement</tt>.
- *
- * @see GF2nPolynomialElement
- * @see GF2nField
- */
-public class GF2Polynomial
-{
-
- // number of bits stored in this GF2Polynomial
- private int len;
-
- // number of int used in value
- private int blocks;
-
- // storage
- private int[] value;
-
- // Random source
- private static Random rand = new Random();
-
- // Lookup-Table for vectorMult: parity[a]= #1(a) mod 2 == 1
- private static final boolean[] parity = {false, true, true, false, true,
- false, false, true, true, false, false, true, false, true, true,
- false, true, false, false, true, false, true, true, false, false,
- true, true, false, true, false, false, true, true, false, false,
- true, false, true, true, false, false, true, true, false, true,
- false, false, true, false, true, true, false, true, false, false,
- true, true, false, false, true, false, true, true, false, true,
- false, false, true, false, true, true, false, false, true, true,
- false, true, false, false, true, false, true, true, false, true,
- false, false, true, true, false, false, true, false, true, true,
- false, false, true, true, false, true, false, false, true, true,
- false, false, true, false, true, true, false, true, false, false,
- true, false, true, true, false, false, true, true, false, true,
- false, false, true, true, false, false, true, false, true, true,
- false, false, true, true, false, true, false, false, true, false,
- true, true, false, true, false, false, true, true, false, false,
- true, false, true, true, false, false, true, true, false, true,
- false, false, true, true, false, false, true, false, true, true,
- false, true, false, false, true, false, true, true, false, false,
- true, true, false, true, false, false, true, false, true, true,
- false, true, false, false, true, true, false, false, true, false,
- true, true, false, true, false, false, true, false, true, true,
- false, false, true, true, false, true, false, false, true, true,
- false, false, true, false, true, true, false, false, true, true,
- false, true, false, false, true, false, true, true, false, true,
- false, false, true, true, false, false, true, false, true, true,
- false};
-
- // Lookup-Table for Squaring: squaringTable[a]=a^2
- private static final short[] squaringTable = {0x0000, 0x0001, 0x0004,
- 0x0005, 0x0010, 0x0011, 0x0014, 0x0015, 0x0040, 0x0041, 0x0044,
- 0x0045, 0x0050, 0x0051, 0x0054, 0x0055, 0x0100, 0x0101, 0x0104,
- 0x0105, 0x0110, 0x0111, 0x0114, 0x0115, 0x0140, 0x0141, 0x0144,
- 0x0145, 0x0150, 0x0151, 0x0154, 0x0155, 0x0400, 0x0401, 0x0404,
- 0x0405, 0x0410, 0x0411, 0x0414, 0x0415, 0x0440, 0x0441, 0x0444,
- 0x0445, 0x0450, 0x0451, 0x0454, 0x0455, 0x0500, 0x0501, 0x0504,
- 0x0505, 0x0510, 0x0511, 0x0514, 0x0515, 0x0540, 0x0541, 0x0544,
- 0x0545, 0x0550, 0x0551, 0x0554, 0x0555, 0x1000, 0x1001, 0x1004,
- 0x1005, 0x1010, 0x1011, 0x1014, 0x1015, 0x1040, 0x1041, 0x1044,
- 0x1045, 0x1050, 0x1051, 0x1054, 0x1055, 0x1100, 0x1101, 0x1104,
- 0x1105, 0x1110, 0x1111, 0x1114, 0x1115, 0x1140, 0x1141, 0x1144,
- 0x1145, 0x1150, 0x1151, 0x1154, 0x1155, 0x1400, 0x1401, 0x1404,
- 0x1405, 0x1410, 0x1411, 0x1414, 0x1415, 0x1440, 0x1441, 0x1444,
- 0x1445, 0x1450, 0x1451, 0x1454, 0x1455, 0x1500, 0x1501, 0x1504,
- 0x1505, 0x1510, 0x1511, 0x1514, 0x1515, 0x1540, 0x1541, 0x1544,
- 0x1545, 0x1550, 0x1551, 0x1554, 0x1555, 0x4000, 0x4001, 0x4004,
- 0x4005, 0x4010, 0x4011, 0x4014, 0x4015, 0x4040, 0x4041, 0x4044,
- 0x4045, 0x4050, 0x4051, 0x4054, 0x4055, 0x4100, 0x4101, 0x4104,
- 0x4105, 0x4110, 0x4111, 0x4114, 0x4115, 0x4140, 0x4141, 0x4144,
- 0x4145, 0x4150, 0x4151, 0x4154, 0x4155, 0x4400, 0x4401, 0x4404,
- 0x4405, 0x4410, 0x4411, 0x4414, 0x4415, 0x4440, 0x4441, 0x4444,
- 0x4445, 0x4450, 0x4451, 0x4454, 0x4455, 0x4500, 0x4501, 0x4504,
- 0x4505, 0x4510, 0x4511, 0x4514, 0x4515, 0x4540, 0x4541, 0x4544,
- 0x4545, 0x4550, 0x4551, 0x4554, 0x4555, 0x5000, 0x5001, 0x5004,
- 0x5005, 0x5010, 0x5011, 0x5014, 0x5015, 0x5040, 0x5041, 0x5044,
- 0x5045, 0x5050, 0x5051, 0x5054, 0x5055, 0x5100, 0x5101, 0x5104,
- 0x5105, 0x5110, 0x5111, 0x5114, 0x5115, 0x5140, 0x5141, 0x5144,
- 0x5145, 0x5150, 0x5151, 0x5154, 0x5155, 0x5400, 0x5401, 0x5404,
- 0x5405, 0x5410, 0x5411, 0x5414, 0x5415, 0x5440, 0x5441, 0x5444,
- 0x5445, 0x5450, 0x5451, 0x5454, 0x5455, 0x5500, 0x5501, 0x5504,
- 0x5505, 0x5510, 0x5511, 0x5514, 0x5515, 0x5540, 0x5541, 0x5544,
- 0x5545, 0x5550, 0x5551, 0x5554, 0x5555};
-
- // pre-computed Bitmask for fast masking, bitMask[a]=0x1 << a
- private static final int[] bitMask = {0x00000001, 0x00000002, 0x00000004,
- 0x00000008, 0x00000010, 0x00000020, 0x00000040, 0x00000080,
- 0x00000100, 0x00000200, 0x00000400, 0x00000800, 0x00001000,
- 0x00002000, 0x00004000, 0x00008000, 0x00010000, 0x00020000,
- 0x00040000, 0x00080000, 0x00100000, 0x00200000, 0x00400000,
- 0x00800000, 0x01000000, 0x02000000, 0x04000000, 0x08000000,
- 0x10000000, 0x20000000, 0x40000000, 0x80000000, 0x00000000};
-
- // pre-computed Bitmask for fast masking, rightMask[a]=0xffffffff >>> (32-a)
- private static final int[] reverseRightMask = {0x00000000, 0x00000001,
- 0x00000003, 0x00000007, 0x0000000f, 0x0000001f, 0x0000003f,
- 0x0000007f, 0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff,
- 0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff, 0x0000ffff,
- 0x0001ffff, 0x0003ffff, 0x0007ffff, 0x000fffff, 0x001fffff,
- 0x003fffff, 0x007fffff, 0x00ffffff, 0x01ffffff, 0x03ffffff,
- 0x07ffffff, 0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff,
- 0xffffffff};
-
- /**
- * Creates a new GF2Polynomial of the given <i>length</i> and value zero.
- *
- * @param length the desired number of bits to store
- */
- public GF2Polynomial(int length)
- {
- int l = length;
- if (l < 1)
- {
- l = 1;
- }
- blocks = ((l - 1) >> 5) + 1;
- value = new int[blocks];
- len = l;
- }
-
- /**
- * Creates a new GF2Polynomial of the given <i>length</i> and random value.
- *
- * @param length the desired number of bits to store
- * @param rand SecureRandom to use for randomization
- */
- public GF2Polynomial(int length, Random rand)
- {
- int l = length;
- if (l < 1)
- {
- l = 1;
- }
- blocks = ((l - 1) >> 5) + 1;
- value = new int[blocks];
- len = l;
- randomize(rand);
- }
-
- /**
- * Creates a new GF2Polynomial of the given <i>length</i> and value
- * selected by <i>value</i>:
- * <UL>
- * <LI>ZERO</LI>
- * <LI>ONE</LI>
- * <LI>RANDOM</LI>
- * <LI>X</LI>
- * <LI>ALL</LI>
- * </UL>
- *
- * @param length the desired number of bits to store
- * @param value the value described by a String
- */
- public GF2Polynomial(int length, String value)
- {
- int l = length;
- if (l < 1)
- {
- l = 1;
- }
- blocks = ((l - 1) >> 5) + 1;
- this.value = new int[blocks];
- len = l;
- if (value.equalsIgnoreCase("ZERO"))
- {
- assignZero();
- }
- else if (value.equalsIgnoreCase("ONE"))
- {
- assignOne();
- }
- else if (value.equalsIgnoreCase("RANDOM"))
- {
- randomize();
- }
- else if (value.equalsIgnoreCase("X"))
- {
- assignX();
- }
- else if (value.equalsIgnoreCase("ALL"))
- {
- assignAll();
- }
- else
- {
- throw new IllegalArgumentException(
- "Error: GF2Polynomial was called using " + value
- + " as value!");
- }
-
- }
-
- /**
- * Creates a new GF2Polynomial of the given <i>length</i> using the given
- * int[]. LSB is contained in bs[0].
- *
- * @param length the desired number of bits to store
- * @param bs contains the desired value, LSB in bs[0]
- */
- public GF2Polynomial(int length, int[] bs)
- {
- int leng = length;
- if (leng < 1)
- {
- leng = 1;
- }
- blocks = ((leng - 1) >> 5) + 1;
- value = new int[blocks];
- len = leng;
- int l = Math.min(blocks, bs.length);
- System.arraycopy(bs, 0, value, 0, l);
- zeroUnusedBits();
- }
-
- /**
- * Creates a new GF2Polynomial by converting the given byte[] <i>os</i>
- * according to 1363 and using the given <i>length</i>.
- *
- * @param length the intended length of this polynomial
- * @param os the octet string to assign to this polynomial
- * @see "P1363 5.5.2 p22f, OS2BSP"
- */
- public GF2Polynomial(int length, byte[] os)
- {
- int l = length;
- if (l < 1)
- {
- l = 1;
- }
- blocks = ((l - 1) >> 5) + 1;
- value = new int[blocks];
- len = l;
- int i, m;
- int k = Math.min(((os.length - 1) >> 2) + 1, blocks);
- for (i = 0; i < k - 1; i++)
- {
- m = os.length - (i << 2) - 1;
- value[i] = (os[m]) & 0x000000ff;
- value[i] |= (os[m - 1] << 8) & 0x0000ff00;
- value[i] |= (os[m - 2] << 16) & 0x00ff0000;
- value[i] |= (os[m - 3] << 24) & 0xff000000;
- }
- i = k - 1;
- m = os.length - (i << 2) - 1;
- value[i] = os[m] & 0x000000ff;
- if (m > 0)
- {
- value[i] |= (os[m - 1] << 8) & 0x0000ff00;
- }
- if (m > 1)
- {
- value[i] |= (os[m - 2] << 16) & 0x00ff0000;
- }
- if (m > 2)
- {
- value[i] |= (os[m - 3] << 24) & 0xff000000;
- }
- zeroUnusedBits();
- reduceN();
- }
-
- /**
- * Creates a new GF2Polynomial by converting the given FlexiBigInt <i>bi</i>
- * according to 1363 and using the given <i>length</i>.
- *
- * @param length the intended length of this polynomial
- * @param bi the FlexiBigInt to assign to this polynomial
- * @see "P1363 5.5.1 p22, I2BSP"
- */
- public GF2Polynomial(int length, BigInteger bi)
- {
- int l = length;
- if (l < 1)
- {
- l = 1;
- }
- blocks = ((l - 1) >> 5) + 1;
- value = new int[blocks];
- len = l;
- int i;
- byte[] val = bi.toByteArray();
- if (val[0] == 0)
- {
- byte[] dummy = new byte[val.length - 1];
- System.arraycopy(val, 1, dummy, 0, dummy.length);
- val = dummy;
- }
- int ov = val.length & 0x03;
- int k = ((val.length - 1) >> 2) + 1;
- for (i = 0; i < ov; i++)
- {
- value[k - 1] |= (val[i] & 0x000000ff) << ((ov - 1 - i) << 3);
- }
- int m = 0;
- for (i = 0; i <= (val.length - 4) >> 2; i++)
- {
- m = val.length - 1 - (i << 2);
- value[i] = (val[m]) & 0x000000ff;
- value[i] |= ((val[m - 1]) << 8) & 0x0000ff00;
- value[i] |= ((val[m - 2]) << 16) & 0x00ff0000;
- value[i] |= ((val[m - 3]) << 24) & 0xff000000;
- }
- if ((len & 0x1f) != 0)
- {
- value[blocks - 1] &= reverseRightMask[len & 0x1f];
- }
- reduceN();
- }
-
- /**
- * Creates a new GF2Polynomial by cloneing the given GF2Polynomial <i>b</i>.
- *
- * @param b the GF2Polynomial to clone
- */
- public GF2Polynomial(GF2Polynomial b)
- {
- len = b.len;
- blocks = b.blocks;
- value = IntUtils.clone(b.value);
- }
-
- /**
- * @return a copy of this GF2Polynomial
- */
- public Object clone()
- {
- return new GF2Polynomial(this);
- }
-
- /**
- * Returns the length of this GF2Polynomial. The length can be greater than
- * the degree. To get the degree call reduceN() before calling getLength().
- *
- * @return the length of this GF2Polynomial
- */
- public int getLength()
- {
- return len;
- }
-
- /**
- * Returns the value of this GF2Polynomial in an int[].
- *
- * @return the value of this GF2Polynomial in a new int[], LSB in int[0]
- */
- public int[] toIntegerArray()
- {
- int[] result;
- result = new int[blocks];
- System.arraycopy(value, 0, result, 0, blocks);
- return result;
- }
-
- /**
- * Returns a string representing this GF2Polynomials value using hexadecimal
- * or binary radix in MSB-first order.
- *
- * @param radix the radix to use (2 or 16, otherwise 2 is used)
- * @return a String representing this GF2Polynomials value.
- */
- public String toString(int radix)
- {
- final char[] HEX_CHARS = {'0', '1', '2', '3', '4', '5', '6', '7', '8',
- '9', 'a', 'b', 'c', 'd', 'e', 'f'};
- final String[] BIN_CHARS = {"0000", "0001", "0010", "0011", "0100",
- "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100",
- "1101", "1110", "1111"};
- String res;
- int i;
- res = new String();
- if (radix == 16)
- {
- for (i = blocks - 1; i >= 0; i--)
- {
- res += HEX_CHARS[(value[i] >>> 28) & 0x0f];
- res += HEX_CHARS[(value[i] >>> 24) & 0x0f];
- res += HEX_CHARS[(value[i] >>> 20) & 0x0f];
- res += HEX_CHARS[(value[i] >>> 16) & 0x0f];
- res += HEX_CHARS[(value[i] >>> 12) & 0x0f];
- res += HEX_CHARS[(value[i] >>> 8) & 0x0f];
- res += HEX_CHARS[(value[i] >>> 4) & 0x0f];
- res += HEX_CHARS[(value[i]) & 0x0f];
- res += " ";
- }
- }
- else
- {
- for (i = blocks - 1; i >= 0; i--)
- {
- res += BIN_CHARS[(value[i] >>> 28) & 0x0f];
- res += BIN_CHARS[(value[i] >>> 24) & 0x0f];
- res += BIN_CHARS[(value[i] >>> 20) & 0x0f];
- res += BIN_CHARS[(value[i] >>> 16) & 0x0f];
- res += BIN_CHARS[(value[i] >>> 12) & 0x0f];
- res += BIN_CHARS[(value[i] >>> 8) & 0x0f];
- res += BIN_CHARS[(value[i] >>> 4) & 0x0f];
- res += BIN_CHARS[(value[i]) & 0x0f];
- res += " ";
- }
- }
- return res;
- }
-
- /**
- * Converts this polynomial to a byte[] (octet string) according to 1363.
- *
- * @return a byte[] representing the value of this polynomial
- * @see "P1363 5.5.2 p22f, BS2OSP"
- */
- public byte[] toByteArray()
- {
- int k = ((len - 1) >> 3) + 1;
- int ov = k & 0x03;
- int m;
- byte[] res = new byte[k];
- int i;
- for (i = 0; i < (k >> 2); i++)
- {
- m = k - (i << 2) - 1;
- res[m] = (byte)((value[i] & 0x000000ff));
- res[m - 1] = (byte)((value[i] & 0x0000ff00) >>> 8);
- res[m - 2] = (byte)((value[i] & 0x00ff0000) >>> 16);
- res[m - 3] = (byte)((value[i] & 0xff000000) >>> 24);
- }
- for (i = 0; i < ov; i++)
- {
- m = (ov - i - 1) << 3;
- res[i] = (byte)((value[blocks - 1] & (0x000000ff << m)) >>> m);
- }
- return res;
- }
-
- /**
- * Converts this polynomial to an integer according to 1363.
- *
- * @return a FlexiBigInt representing the value of this polynomial
- * @see "P1363 5.5.1 p22, BS2IP"
- */
- public BigInteger toFlexiBigInt()
- {
- if (len == 0 || isZero())
- {
- return new BigInteger(0, new byte[0]);
- }
- return new BigInteger(1, toByteArray());
- }
-
- /**
- * Sets the LSB to 1 and all other to 0, assigning 'one' to this
- * GF2Polynomial.
- */
- public void assignOne()
- {
- int i;
- for (i = 1; i < blocks; i++)
- {
- value[i] = 0x00;
- }
- value[0] = 0x01;
- }
-
- /**
- * Sets Bit 1 to 1 and all other to 0, assigning 'x' to this GF2Polynomial.
- */
- public void assignX()
- {
- int i;
- for (i = 1; i < blocks; i++)
- {
- value[i] = 0x00;
- }
- value[0] = 0x02;
- }
-
- /**
- * Sets all Bits to 1.
- */
- public void assignAll()
- {
- int i;
- for (i = 0; i < blocks; i++)
- {
- value[i] = 0xffffffff;
- }
- zeroUnusedBits();
- }
-
- /**
- * Resets all bits to zero.
- */
- public void assignZero()
- {
- int i;
- for (i = 0; i < blocks; i++)
- {
- value[i] = 0x00;
- }
- }
-
- /**
- * Fills all len bits of this GF2Polynomial with random values.
- */
- public void randomize()
- {
- int i;
- for (i = 0; i < blocks; i++)
- {
- value[i] = rand.nextInt();
- }
- zeroUnusedBits();
- }
-
- /**
- * Fills all len bits of this GF2Polynomial with random values using the
- * specified source of randomness.
- *
- * @param rand the source of randomness
- */
- public void randomize(Random rand)
- {
- int i;
- for (i = 0; i < blocks; i++)
- {
- value[i] = rand.nextInt();
- }
- zeroUnusedBits();
- }
-
- /**
- * Returns true if two GF2Polynomials have the same size and value and thus
- * are equal.
- *
- * @param other the other GF2Polynomial
- * @return true if this GF2Polynomial equals <i>b</i> (<i>this</i> ==
- * <i>b</i>)
- */
- public boolean equals(Object other)
- {
- if (other == null || !(other instanceof GF2Polynomial))
- {
- return false;
- }
-
- GF2Polynomial otherPol = (GF2Polynomial)other;
-
- if (len != otherPol.len)
- {
- return false;
- }
- for (int i = 0; i < blocks; i++)
- {
- if (value[i] != otherPol.value[i])
- {
- return false;
- }
- }
- return true;
- }
-
- /**
- * @return the hash code of this polynomial
- */
- public int hashCode()
- {
- return len + value.hashCode();
- }
-
- /**
- * Tests if all bits equal zero.
- *
- * @return true if this GF2Polynomial equals 'zero' (<i>this</i> == 0)
- */
- public boolean isZero()
- {
- int i;
- if (len == 0)
- {
- return true;
- }
- for (i = 0; i < blocks; i++)
- {
- if (value[i] != 0)
- {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Tests if all bits are reset to 0 and LSB is set to 1.
- *
- * @return true if this GF2Polynomial equals 'one' (<i>this</i> == 1)
- */
- public boolean isOne()
- {
- int i;
- for (i = 1; i < blocks; i++)
- {
- if (value[i] != 0)
- {
- return false;
- }
- }
- if (value[0] != 0x01)
- {
- return false;
- }
- return true;
- }
-
- /**
- * Adds <i>b</i> to this GF2Polynomial and assigns the result to this
- * GF2Polynomial. <i>b</i> can be of different size.
- *
- * @param b GF2Polynomial to add to this GF2Polynomial
- */
- public void addToThis(GF2Polynomial b)
- {
- expandN(b.len);
- xorThisBy(b);
- }
-
- /**
- * Adds two GF2Polynomials, <i>this</i> and <i>b</i>, and returns the
- * result. <i>this</i> and <i>b</i> can be of different size.
- *
- * @param b a GF2Polynomial
- * @return a new GF2Polynomial (<i>this</i> + <i>b</i>)
- */
- public GF2Polynomial add(GF2Polynomial b)
- {
- return xor(b);
- }
-
- /**
- * Subtracts <i>b</i> from this GF2Polynomial and assigns the result to
- * this GF2Polynomial. <i>b</i> can be of different size.
- *
- * @param b a GF2Polynomial
- */
- public void subtractFromThis(GF2Polynomial b)
- {
- expandN(b.len);
- xorThisBy(b);
- }
-
- /**
- * Subtracts two GF2Polynomials, <i>this</i> and <i>b</i>, and returns the
- * result in a new GF2Polynomial. <i>this</i> and <i>b</i> can be of
- * different size.
- *
- * @param b a GF2Polynomial
- * @return a new GF2Polynomial (<i>this</i> - <i>b</i>)
- */
- public GF2Polynomial subtract(GF2Polynomial b)
- {
- return xor(b);
- }
-
- /**
- * Toggles the LSB of this GF2Polynomial, increasing its value by 'one'.
- */
- public void increaseThis()
- {
- xorBit(0);
- }
-
- /**
- * Toggles the LSB of this GF2Polynomial, increasing the value by 'one' and
- * returns the result in a new GF2Polynomial.
- *
- * @return <tt>this + 1</tt>
- */
- public GF2Polynomial increase()
- {
- GF2Polynomial result = new GF2Polynomial(this);
- result.increaseThis();
- return result;
- }
-
- /**
- * Multiplies this GF2Polynomial with <i>b</i> and returns the result in a
- * new GF2Polynomial. This method does not reduce the result in GF(2^N).
- * This method uses classic multiplication (schoolbook).
- *
- * @param b a GF2Polynomial
- * @return a new GF2Polynomial (<i>this</i> * <i>b</i>)
- */
- public GF2Polynomial multiplyClassic(GF2Polynomial b)
- {
- GF2Polynomial result = new GF2Polynomial(Math.max(len, b.len) << 1);
- GF2Polynomial[] m = new GF2Polynomial[32];
- int i, j;
- m[0] = new GF2Polynomial(this);
- for (i = 1; i <= 31; i++)
- {
- m[i] = m[i - 1].shiftLeft();
- }
- for (i = 0; i < b.blocks; i++)
- {
- for (j = 0; j <= 31; j++)
- {
- if ((b.value[i] & bitMask[j]) != 0)
- {
- result.xorThisBy(m[j]);
- }
- }
- for (j = 0; j <= 31; j++)
- {
- m[j].shiftBlocksLeft();
- }
- }
- return result;
- }
-
- /**
- * Multiplies this GF2Polynomial with <i>b</i> and returns the result in a
- * new GF2Polynomial. This method does not reduce the result in GF(2^N).
- * This method uses Karatzuba multiplication.
- *
- * @param b a GF2Polynomial
- * @return a new GF2Polynomial (<i>this</i> * <i>b</i>)
- */
- public GF2Polynomial multiply(GF2Polynomial b)
- {
- int n = Math.max(len, b.len);
- expandN(n);
- b.expandN(n);
- return karaMult(b);
- }
-
- /**
- * Does the recursion for Karatzuba multiplication.
- */
- private GF2Polynomial karaMult(GF2Polynomial b)
- {
- GF2Polynomial result = new GF2Polynomial(len << 1);
- if (len <= 32)
- {
- result.value = mult32(value[0], b.value[0]);
- return result;
- }
- if (len <= 64)
- {
- result.value = mult64(value, b.value);
- return result;
- }
- if (len <= 128)
- {
- result.value = mult128(value, b.value);
- return result;
- }
- if (len <= 256)
- {
- result.value = mult256(value, b.value);
- return result;
- }
- if (len <= 512)
- {
- result.value = mult512(value, b.value);
- return result;
- }
-
- int n = IntegerFunctions.floorLog(len - 1);
- n = bitMask[n];
-
- GF2Polynomial a0 = lower(((n - 1) >> 5) + 1);
- GF2Polynomial a1 = upper(((n - 1) >> 5) + 1);
- GF2Polynomial b0 = b.lower(((n - 1) >> 5) + 1);
- GF2Polynomial b1 = b.upper(((n - 1) >> 5) + 1);
-
- GF2Polynomial c = a1.karaMult(b1); // c = a1*b1
- GF2Polynomial e = a0.karaMult(b0); // e = a0*b0
- a0.addToThis(a1); // a0 = a0 + a1
- b0.addToThis(b1); // b0 = b0 + b1
- GF2Polynomial d = a0.karaMult(b0); // d = (a0+a1)*(b0+b1)
-
- result.shiftLeftAddThis(c, n << 1);
- result.shiftLeftAddThis(c, n);
- result.shiftLeftAddThis(d, n);
- result.shiftLeftAddThis(e, n);
- result.addToThis(e);
- return result;
- }
-
- /**
- * 16-Integer Version of Karatzuba multiplication.
- */
- private static int[] mult512(int[] a, int[] b)
- {
- int[] result = new int[32];
- int[] a0 = new int[8];
- System.arraycopy(a, 0, a0, 0, Math.min(8, a.length));
- int[] a1 = new int[8];
- if (a.length > 8)
- {
- System.arraycopy(a, 8, a1, 0, Math.min(8, a.length - 8));
- }
- int[] b0 = new int[8];
- System.arraycopy(b, 0, b0, 0, Math.min(8, b.length));
- int[] b1 = new int[8];
- if (b.length > 8)
- {
- System.arraycopy(b, 8, b1, 0, Math.min(8, b.length - 8));
- }
- int[] c = mult256(a1, b1);
- result[31] ^= c[15];
- result[30] ^= c[14];
- result[29] ^= c[13];
- result[28] ^= c[12];
- result[27] ^= c[11];
- result[26] ^= c[10];
- result[25] ^= c[9];
- result[24] ^= c[8];
- result[23] ^= c[7] ^ c[15];
- result[22] ^= c[6] ^ c[14];
- result[21] ^= c[5] ^ c[13];
- result[20] ^= c[4] ^ c[12];
- result[19] ^= c[3] ^ c[11];
- result[18] ^= c[2] ^ c[10];
- result[17] ^= c[1] ^ c[9];
- result[16] ^= c[0] ^ c[8];
- result[15] ^= c[7];
- result[14] ^= c[6];
- result[13] ^= c[5];
- result[12] ^= c[4];
- result[11] ^= c[3];
- result[10] ^= c[2];
- result[9] ^= c[1];
- result[8] ^= c[0];
- a1[0] ^= a0[0];
- a1[1] ^= a0[1];
- a1[2] ^= a0[2];
- a1[3] ^= a0[3];
- a1[4] ^= a0[4];
- a1[5] ^= a0[5];
- a1[6] ^= a0[6];
- a1[7] ^= a0[7];
- b1[0] ^= b0[0];
- b1[1] ^= b0[1];
- b1[2] ^= b0[2];
- b1[3] ^= b0[3];
- b1[4] ^= b0[4];
- b1[5] ^= b0[5];
- b1[6] ^= b0[6];
- b1[7] ^= b0[7];
- int[] d = mult256(a1, b1);
- result[23] ^= d[15];
- result[22] ^= d[14];
- result[21] ^= d[13];
- result[20] ^= d[12];
- result[19] ^= d[11];
- result[18] ^= d[10];
- result[17] ^= d[9];
- result[16] ^= d[8];
- result[15] ^= d[7];
- result[14] ^= d[6];
- result[13] ^= d[5];
- result[12] ^= d[4];
- result[11] ^= d[3];
- result[10] ^= d[2];
- result[9] ^= d[1];
- result[8] ^= d[0];
- int[] e = mult256(a0, b0);
- result[23] ^= e[15];
- result[22] ^= e[14];
- result[21] ^= e[13];
- result[20] ^= e[12];
- result[19] ^= e[11];
- result[18] ^= e[10];
- result[17] ^= e[9];
- result[16] ^= e[8];
- result[15] ^= e[7] ^ e[15];
- result[14] ^= e[6] ^ e[14];
- result[13] ^= e[5] ^ e[13];
- result[12] ^= e[4] ^ e[12];
- result[11] ^= e[3] ^ e[11];
- result[10] ^= e[2] ^ e[10];
- result[9] ^= e[1] ^ e[9];
- result[8] ^= e[0] ^ e[8];
- result[7] ^= e[7];
- result[6] ^= e[6];
- result[5] ^= e[5];
- result[4] ^= e[4];
- result[3] ^= e[3];
- result[2] ^= e[2];
- result[1] ^= e[1];
- result[0] ^= e[0];
- return result;
- }
-
- /**
- * 8-Integer Version of Karatzuba multiplication.
- */
- private static int[] mult256(int[] a, int[] b)
- {
- int[] result = new int[16];
- int[] a0 = new int[4];
- System.arraycopy(a, 0, a0, 0, Math.min(4, a.length));
- int[] a1 = new int[4];
- if (a.length > 4)
- {
- System.arraycopy(a, 4, a1, 0, Math.min(4, a.length - 4));
- }
- int[] b0 = new int[4];
- System.arraycopy(b, 0, b0, 0, Math.min(4, b.length));
- int[] b1 = new int[4];
- if (b.length > 4)
- {
- System.arraycopy(b, 4, b1, 0, Math.min(4, b.length - 4));
- }
- if (a1[3] == 0 && a1[2] == 0 && b1[3] == 0 && b1[2] == 0)
- {
- if (a1[1] == 0 && b1[1] == 0)
- {
- if (a1[0] != 0 || b1[0] != 0)
- { // [3]=[2]=[1]=0, [0]!=0
- int[] c = mult32(a1[0], b1[0]);
- result[9] ^= c[1];
- result[8] ^= c[0];
- result[5] ^= c[1];
- result[4] ^= c[0];
- }
- }
- else
- { // [3]=[2]=0 [1]!=0, [0]!=0
- int[] c = mult64(a1, b1);
- result[11] ^= c[3];
- result[10] ^= c[2];
- result[9] ^= c[1];
- result[8] ^= c[0];
- result[7] ^= c[3];
- result[6] ^= c[2];
- result[5] ^= c[1];
- result[4] ^= c[0];
- }
- }
- else
- { // [3]!=0 [2]!=0 [1]!=0, [0]!=0
- int[] c = mult128(a1, b1);
- result[15] ^= c[7];
- result[14] ^= c[6];
- result[13] ^= c[5];
- result[12] ^= c[4];
- result[11] ^= c[3] ^ c[7];
- result[10] ^= c[2] ^ c[6];
- result[9] ^= c[1] ^ c[5];
- result[8] ^= c[0] ^ c[4];
- result[7] ^= c[3];
- result[6] ^= c[2];
- result[5] ^= c[1];
- result[4] ^= c[0];
- }
- a1[0] ^= a0[0];
- a1[1] ^= a0[1];
- a1[2] ^= a0[2];
- a1[3] ^= a0[3];
- b1[0] ^= b0[0];
- b1[1] ^= b0[1];
- b1[2] ^= b0[2];
- b1[3] ^= b0[3];
- int[] d = mult128(a1, b1);
- result[11] ^= d[7];
- result[10] ^= d[6];
- result[9] ^= d[5];
- result[8] ^= d[4];
- result[7] ^= d[3];
- result[6] ^= d[2];
- result[5] ^= d[1];
- result[4] ^= d[0];
- int[] e = mult128(a0, b0);
- result[11] ^= e[7];
- result[10] ^= e[6];
- result[9] ^= e[5];
- result[8] ^= e[4];
- result[7] ^= e[3] ^ e[7];
- result[6] ^= e[2] ^ e[6];
- result[5] ^= e[1] ^ e[5];
- result[4] ^= e[0] ^ e[4];
- result[3] ^= e[3];
- result[2] ^= e[2];
- result[1] ^= e[1];
- result[0] ^= e[0];
- return result;
- }
-
- /**
- * 4-Integer Version of Karatzuba multiplication.
- */
- private static int[] mult128(int[] a, int[] b)
- {
- int[] result = new int[8];
- int[] a0 = new int[2];
- System.arraycopy(a, 0, a0, 0, Math.min(2, a.length));
- int[] a1 = new int[2];
- if (a.length > 2)
- {
- System.arraycopy(a, 2, a1, 0, Math.min(2, a.length - 2));
- }
- int[] b0 = new int[2];
- System.arraycopy(b, 0, b0, 0, Math.min(2, b.length));
- int[] b1 = new int[2];
- if (b.length > 2)
- {
- System.arraycopy(b, 2, b1, 0, Math.min(2, b.length - 2));
- }
- if (a1[1] == 0 && b1[1] == 0)
- {
- if (a1[0] != 0 || b1[0] != 0)
- {
- int[] c = mult32(a1[0], b1[0]);
- result[5] ^= c[1];
- result[4] ^= c[0];
- result[3] ^= c[1];
- result[2] ^= c[0];
- }
- }
- else
- {
- int[] c = mult64(a1, b1);
- result[7] ^= c[3];
- result[6] ^= c[2];
- result[5] ^= c[1] ^ c[3];
- result[4] ^= c[0] ^ c[2];
- result[3] ^= c[1];
- result[2] ^= c[0];
- }
- a1[0] ^= a0[0];
- a1[1] ^= a0[1];
- b1[0] ^= b0[0];
- b1[1] ^= b0[1];
- if (a1[1] == 0 && b1[1] == 0)
- {
- int[] d = mult32(a1[0], b1[0]);
- result[3] ^= d[1];
- result[2] ^= d[0];
- }
- else
- {
- int[] d = mult64(a1, b1);
- result[5] ^= d[3];
- result[4] ^= d[2];
- result[3] ^= d[1];
- result[2] ^= d[0];
- }
- if (a0[1] == 0 && b0[1] == 0)
- {
- int[] e = mult32(a0[0], b0[0]);
- result[3] ^= e[1];
- result[2] ^= e[0];
- result[1] ^= e[1];
- result[0] ^= e[0];
- }
- else
- {
- int[] e = mult64(a0, b0);
- result[5] ^= e[3];
- result[4] ^= e[2];
- result[3] ^= e[1] ^ e[3];
- result[2] ^= e[0] ^ e[2];
- result[1] ^= e[1];
- result[0] ^= e[0];
- }
- return result;
- }
-
- /**
- * 2-Integer Version of Karatzuba multiplication.
- */
- private static int[] mult64(int[] a, int[] b)
- {
- int[] result = new int[4];
- int a0 = a[0];
- int a1 = 0;
- if (a.length > 1)
- {
- a1 = a[1];
- }
- int b0 = b[0];
- int b1 = 0;
- if (b.length > 1)
- {
- b1 = b[1];
- }
- if (a1 != 0 || b1 != 0)
- {
- int[] c = mult32(a1, b1);
- result[3] ^= c[1];
- result[2] ^= c[0] ^ c[1];
- result[1] ^= c[0];
- }
- int[] d = mult32(a0 ^ a1, b0 ^ b1);
- result[2] ^= d[1];
- result[1] ^= d[0];
- int[] e = mult32(a0, b0);
- result[2] ^= e[1];
- result[1] ^= e[0] ^ e[1];
- result[0] ^= e[0];
- return result;
- }
-
- /**
- * 4-Byte Version of Karatzuba multiplication. Here the actual work is done.
- */
- private static int[] mult32(int a, int b)
- {
- int[] result = new int[2];
- if (a == 0 || b == 0)
- {
- return result;
- }
- long b2 = b;
- b2 &= 0x00000000ffffffffL;
- int i;
- long h = 0;
- for (i = 1; i <= 32; i++)
- {
- if ((a & bitMask[i - 1]) != 0)
- {
- h ^= b2;
- }
- b2 <<= 1;
- }
- result[1] = (int)(h >>> 32);
- result[0] = (int)(h & 0x00000000ffffffffL);
- return result;
- }
-
- /**
- * Returns a new GF2Polynomial containing the upper <i>k</i> bytes of this
- * GF2Polynomial.
- *
- * @param k
- * @return a new GF2Polynomial containing the upper <i>k</i> bytes of this
- * GF2Polynomial
- * @see GF2Polynomial#karaMult
- */
- private GF2Polynomial upper(int k)
- {
- int j = Math.min(k, blocks - k);
- GF2Polynomial result = new GF2Polynomial(j << 5);
- if (blocks >= k)
- {
- System.arraycopy(value, k, result.value, 0, j);
- }
- return result;
- }
-
- /**
- * Returns a new GF2Polynomial containing the lower <i>k</i> bytes of this
- * GF2Polynomial.
- *
- * @param k
- * @return a new GF2Polynomial containing the lower <i>k</i> bytes of this
- * GF2Polynomial
- * @see GF2Polynomial#karaMult
- */
- private GF2Polynomial lower(int k)
- {
- GF2Polynomial result = new GF2Polynomial(k << 5);
- System.arraycopy(value, 0, result.value, 0, Math.min(k, blocks));
- return result;
- }
-
- /**
- * Returns the remainder of <i>this</i> divided by <i>g</i> in a new
- * GF2Polynomial.
- *
- * @param g GF2Polynomial != 0
- * @return a new GF2Polynomial (<i>this</i> % <i>g</i>)
- * @throws PolynomialIsZeroException if <i>g</i> equals zero
- */
- public GF2Polynomial remainder(GF2Polynomial g)
- throws RuntimeException
- {
- /* a div b = q / r */
- GF2Polynomial a = new GF2Polynomial(this);
- GF2Polynomial b = new GF2Polynomial(g);
- GF2Polynomial j;
- int i;
- if (b.isZero())
- {
- throw new RuntimeException();
- }
- a.reduceN();
- b.reduceN();
- if (a.len < b.len)
- {
- return a;
- }
- i = a.len - b.len;
- while (i >= 0)
- {
- j = b.shiftLeft(i);
- a.subtractFromThis(j);
- a.reduceN();
- i = a.len - b.len;
- }
- return a;
- }
-
- /**
- * Returns the absolute quotient of <i>this</i> divided by <i>g</i> in a
- * new GF2Polynomial.
- *
- * @param g GF2Polynomial != 0
- * @return a new GF2Polynomial |_ <i>this</i> / <i>g</i> _|
- * @throws PolynomialIsZeroException if <i>g</i> equals zero
- */
- public GF2Polynomial quotient(GF2Polynomial g)
- throws RuntimeException
- {
- /* a div b = q / r */
- GF2Polynomial q = new GF2Polynomial(len);
- GF2Polynomial a = new GF2Polynomial(this);
- GF2Polynomial b = new GF2Polynomial(g);
- GF2Polynomial j;
- int i;
- if (b.isZero())
- {
- throw new RuntimeException();
- }
- a.reduceN();
- b.reduceN();
- if (a.len < b.len)
- {
- return new GF2Polynomial(0);
- }
- i = a.len - b.len;
- q.expandN(i + 1);
-
- while (i >= 0)
- {
- j = b.shiftLeft(i);
- a.subtractFromThis(j);
- a.reduceN();
- q.xorBit(i);
- i = a.len - b.len;
- }
-
- return q;
- }
-
- /**
- * Divides <i>this</i> by <i>g</i> and returns the quotient and remainder
- * in a new GF2Polynomial[2], quotient in [0], remainder in [1].
- *
- * @param g GF2Polynomial != 0
- * @return a new GF2Polynomial[2] containing quotient and remainder
- * @throws PolynomialIsZeroException if <i>g</i> equals zero
- */
- public GF2Polynomial[] divide(GF2Polynomial g)
- throws RuntimeException
- {
- /* a div b = q / r */
- GF2Polynomial[] result = new GF2Polynomial[2];
- GF2Polynomial q = new GF2Polynomial(len);
- GF2Polynomial a = new GF2Polynomial(this);
- GF2Polynomial b = new GF2Polynomial(g);
- GF2Polynomial j;
- int i;
- if (b.isZero())
- {
- throw new RuntimeException();
- }
- a.reduceN();
- b.reduceN();
- if (a.len < b.len)
- {
- result[0] = new GF2Polynomial(0);
- result[1] = a;
- return result;
- }
- i = a.len - b.len;
- q.expandN(i + 1);
-
- while (i >= 0)
- {
- j = b.shiftLeft(i);
- a.subtractFromThis(j);
- a.reduceN();
- q.xorBit(i);
- i = a.len - b.len;
- }
-
- result[0] = q;
- result[1] = a;
- return result;
- }
-
- /**
- * Returns the greatest common divisor of <i>this</i> and <i>g</i> in a
- * new GF2Polynomial.
- *
- * @param g GF2Polynomial != 0
- * @return a new GF2Polynomial gcd(<i>this</i>,<i>g</i>)
- * @throws ArithmeticException if <i>this</i> and <i>g</i> both are equal to zero
- * @throws PolynomialIsZeroException to be API-compliant (should never be thrown).
- */
- public GF2Polynomial gcd(GF2Polynomial g)
- throws RuntimeException
- {
- if (isZero() && g.isZero())
- {
- throw new ArithmeticException("Both operands of gcd equal zero.");
- }
- if (isZero())
- {
- return new GF2Polynomial(g);
- }
- if (g.isZero())
- {
- return new GF2Polynomial(this);
- }
- GF2Polynomial a = new GF2Polynomial(this);
- GF2Polynomial b = new GF2Polynomial(g);
- GF2Polynomial c;
-
- while (!b.isZero())
- {
- c = a.remainder(b);
- a = b;
- b = c;
- }
-
- return a;
- }
-
- /**
- * Checks if <i>this</i> is irreducible, according to IEEE P1363, A.5.5,
- * p103.<br>
- * Note: The algorithm from IEEE P1363, A5.5 can be used to check a
- * polynomial with coefficients in GF(2^r) for irreducibility. As this class
- * only represents polynomials with coefficients in GF(2), the algorithm is
- * adapted to the case r=1.
- *
- * @return true if <i>this</i> is irreducible
- * @see "P1363, A.5.5, p103"
- */
- public boolean isIrreducible()
- {
- if (isZero())
- {
- return false;
- }
- GF2Polynomial f = new GF2Polynomial(this);
- int d, i;
- GF2Polynomial u, g;
- GF2Polynomial dummy;
- f.reduceN();
- d = f.len - 1;
- u = new GF2Polynomial(f.len, "X");
-
- for (i = 1; i <= (d >> 1); i++)
- {
- u.squareThisPreCalc();
- u = u.remainder(f);
- dummy = u.add(new GF2Polynomial(32, "X"));
- if (!dummy.isZero())
- {
- g = f.gcd(dummy);
- if (!g.isOne())
- {
- return false;
- }
- }
- else
- {
- return false;
- }
- }
-
- return true;
- }
-
- /**
- * Reduces this GF2Polynomial using the trinomial x^<i>m</i> + x^<i>tc</i> +
- * 1.
- *
- * @param m the degree of the used field
- * @param tc degree of the middle x in the trinomial
- */
- void reduceTrinomial(int m, int tc)
- {
- int i;
- int p0, p1;
- int q0, q1;
- long t;
- p0 = m >>> 5; // block which contains 2^m
- q0 = 32 - (m & 0x1f); // (32-index) of 2^m within block p0
- p1 = (m - tc) >>> 5; // block which contains 2^tc
- q1 = 32 - ((m - tc) & 0x1f); // (32-index) of 2^tc within block q1
- int max = ((m << 1) - 2) >>> 5; // block which contains 2^(2m-2)
- int min = p0; // block which contains 2^m
- for (i = max; i > min; i--)
- { // for i = maxBlock to minBlock
- // reduce coefficients contained in t
- // t = block[i]
- t = value[i] & 0x00000000ffffffffL;
- // block[i-p0-1] ^= t << q0
- value[i - p0 - 1] ^= (int)(t << q0);
- // block[i-p0] ^= t >>> (32-q0)
- value[i - p0] ^= t >>> (32 - q0);
- // block[i-p1-1] ^= << q1
- value[i - p1 - 1] ^= (int)(t << q1);
- // block[i-p1] ^= t >>> (32-q1)
- value[i - p1] ^= t >>> (32 - q1);
- value[i] = 0x00;
- }
- // reduce last coefficients in block containing 2^m
- t = value[min] & 0x00000000ffffffffL & (0xffffffffL << (m & 0x1f)); // t
- // contains the last coefficients > m
- value[0] ^= t >>> (32 - q0);
- if (min - p1 - 1 >= 0)
- {
- value[min - p1 - 1] ^= (int)(t << q1);
- }
- value[min - p1] ^= t >>> (32 - q1);
-
- value[min] &= reverseRightMask[m & 0x1f];
- blocks = ((m - 1) >>> 5) + 1;
- len = m;
- }
-
- /**
- * Reduces this GF2Polynomial using the pentanomial x^<i>m</i> + x^<i>pc[2]</i> +
- * x^<i>pc[1]</i> + x^<i>pc[0]</i> + 1.
- *
- * @param m the degree of the used field
- * @param pc degrees of the middle x's in the pentanomial
- */
- void reducePentanomial(int m, int[] pc)
- {
- int i;
- int p0, p1, p2, p3;
- int q0, q1, q2, q3;
- long t;
- p0 = m >>> 5;
- q0 = 32 - (m & 0x1f);
- p1 = (m - pc[0]) >>> 5;
- q1 = 32 - ((m - pc[0]) & 0x1f);
- p2 = (m - pc[1]) >>> 5;
- q2 = 32 - ((m - pc[1]) & 0x1f);
- p3 = (m - pc[2]) >>> 5;
- q3 = 32 - ((m - pc[2]) & 0x1f);
- int max = ((m << 1) - 2) >>> 5;
- int min = p0;
- for (i = max; i > min; i--)
- {
- t = value[i] & 0x00000000ffffffffL;
- value[i - p0 - 1] ^= (int)(t << q0);
- value[i - p0] ^= t >>> (32 - q0);
- value[i - p1 - 1] ^= (int)(t << q1);
- value[i - p1] ^= t >>> (32 - q1);
- value[i - p2 - 1] ^= (int)(t << q2);
- value[i - p2] ^= t >>> (32 - q2);
- value[i - p3 - 1] ^= (int)(t << q3);
- value[i - p3] ^= t >>> (32 - q3);
- value[i] = 0;
- }
- t = value[min] & 0x00000000ffffffffL & (0xffffffffL << (m & 0x1f));
- value[0] ^= t >>> (32 - q0);
- if (min - p1 - 1 >= 0)
- {
- value[min - p1 - 1] ^= (int)(t << q1);
- }
- value[min - p1] ^= t >>> (32 - q1);
- if (min - p2 - 1 >= 0)
- {
- value[min - p2 - 1] ^= (int)(t << q2);
- }
- value[min - p2] ^= t >>> (32 - q2);
- if (min - p3 - 1 >= 0)
- {
- value[min - p3 - 1] ^= (int)(t << q3);
- }
- value[min - p3] ^= t >>> (32 - q3);
- value[min] &= reverseRightMask[m & 0x1f];
-
- blocks = ((m - 1) >>> 5) + 1;
- len = m;
- }
-
- /**
- * Reduces len by finding the most significant bit set to one and reducing
- * len and blocks.
- */
- public void reduceN()
- {
- int i, j, h;
- i = blocks - 1;
- while ((value[i] == 0) && (i > 0))
- {
- i--;
- }
- h = value[i];
- j = 0;
- while (h != 0)
- {
- h >>>= 1;
- j++;
- }
- len = (i << 5) + j;
- blocks = i + 1;
- }
-
- /**
- * Expands len and int[] value to <i>i</i>. This is useful before adding
- * two GF2Polynomials of different size.
- *
- * @param i the intended length
- */
- public void expandN(int i)
- {
- int k;
- int[] bs;
- if (len >= i)
- {
- return;
- }
- len = i;
- k = ((i - 1) >>> 5) + 1;
- if (blocks >= k)
- {
- return;
- }
- if (value.length >= k)
- {
- int j;
- for (j = blocks; j < k; j++)
- {
- value[j] = 0;
- }
- blocks = k;
- return;
- }
- bs = new int[k];
- System.arraycopy(value, 0, bs, 0, blocks);
- blocks = k;
- value = null;
- value = bs;
- }
-
- /**
- * Squares this GF2Polynomial and expands it accordingly. This method does
- * not reduce the result in GF(2^N). There exists a faster method for
- * squaring in GF(2^N).
- *
- * @see GF2nPolynomialElement#square
- */
- public void squareThisBitwise()
- {
- int i, h, j, k;
- if (isZero())
- {
- return;
- }
- int[] result = new int[blocks << 1];
- for (i = blocks - 1; i >= 0; i--)
- {
- h = value[i];
- j = 0x00000001;
- for (k = 0; k < 16; k++)
- {
- if ((h & 0x01) != 0)
- {
- result[i << 1] |= j;
- }
- if ((h & 0x00010000) != 0)
- {
- result[(i << 1) + 1] |= j;
- }
- j <<= 2;
- h >>>= 1;
- }
- }
- value = null;
- value = result;
- blocks = result.length;
- len = (len << 1) - 1;
- }
-
- /**
- * Squares this GF2Polynomial by using precomputed values of squaringTable.
- * This method does not reduce the result in GF(2^N).
- */
- public void squareThisPreCalc()
- {
- int i;
- if (isZero())
- {
- return;
- }
- if (value.length >= (blocks << 1))
- {
- for (i = blocks - 1; i >= 0; i--)
- {
- value[(i << 1) + 1] = GF2Polynomial.squaringTable[(value[i] & 0x00ff0000) >>> 16]
- | (GF2Polynomial.squaringTable[(value[i] & 0xff000000) >>> 24] << 16);
- value[i << 1] = GF2Polynomial.squaringTable[value[i] & 0x000000ff]
- | (GF2Polynomial.squaringTable[(value[i] & 0x0000ff00) >>> 8] << 16);
- }
- blocks <<= 1;
- len = (len << 1) - 1;
- }
- else
- {
- int[] result = new int[blocks << 1];
- for (i = 0; i < blocks; i++)
- {
- result[i << 1] = GF2Polynomial.squaringTable[value[i] & 0x000000ff]
- | (GF2Polynomial.squaringTable[(value[i] & 0x0000ff00) >>> 8] << 16);
- result[(i << 1) + 1] = GF2Polynomial.squaringTable[(value[i] & 0x00ff0000) >>> 16]
- | (GF2Polynomial.squaringTable[(value[i] & 0xff000000) >>> 24] << 16);
- }
- value = null;
- value = result;
- blocks <<= 1;
- len = (len << 1) - 1;
- }
- }
-
- /**
- * Does a vector-multiplication modulo 2 and returns the result as boolean.
- *
- * @param b GF2Polynomial
- * @return this x <i>b</i> as boolean (1-&gt;true, 0-&gt;false)
- * @throws PolynomialsHaveDifferentLengthException if <i>this</i> and <i>b</i> have a different length and
- * thus cannot be vector-multiplied
- */
- public boolean vectorMult(GF2Polynomial b)
- throws RuntimeException
- {
- int i;
- int h;
- boolean result = false;
- if (len != b.len)
- {
- throw new RuntimeException();
- }
- for (i = 0; i < blocks; i++)
- {
- h = value[i] & b.value[i];
- result ^= parity[h & 0x000000ff];
- result ^= parity[(h >>> 8) & 0x000000ff];
- result ^= parity[(h >>> 16) & 0x000000ff];
- result ^= parity[(h >>> 24) & 0x000000ff];
- }
- return result;
- }
-
- /**
- * Returns the bitwise exclusive-or of <i>this</i> and <i>b</i> in a new
- * GF2Polynomial. <i>this</i> and <i>b</i> can be of different size.
- *
- * @param b GF2Polynomial
- * @return a new GF2Polynomial (<i>this</i> ^ <i>b</i>)
- */
- public GF2Polynomial xor(GF2Polynomial b)
- {
- int i;
- GF2Polynomial result;
- int k = Math.min(blocks, b.blocks);
- if (len >= b.len)
- {
- result = new GF2Polynomial(this);
- for (i = 0; i < k; i++)
- {
- result.value[i] ^= b.value[i];
- }
- }
- else
- {
- result = new GF2Polynomial(b);
- for (i = 0; i < k; i++)
- {
- result.value[i] ^= value[i];
- }
- }
- // If we xor'ed some bits too many by proceeding blockwise,
- // restore them to zero:
- result.zeroUnusedBits();
- return result;
- }
-
- /**
- * Computes the bitwise exclusive-or of this GF2Polynomial and <i>b</i> and
- * stores the result in this GF2Polynomial. <i>b</i> can be of different
- * size.
- *
- * @param b GF2Polynomial
- */
- public void xorThisBy(GF2Polynomial b)
- {
- int i;
- for (i = 0; i < Math.min(blocks, b.blocks); i++)
- {
- value[i] ^= b.value[i];
- }
- // If we xor'ed some bits too many by proceeding blockwise,
- // restore them to zero:
- zeroUnusedBits();
- }
-
- /**
- * If {@link #len} is not a multiple of the block size (32), some extra bits
- * of the last block might have been modified during a blockwise operation.
- * This method compensates for that by restoring these "extra" bits to zero.
- */
- private void zeroUnusedBits()
- {
- if ((len & 0x1f) != 0)
- {
- value[blocks - 1] &= reverseRightMask[len & 0x1f];
- }
- }
-
- /**
- * Sets the bit at position <i>i</i>.
- *
- * @param i int
- * @throws RuntimeException if (<i>i</i> &lt; 0) || (<i>i</i> &gt; (len - 1))
- */
- public void setBit(int i)
- throws RuntimeException
- {
- if (i < 0 || i > (len - 1))
- {
- throw new RuntimeException();
- }
- value[i >>> 5] |= bitMask[i & 0x1f];
- return;
- }
-
- /**
- * Returns the bit at position <i>i</i>.
- *
- * @param i int
- * @return the bit at position <i>i</i> if <i>i</i> is a valid position, 0
- * otherwise.
- */
- public int getBit(int i)
- {
- if (i < 0)
- {
- throw new RuntimeException();
- }
- if (i > (len - 1))
- {
- return 0;
- }
- return ((value[i >>> 5] & bitMask[i & 0x1f]) != 0) ? 1 : 0;
- }
-
- /**
- * Resets the bit at position <i>i</i>.
- *
- * @param i int
- * @throws RuntimeException if (<i>i</i> &lt; 0) || (<i>i</i> &gt; (len - 1))
- */
- public void resetBit(int i)
- throws RuntimeException
- {
- if (i < 0)
- {
- throw new RuntimeException();
- }
- if (i > (len - 1))
- {
- return;
- }
- value[i >>> 5] &= ~bitMask[i & 0x1f];
- }
-
- /**
- * Xors the bit at position <i>i</i>.
- *
- * @param i int
- * @throws RuntimeException if (<i>i</i> &lt; 0) || (<i>i</i> &gt; (len - 1))
- */
- public void xorBit(int i)
- throws RuntimeException
- {
- if (i < 0 || i > (len - 1))
- {
- throw new RuntimeException();
- }
- value[i >>> 5] ^= bitMask[i & 0x1f];
- }
-
- /**
- * Tests the bit at position <i>i</i>.
- *
- * @param i the position of the bit to be tested
- * @return true if the bit at position <i>i</i> is set (a(<i>i</i>) ==
- * 1). False if (<i>i</i> &lt; 0) || (<i>i</i> &gt; (len - 1))
- */
- public boolean testBit(int i)
- {
- if (i < 0)
- {
- throw new RuntimeException();
- }
- if (i > (len - 1))
- {
- return false;
- }
- return (value[i >>> 5] & bitMask[i & 0x1f]) != 0;
- }
-
- /**
- * Returns this GF2Polynomial shift-left by 1 in a new GF2Polynomial.
- *
- * @return a new GF2Polynomial (this &lt;&lt; 1)
- */
- public GF2Polynomial shiftLeft()
- {
- GF2Polynomial result = new GF2Polynomial(len + 1, value);
- int i;
- for (i = result.blocks - 1; i >= 1; i--)
- {
- result.value[i] <<= 1;
- result.value[i] |= result.value[i - 1] >>> 31;
- }
- result.value[0] <<= 1;
- return result;
- }
-
- /**
- * Shifts-left this by one and enlarges the size of value if necesary.
- */
- public void shiftLeftThis()
- {
- /** @todo This is untested. */
- int i;
- if ((len & 0x1f) == 0)
- { // check if blocks increases
- len += 1;
- blocks += 1;
- if (blocks > value.length)
- { // enlarge value
- int[] bs = new int[blocks];
- System.arraycopy(value, 0, bs, 0, value.length);
- value = null;
- value = bs;
- }
- for (i = blocks - 1; i >= 1; i--)
- {
- value[i] |= value[i - 1] >>> 31;
- value[i - 1] <<= 1;
- }
- }
- else
- {
- len += 1;
- for (i = blocks - 1; i >= 1; i--)
- {
- value[i] <<= 1;
- value[i] |= value[i - 1] >>> 31;
- }
- value[0] <<= 1;
- }
- }
-
- /**
- * Returns this GF2Polynomial shift-left by <i>k</i> in a new
- * GF2Polynomial.
- *
- * @param k int
- * @return a new GF2Polynomial (this &lt;&lt; <i>k</i>)
- */
- public GF2Polynomial shiftLeft(int k)
- {
- // Variant 2, requiring a modified shiftBlocksLeft(k)
- // In case of modification, consider a rename to doShiftBlocksLeft()
- // with an explicit note that this method assumes that the polynomial
- // has already been resized. Or consider doing things inline.
- // Construct the resulting polynomial of appropriate length:
- GF2Polynomial result = new GF2Polynomial(len + k, value);
- // Shift left as many multiples of the block size as possible:
- if (k >= 32)
- {
- result.doShiftBlocksLeft(k >>> 5);
- }
- // Shift left by the remaining (<32) amount:
- final int remaining = k & 0x1f;
- if (remaining != 0)
- {
- for (int i = result.blocks - 1; i >= 1; i--)
- {
- result.value[i] <<= remaining;
- result.value[i] |= result.value[i - 1] >>> (32 - remaining);
- }
- result.value[0] <<= remaining;
- }
- return result;
- }
-
- /**
- * Shifts left b and adds the result to Its a fast version of
- * <tt>this = add(b.shl(k));</tt>
- *
- * @param b GF2Polynomial to shift and add to this
- * @param k the amount to shift
- * @see GF2nPolynomialElement#invertEEA
- */
- public void shiftLeftAddThis(GF2Polynomial b, int k)
- {
- if (k == 0)
- {
- addToThis(b);
- return;
- }
- int i;
- expandN(b.len + k);
- int d = k >>> 5;
- for (i = b.blocks - 1; i >= 0; i--)
- {
- if ((i + d + 1 < blocks) && ((k & 0x1f) != 0))
- {
- value[i + d + 1] ^= b.value[i] >>> (32 - (k & 0x1f));
- }
- value[i + d] ^= b.value[i] << (k & 0x1f);
- }
- }
-
- /**
- * Shifts-left this GF2Polynomial's value blockwise 1 block resulting in a
- * shift-left by 32.
- *
- * @see GF2Polynomial#multiply
- */
- void shiftBlocksLeft()
- {
- blocks += 1;
- len += 32;
- if (blocks <= value.length)
- {
- int i;
- for (i = blocks - 1; i >= 1; i--)
- {
- value[i] = value[i - 1];
- }
- value[0] = 0x00;
- }
- else
- {
- int[] result = new int[blocks];
- System.arraycopy(value, 0, result, 1, blocks - 1);
- value = null;
- value = result;
- }
- }
-
- /**
- * Shifts left this GF2Polynomial's value blockwise <i>b</i> blocks
- * resulting in a shift-left by b*32. This method assumes that {@link #len}
- * and {@link #blocks} have already been updated to reflect the final state.
- *
- * @param b shift amount (in blocks)
- */
- private void doShiftBlocksLeft(int b)
- {
- if (blocks <= value.length)
- {
- int i;
- for (i = blocks - 1; i >= b; i--)
- {
- value[i] = value[i - b];
- }
- for (i = 0; i < b; i++)
- {
- value[i] = 0x00;
- }
- }
- else
- {
- int[] result = new int[blocks];
- System.arraycopy(value, 0, result, b, blocks - b);
- value = null;
- value = result;
- }
- }
-
- /**
- * Returns this GF2Polynomial shift-right by 1 in a new GF2Polynomial.
- *
- * @return a new GF2Polynomial (this &lt;&lt; 1)
- */
- public GF2Polynomial shiftRight()
- {
- GF2Polynomial result = new GF2Polynomial(len - 1);
- int i;
- System.arraycopy(value, 0, result.value, 0, result.blocks);
- for (i = 0; i <= result.blocks - 2; i++)
- {
- result.value[i] >>>= 1;
- result.value[i] |= result.value[i + 1] << 31;
- }
- result.value[result.blocks - 1] >>>= 1;
- if (result.blocks < blocks)
- {
- result.value[result.blocks - 1] |= value[result.blocks] << 31;
- }
- return result;
- }
-
- /**
- * Shifts-right this GF2Polynomial by 1.
- */
- public void shiftRightThis()
- {
- int i;
- len -= 1;
- blocks = ((len - 1) >>> 5) + 1;
- for (i = 0; i <= blocks - 2; i++)
- {
- value[i] >>>= 1;
- value[i] |= value[i + 1] << 31;
- }
- value[blocks - 1] >>>= 1;
- if ((len & 0x1f) == 0)
- {
- value[blocks - 1] |= value[blocks] << 31;
- }
- }
-
-}
diff --git a/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2Vector.java b/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2Vector.java
deleted file mode 100644
index ec35b68..0000000
--- a/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2Vector.java
+++ /dev/null
@@ -1,539 +0,0 @@
-package org.bouncycastle.pqc.math.linearalgebra;
-
-import java.security.SecureRandom;
-
-/**
- * This class implements the abstract class <tt>Vector</tt> for the case of
- * vectors over the finite field GF(2). <br>
- * For the vector representation the array of type int[] is used, thus one
- * element of the array holds 32 elements of the vector.
- *
- * @see Vector
- */
-public class GF2Vector
- extends Vector
-{
-
- /**
- * holds the elements of this vector
- */
- private int[] v;
-
- /**
- * Construct the zero vector of the given length.
- *
- * @param length the length of the vector
- */
- public GF2Vector(int length)
- {
- if (length < 0)
- {
- throw new ArithmeticException("Negative length.");
- }
- this.length = length;
- v = new int[(length + 31) >> 5];
- }
-
- /**
- * Construct a random GF2Vector of the given length.
- *
- * @param length the length of the vector
- * @param sr the source of randomness
- */
- public GF2Vector(int length, SecureRandom sr)
- {
- this.length = length;
-
- int size = (length + 31) >> 5;
- v = new int[size];
-
- // generate random elements
- for (int i = size - 1; i >= 0; i--)
- {
- v[i] = sr.nextInt();
- }
-
- // erase unused bits
- int r = length & 0x1f;
- if (r != 0)
- {
- // erase unused bits
- v[size - 1] &= (1 << r) - 1;
- }
- }
-
- /**
- * Construct a random GF2Vector of the given length with the specified
- * number of non-zero coefficients.
- *
- * @param length the length of the vector
- * @param t the number of non-zero coefficients
- * @param sr the source of randomness
- */
- public GF2Vector(int length, int t, SecureRandom sr)
- {
- if (t > length)
- {
- throw new ArithmeticException(
- "The hamming weight is greater than the length of vector.");
- }
- this.length = length;
-
- int size = (length + 31) >> 5;
- v = new int[size];
-
- int[] help = new int[length];
- for (int i = 0; i < length; i++)
- {
- help[i] = i;
- }
-
- int m = length;
- for (int i = 0; i < t; i++)
- {
- int j = RandUtils.nextInt(sr, m);
- setBit(help[j]);
- m--;
- help[j] = help[m];
- }
- }
-
- /**
- * Construct a GF2Vector of the given length and with elements from the
- * given array. The array is copied and unused bits are masked out.
- *
- * @param length the length of the vector
- * @param v the element array
- */
- public GF2Vector(int length, int[] v)
- {
- if (length < 0)
- {
- throw new ArithmeticException("negative length");
- }
- this.length = length;
-
- int size = (length + 31) >> 5;
-
- if (v.length != size)
- {
- throw new ArithmeticException("length mismatch");
- }
-
- this.v = IntUtils.clone(v);
-
- int r = length & 0x1f;
- if (r != 0)
- {
- // erase unused bits
- this.v[size - 1] &= (1 << r) - 1;
- }
- }
-
- /**
- * Copy constructor.
- *
- * @param other another {@link GF2Vector}
- */
- public GF2Vector(GF2Vector other)
- {
- this.length = other.length;
- this.v = IntUtils.clone(other.v);
- }
-
- /**
- * Construct a new {@link GF2Vector} of the given length and with the given
- * element array. The array is not changed and only a reference to the array
- * is stored. No length checking is performed either.
- *
- * @param v the element array
- * @param length the length of the vector
- */
- protected GF2Vector(int[] v, int length)
- {
- this.v = v;
- this.length = length;
- }
-
- /**
- * Construct a new GF2Vector with the given length out of the encoded
- * vector.
- *
- * @param length the length of the vector
- * @param encVec the encoded vector
- * @return the decoded vector
- */
- public static GF2Vector OS2VP(int length, byte[] encVec)
- {
- if (length < 0)
- {
- throw new ArithmeticException("negative length");
- }
-
- int byteLen = (length + 7) >> 3;
-
- if (encVec.length > byteLen)
- {
- throw new ArithmeticException("length mismatch");
- }
-
- return new GF2Vector(length, LittleEndianConversions.toIntArray(encVec));
- }
-
- /**
- * Encode this vector as byte array.
- *
- * @return the encoded vector
- */
- public byte[] getEncoded()
- {
- int byteLen = (length + 7) >> 3;
- return LittleEndianConversions.toByteArray(v, byteLen);
- }
-
- /**
- * @return the int array representation of this vector
- */
- public int[] getVecArray()
- {
- return v;
- }
-
- /**
- * Return the Hamming weight of this vector, i.e., compute the number of
- * units of this vector.
- *
- * @return the Hamming weight of this vector
- */
- public int getHammingWeight()
- {
- int weight = 0;
- for (int i = 0; i < v.length; i++)
- {
- int e = v[i];
- for (int j = 0; j < 32; j++)
- {
- int b = e & 1;
- if (b != 0)
- {
- weight++;
- }
- e >>>= 1;
- }
- }
- return weight;
- }
-
- /**
- * @return whether this is the zero vector (i.e., all elements are zero)
- */
- public boolean isZero()
- {
- for (int i = v.length - 1; i >= 0; i--)
- {
- if (v[i] != 0)
- {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Return the value of the bit of this vector at the specified index.
- *
- * @param index the index
- * @return the value of the bit (0 or 1)
- */
- public int getBit(int index)
- {
- if (index >= length)
- {
- throw new IndexOutOfBoundsException();
- }
- int q = index >> 5;
- int r = index & 0x1f;
- return (v[q] & (1 << r)) >>> r;
- }
-
- /**
- * Set the coefficient at the given index to 1. If the index is out of
- * bounds, do nothing.
- *
- * @param index the index of the coefficient to set
- */
- public void setBit(int index)
- {
- if (index >= length)
- {
- throw new IndexOutOfBoundsException();
- }
- v[index >> 5] |= 1 << (index & 0x1f);
- }
-
- /**
- * Adds another GF2Vector to this vector.
- *
- * @param other another GF2Vector
- * @return <tt>this + other</tt>
- * @throws ArithmeticException if the other vector is not a GF2Vector or has another
- * length.
- */
- public Vector add(Vector other)
- {
- if (!(other instanceof GF2Vector))
- {
- throw new ArithmeticException("vector is not defined over GF(2)");
- }
-
- GF2Vector otherVec = (GF2Vector)other;
- if (length != otherVec.length)
- {
- throw new ArithmeticException("length mismatch");
- }
-
- int[] vec = IntUtils.clone(((GF2Vector)other).v);
-
- for (int i = vec.length - 1; i >= 0; i--)
- {
- vec[i] ^= v[i];
- }
-
- return new GF2Vector(length, vec);
- }
-
- /**
- * Multiply this vector with a permutation.
- *
- * @param p the permutation
- * @return <tt>this*p = p*this</tt>
- */
- public Vector multiply(Permutation p)
- {
- int[] pVec = p.getVector();
- if (length != pVec.length)
- {
- throw new ArithmeticException("length mismatch");
- }
-
- GF2Vector result = new GF2Vector(length);
-
- for (int i = 0; i < pVec.length; i++)
- {
- int e = v[pVec[i] >> 5] & (1 << (pVec[i] & 0x1f));
- if (e != 0)
- {
- result.v[i >> 5] |= 1 << (i & 0x1f);
- }
- }
-
- return result;
- }
-
- /**
- * Return a new vector consisting of the elements of this vector with the
- * indices given by the set <tt>setJ</tt>.
- *
- * @param setJ the set of indices of elements to extract
- * @return the new {@link GF2Vector}
- * <tt>[this_setJ[0], this_setJ[1], ..., this_setJ[#setJ-1]]</tt>
- */
- public GF2Vector extractVector(int[] setJ)
- {
- int k = setJ.length;
- if (setJ[k - 1] > length)
- {
- throw new ArithmeticException("invalid index set");
- }
-
- GF2Vector result = new GF2Vector(k);
-
- for (int i = 0; i < k; i++)
- {
- int e = v[setJ[i] >> 5] & (1 << (setJ[i] & 0x1f));
- if (e != 0)
- {
- result.v[i >> 5] |= 1 << (i & 0x1f);
- }
- }
-
- return result;
- }
-
- /**
- * Return a new vector consisting of the first <tt>k</tt> elements of this
- * vector.
- *
- * @param k the number of elements to extract
- * @return a new {@link GF2Vector} consisting of the first <tt>k</tt>
- * elements of this vector
- */
- public GF2Vector extractLeftVector(int k)
- {
- if (k > length)
- {
- throw new ArithmeticException("invalid length");
- }
-
- if (k == length)
- {
- return new GF2Vector(this);
- }
-
- GF2Vector result = new GF2Vector(k);
-
- int q = k >> 5;
- int r = k & 0x1f;
-
- System.arraycopy(v, 0, result.v, 0, q);
- if (r != 0)
- {
- result.v[q] = v[q] & ((1 << r) - 1);
- }
-
- return result;
- }
-
- /**
- * Return a new vector consisting of the last <tt>k</tt> elements of this
- * vector.
- *
- * @param k the number of elements to extract
- * @return a new {@link GF2Vector} consisting of the last <tt>k</tt>
- * elements of this vector
- */
- public GF2Vector extractRightVector(int k)
- {
- if (k > length)
- {
- throw new ArithmeticException("invalid length");
- }
-
- if (k == length)
- {
- return new GF2Vector(this);
- }
-
- GF2Vector result = new GF2Vector(k);
-
- int q = (length - k) >> 5;
- int r = (length - k) & 0x1f;
- int length = (k + 31) >> 5;
-
- int ind = q;
- // if words have to be shifted
- if (r != 0)
- {
- // process all but last word
- for (int i = 0; i < length - 1; i++)
- {
- result.v[i] = (v[ind++] >>> r) | (v[ind] << (32 - r));
- }
- // process last word
- result.v[length - 1] = v[ind++] >>> r;
- if (ind < v.length)
- {
- result.v[length - 1] |= v[ind] << (32 - r);
- }
- }
- else
- {
- // no shift necessary
- System.arraycopy(v, q, result.v, 0, length);
- }
-
- return result;
- }
-
- /**
- * Rewrite this vector as a vector over <tt>GF(2<sup>m</sup>)</tt> with
- * <tt>t</tt> elements.
- *
- * @param field the finite field <tt>GF(2<sup>m</sup>)</tt>
- * @return the converted vector over <tt>GF(2<sup>m</sup>)</tt>
- */
- public GF2mVector toExtensionFieldVector(GF2mField field)
- {
- int m = field.getDegree();
- if ((length % m) != 0)
- {
- throw new ArithmeticException("conversion is impossible");
- }
-
- int t = length / m;
- int[] result = new int[t];
- int count = 0;
- for (int i = t - 1; i >= 0; i--)
- {
- for (int j = field.getDegree() - 1; j >= 0; j--)
- {
- int q = count >>> 5;
- int r = count & 0x1f;
-
- int e = (v[q] >>> r) & 1;
- if (e == 1)
- {
- result[i] ^= 1 << j;
- }
- count++;
- }
- }
- return new GF2mVector(field, result);
- }
-
- /**
- * Check if the given object is equal to this vector.
- *
- * @param other vector
- * @return the result of the comparison
- */
- public boolean equals(Object other)
- {
-
- if (!(other instanceof GF2Vector))
- {
- return false;
- }
- GF2Vector otherVec = (GF2Vector)other;
-
- return (length == otherVec.length) && IntUtils.equals(v, otherVec.v);
- }
-
- /**
- * @return the hash code of this vector
- */
- public int hashCode()
- {
- int hash = length;
- hash = hash * 31 + v.hashCode();
- return hash;
- }
-
- /**
- * @return a human readable form of this vector
- */
- public String toString()
- {
- StringBuffer buf = new StringBuffer();
- for (int i = 0; i < length; i++)
- {
- if ((i != 0) && ((i & 0x1f) == 0))
- {
- buf.append(' ');
- }
- int q = i >> 5;
- int r = i & 0x1f;
- int bit = v[q] & (1 << r);
- if (bit == 0)
- {
- buf.append('0');
- }
- else
- {
- buf.append('1');
- }
- }
- return buf.toString();
- }
-
-}
diff --git a/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2mField.java b/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2mField.java
deleted file mode 100644
index f5f7b64..0000000
--- a/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2mField.java
+++ /dev/null
@@ -1,369 +0,0 @@
-package org.bouncycastle.pqc.math.linearalgebra;
-
-import java.security.SecureRandom;
-
-/**
- * This class describes operations with elements from the finite field F =
- * GF(2^m). ( GF(2^m)= GF(2)[A] where A is a root of irreducible polynomial with
- * degree m, each field element B has a polynomial basis representation, i.e. it
- * is represented by a different binary polynomial of degree less than m, B =
- * poly(A) ) All operations are defined only for field with 1&lt; m &lt;32. For the
- * representation of field elements the map f: F-&gt;Z, poly(A)-&gt;poly(2) is used,
- * where integers have the binary representation. For example: A^7+A^3+A+1 -&gt;
- * (00...0010001011)=139 Also for elements type Integer is used.
- *
- * @see PolynomialRingGF2
- */
-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 IllegalArgumentException(
- " Error: the degree of field is too large ");
- }
- if (degree < 1)
- {
- throw new IllegalArgumentException(
- " 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 IllegalArgumentException(
- " Error: the degree is not correct");
- }
- if (!PolynomialRingGF2.isIrreducible(poly))
- {
- throw new IllegalArgumentException(
- " Error: given polynomial is reducible");
- }
- this.degree = degree;
- polynomial = poly;
-
- }
-
- public GF2mField(byte[] enc)
- {
- if (enc.length != 4)
- {
- throw new IllegalArgumentException(
- "byte array is not an encoded finite field");
- }
- polynomial = LittleEndianConversions.OS2IP(enc);
- if (!PolynomialRingGF2.isIrreducible(polynomial))
- {
- throw new IllegalArgumentException(
- "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;
- }
- 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(new SecureRandom());
- }
-
- /**
- * 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 boolean 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;
- }
- 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 boolean equals(Object other)
- {
- if ((other == null) || !(other instanceof 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;
- int i = 1;
- while (p != 0)
- {
- b = (byte)(p & 0x01);
- if (b == 1)
- {
- str = str + "+x^" + i;
- }
- p >>>= 1;
- i++;
- }
- }
- return str;
- }
-
-}
diff --git a/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2mMatrix.java b/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2mMatrix.java
deleted file mode 100644
index 8dfdb9b..0000000
--- a/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2mMatrix.java
+++ /dev/null
@@ -1,377 +0,0 @@
-package org.bouncycastle.pqc.math.linearalgebra;
-
-/**
- * This class describes some operations with matrices over finite field <i>GF(2<sup>m</sup>)</i>
- * with small <i>m</i> (1&lt; m &lt;32).
- *
- * @see Matrix
- */
-public class GF2mMatrix
- extends Matrix
-{
-
- /**
- * finite field GF(2^m)
- */
- protected GF2mField field;
-
- /**
- * For the matrix representation the array of type int[][] is used, thus
- * every element of the array keeps one element of the matrix (element from
- * finite field GF(2^m))
- */
- protected int[][] matrix;
-
- /**
- * Constructor.
- *
- * @param field a finite field GF(2^m)
- * @param enc byte[] matrix in byte array form
- */
- public GF2mMatrix(GF2mField field, byte[] enc)
- {
-
- this.field = field;
-
- // decode matrix
- int d = 8;
- int count = 1;
- while (field.getDegree() > d)
- {
- count++;
- d += 8;
- }
-
- if (enc.length < 5)
- {
- throw new IllegalArgumentException(
- " Error: given array is not encoded matrix over GF(2^m)");
- }
-
- this.numRows = ((enc[3] & 0xff) << 24) ^ ((enc[2] & 0xff) << 16)
- ^ ((enc[1] & 0xff) << 8) ^ (enc[0] & 0xff);
-
- int n = count * this.numRows;
-
- if ((this.numRows <= 0) || (((enc.length - 4) % n) != 0))
- {
- throw new IllegalArgumentException(
- " Error: given array is not encoded matrix over GF(2^m)");
- }
-
- this.numColumns = (enc.length - 4) / n;
-
- matrix = new int[this.numRows][this.numColumns];
- count = 4;
- for (int i = 0; i < this.numRows; i++)
- {
- for (int j = 0; j < this.numColumns; j++)
- {
- for (int jj = 0; jj < d; jj += 8)
- {
- matrix[i][j] ^= (enc[count++] & 0x000000ff) << jj;
- }
- if (!this.field.isElementOfThisField(matrix[i][j]))
- {
- throw new IllegalArgumentException(
- " Error: given array is not encoded matrix over GF(2^m)");
- }
- }
- }
- }
-
- /**
- * Copy constructor.
- *
- * @param other another {@link GF2mMatrix}
- */
- public GF2mMatrix(GF2mMatrix other)
- {
- numRows = other.numRows;
- numColumns = other.numColumns;
- field = other.field;
- matrix = new int[numRows][];
- for (int i = 0; i < numRows; i++)
- {
- matrix[i] = IntUtils.clone(other.matrix[i]);
- }
- }
-
- /**
- * Constructor.
- *
- * @param field a finite field GF(2^m)
- * @param matrix the matrix as int array. Only the reference is copied.
- */
- protected GF2mMatrix(GF2mField field, int[][] matrix)
- {
- this.field = field;
- this.matrix = matrix;
- numRows = matrix.length;
- numColumns = matrix[0].length;
- }
-
- /**
- * @return a byte array encoding of this matrix
- */
- public byte[] getEncoded()
- {
- int d = 8;
- int count = 1;
- while (field.getDegree() > d)
- {
- count++;
- d += 8;
- }
-
- byte[] bf = new byte[this.numRows * this.numColumns * count + 4];
- bf[0] = (byte)(this.numRows & 0xff);
- bf[1] = (byte)((this.numRows >>> 8) & 0xff);
- bf[2] = (byte)((this.numRows >>> 16) & 0xff);
- bf[3] = (byte)((this.numRows >>> 24) & 0xff);
-
- count = 4;
- for (int i = 0; i < this.numRows; i++)
- {
- for (int j = 0; j < this.numColumns; j++)
- {
- for (int jj = 0; jj < d; jj += 8)
- {
- bf[count++] = (byte)(matrix[i][j] >>> jj);
- }
- }
- }
-
- return bf;
- }
-
- /**
- * Check if this is the zero matrix (i.e., all entries are zero).
- *
- * @return <tt>true</tt> if this is the zero matrix
- */
- public boolean isZero()
- {
- for (int i = 0; i < numRows; i++)
- {
- for (int j = 0; j < numColumns; j++)
- {
- if (matrix[i][j] != 0)
- {
- return false;
- }
- }
- }
- return true;
- }
-
- /**
- * Compute the inverse of this matrix.
- *
- * @return the inverse of this matrix (newly created).
- */
- public Matrix computeInverse()
- {
- if (numRows != numColumns)
- {
- throw new ArithmeticException("Matrix is not invertible.");
- }
-
- // clone this matrix
- int[][] tmpMatrix = new int[numRows][numRows];
- for (int i = numRows - 1; i >= 0; i--)
- {
- tmpMatrix[i] = IntUtils.clone(matrix[i]);
- }
-
- // initialize inverse matrix as unit matrix
- int[][] invMatrix = new int[numRows][numRows];
- for (int i = numRows - 1; i >= 0; i--)
- {
- invMatrix[i][i] = 1;
- }
-
- // simultaneously compute Gaussian reduction of tmpMatrix and unit
- // matrix
- for (int i = 0; i < numRows; i++)
- {
- // if diagonal element is zero
- if (tmpMatrix[i][i] == 0)
- {
- boolean foundNonZero = false;
- // find a non-zero element in the same column
- for (int j = i + 1; j < numRows; j++)
- {
- if (tmpMatrix[j][i] != 0)
- {
- // found it, swap rows ...
- foundNonZero = true;
- swapColumns(tmpMatrix, i, j);
- swapColumns(invMatrix, i, j);
- // ... and quit searching
- j = numRows;
- continue;
- }
- }
- // if no non-zero element was found
- if (!foundNonZero)
- {
- // the matrix is not invertible
- throw new ArithmeticException("Matrix is not invertible.");
- }
- }
-
- // normalize i-th row
- int coef = tmpMatrix[i][i];
- int invCoef = field.inverse(coef);
- multRowWithElementThis(tmpMatrix[i], invCoef);
- multRowWithElementThis(invMatrix[i], invCoef);
-
- // normalize all other rows
- for (int j = 0; j < numRows; j++)
- {
- if (j != i)
- {
- coef = tmpMatrix[j][i];
- if (coef != 0)
- {
- int[] tmpRow = multRowWithElement(tmpMatrix[i], coef);
- int[] tmpInvRow = multRowWithElement(invMatrix[i], coef);
- addToRow(tmpRow, tmpMatrix[j]);
- addToRow(tmpInvRow, invMatrix[j]);
- }
- }
- }
- }
-
- return new GF2mMatrix(field, invMatrix);
- }
-
- private static void swapColumns(int[][] matrix, int first, int second)
- {
- int[] tmp = matrix[first];
- matrix[first] = matrix[second];
- matrix[second] = tmp;
- }
-
- private void multRowWithElementThis(int[] row, int element)
- {
- for (int i = row.length - 1; i >= 0; i--)
- {
- row[i] = field.mult(row[i], element);
- }
- }
-
- private int[] multRowWithElement(int[] row, int element)
- {
- int[] result = new int[row.length];
- for (int i = row.length - 1; i >= 0; i--)
- {
- result[i] = field.mult(row[i], element);
- }
- return result;
- }
-
- /**
- * Add one row to another.
- *
- * @param fromRow the addend
- * @param toRow the row to add to
- */
- private void addToRow(int[] fromRow, int[] toRow)
- {
- for (int i = toRow.length - 1; i >= 0; i--)
- {
- toRow[i] = field.add(fromRow[i], toRow[i]);
- }
- }
-
- public Matrix rightMultiply(Matrix a)
- {
- throw new RuntimeException("Not implemented.");
- }
-
- public Matrix rightMultiply(Permutation perm)
- {
- throw new RuntimeException("Not implemented.");
- }
-
- public Vector leftMultiply(Vector vector)
- {
- throw new RuntimeException("Not implemented.");
- }
-
- public Vector rightMultiply(Vector vector)
- {
- throw new RuntimeException("Not implemented.");
- }
-
- /**
- * Checks if given object is equal to this matrix. The method returns false
- * whenever the given object is not a matrix over GF(2^m).
- *
- * @param other object
- * @return true or false
- */
- public boolean equals(Object other)
- {
-
- if (other == null || !(other instanceof GF2mMatrix))
- {
- return false;
- }
-
- GF2mMatrix otherMatrix = (GF2mMatrix)other;
-
- if ((!this.field.equals(otherMatrix.field))
- || (otherMatrix.numRows != this.numColumns)
- || (otherMatrix.numColumns != this.numColumns))
- {
- return false;
- }
-
- for (int i = 0; i < this.numRows; i++)
- {
- for (int j = 0; j < this.numColumns; j++)
- {
- if (this.matrix[i][j] != otherMatrix.matrix[i][j])
- {
- return false;
- }
- }
- }
-
- return true;
- }
-
- public int hashCode()
- {
- int hash = (this.field.hashCode() * 31 + numRows) * 31 + numColumns;
- for (int i = 0; i < this.numRows; i++)
- {
- for (int j = 0; j < this.numColumns; j++)
- {
- hash = hash * 31 + matrix[i][j];
- }
- }
- return hash;
- }
-
- public String toString()
- {
- String str = this.numRows + " x " + this.numColumns + " Matrix over "
- + this.field.toString() + ": \n";
-
- for (int i = 0; i < this.numRows; i++)
- {
- for (int j = 0; j < this.numColumns; j++)
- {
- str = str + this.field.elementToStr(matrix[i][j]) + " : ";
- }
- str = str + "\n";
- }
-
- return str;
- }
-
-}
diff --git a/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2mVector.java b/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2mVector.java
deleted file mode 100644
index f2527f6..0000000
--- a/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2mVector.java
+++ /dev/null
@@ -1,256 +0,0 @@
-package 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&lt;m&lt;32</tt>). It extends the abstract class {@link Vector}.
- */
-public class GF2mVector
- extends 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 IllegalArgumentException(
- "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 IllegalArgumentException(
- "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 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)(vector[i] >>> j);
- }
- }
-
- return res;
- }
-
- /**
- * @return whether this is the zero vector (i.e., all elements are zero)
- */
- public boolean 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 Vector add(Vector addend)
- {
- throw new RuntimeException("not implemented");
- }
-
- /**
- * Multiply this vector with a permutation.
- *
- * @param p the permutation
- * @return <tt>this*p = p*this</tt>
- */
- public 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 boolean equals(Object other)
- {
-
- if (!(other instanceof GF2mVector))
- {
- return false;
- }
- GF2mVector otherVec = (GF2mVector)other;
-
- if (!field.equals(otherVec.field))
- {
- return false;
- }
-
- return IntUtils.equals(vector, otherVec.vector);
- }
-
- /**
- * @return the hash code of this vector
- */
- public int hashCode()
- {
- int hash = this.field.hashCode();
- hash = hash * 31 + vector.hashCode();
- return hash;
- }
-
- /**
- * @return a human readable form of this vector
- */
- public String toString()
- {
- StringBuffer buf = new StringBuffer();
- for (int i = 0; i < vector.length; i++)
- {
- for (int j = 0; j < field.getDegree(); j++)
- {
- int r = j & 0x1f;
- int bitMask = 1 << r;
- int coeff = vector[i] & bitMask;
- if (coeff != 0)
- {
- buf.append('1');
- }
- else
- {
- buf.append('0');
- }
- }
- buf.append(' ');
- }
- return buf.toString();
- }
-
-}
diff --git a/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2nElement.java b/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2nElement.java
deleted file mode 100644
index faa99dc..0000000
--- a/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2nElement.java
+++ /dev/null
@@ -1,186 +0,0 @@
-package org.bouncycastle.pqc.math.linearalgebra;
-
-
-/**
- * This abstract class implements an element of the finite field <i>GF(2)<sup>n
- * </sup></i> in either <i>optimal normal basis</i> representation (<i>ONB</i>)
- * or in <i>polynomial</i> representation. It is extended by the classes <a
- * href = GF2nONBElement.html><tt> GF2nONBElement</tt></a> and <a href =
- * GF2nPolynomialElement.html> <tt>GF2nPolynomialElement</tt> </a>.
- *
- * @see GF2nPolynomialElement
- * @see GF2nONBElement
- * @see GF2nONBField
- */
-public abstract class GF2nElement
- implements GFElement
-{
-
- // /////////////////////////////////////////////////////////////////////
- // member variables
- // /////////////////////////////////////////////////////////////////////
-
- /**
- * holds a pointer to this element's corresponding field.
- */
- protected GF2nField mField;
-
- /**
- * holds the extension degree <i>n</i> of this element's corresponding
- * field.
- */
- protected int mDegree;
-
- // /////////////////////////////////////////////////////////////////////
- // pseudo-constructors
- // /////////////////////////////////////////////////////////////////////
-
- /**
- * @return a copy of this GF2nElement
- */
- public abstract Object clone();
-
- // /////////////////////////////////////////////////////////////////////
- // assignments
- // /////////////////////////////////////////////////////////////////////
-
- /**
- * Assign the value 0 to this element.
- */
- abstract void assignZero();
-
- /**
- * Assigns the value 1 to this element.
- */
- abstract void assignOne();
-
- // /////////////////////////////////////////////////////////////////////
- // access
- // /////////////////////////////////////////////////////////////////////
-
- /**
- * Returns whether the rightmost bit of the bit representation is set. This
- * is needed for data conversion according to 1363.
- *
- * @return true if the rightmost bit of this element is set
- */
- public abstract boolean testRightmostBit();
-
- /**
- * Checks whether the indexed bit of the bit representation is set
- *
- * @param index the index of the bit to test
- * @return <tt>true</tt> if the indexed bit is set
- */
- abstract boolean testBit(int index);
-
- /**
- * Returns the field of this element.
- *
- * @return the field of this element
- */
- public final GF2nField getField()
- {
- return mField;
- }
-
- // /////////////////////////////////////////////////////////////////////
- // arithmetic
- // /////////////////////////////////////////////////////////////////////
-
- /**
- * Returns <tt>this</tt> element + 1.
- *
- * @return <tt>this</tt> + 1
- */
- public abstract GF2nElement increase();
-
- /**
- * Increases this element by one.
- */
- public abstract void increaseThis();
-
- /**
- * Compute the difference of this element and <tt>minuend</tt>.
- *
- * @param minuend the minuend
- * @return <tt>this - minuend</tt> (newly created)
- * @throws DifferentFieldsException if the elements are of different fields.
- */
- public final GFElement subtract(GFElement minuend)
- throws RuntimeException
- {
- return add(minuend);
- }
-
- /**
- * Compute the difference of this element and <tt>minuend</tt>,
- * overwriting this element.
- *
- * @param minuend the minuend
- * @throws DifferentFieldsException if the elements are of different fields.
- */
- public final void subtractFromThis(GFElement minuend)
- {
- addToThis(minuend);
- }
-
- /**
- * Returns <tt>this</tt> element to the power of 2.
- *
- * @return <tt>this</tt><sup>2</sup>
- */
- public abstract GF2nElement square();
-
- /**
- * Squares <tt>this</tt> element.
- */
- public abstract void squareThis();
-
- /**
- * Compute the square root of this element and return the result in a new
- * {@link GF2nElement}.
- *
- * @return <tt>this<sup>1/2</sup></tt> (newly created)
- */
- public abstract GF2nElement squareRoot();
-
- /**
- * Compute the square root of this element.
- */
- public abstract void squareRootThis();
-
- /**
- * Performs a basis transformation of this element to the given GF2nField
- * <tt>basis</tt>.
- *
- * @param basis the GF2nField representation to transform this element to
- * @return this element in the representation of <tt>basis</tt>
- * @throws DifferentFieldsException if <tt>this</tt> cannot be converted according to
- * <tt>basis</tt>.
- */
- public final GF2nElement convert(GF2nField basis)
- throws RuntimeException
- {
- return mField.convert(this, basis);
- }
-
- /**
- * Returns the trace of this element.
- *
- * @return the trace of this element
- */
- public abstract int trace();
-
- /**
- * Solves a quadratic equation.<br>
- * Let z<sup>2</sup> + z = <tt>this</tt>. Then this method returns z.
- *
- * @return z with z<sup>2</sup> + z = <tt>this</tt>
- * @throws NoSolutionException if z<sup>2</sup> + z = <tt>this</tt> does not have a
- * solution
- */
- public abstract GF2nElement solveQuadraticEquation()
- throws RuntimeException;
-
-}
diff --git a/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2nField.java b/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2nField.java
deleted file mode 100644
index 907afd7..0000000
--- a/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2nField.java
+++ /dev/null
@@ -1,292 +0,0 @@
-package org.bouncycastle.pqc.math.linearalgebra;
-
-
-import java.util.Vector;
-
-
-/**
- * This abstract class defines the finite field <i>GF(2<sup>n</sup>)</i>. It
- * holds the extension degree <i>n</i>, the characteristic, the irreducible
- * fieldpolynomial and conversion matrices. GF2nField is implemented by the
- * classes GF2nPolynomialField and GF2nONBField.
- *
- * @see GF2nONBField
- * @see GF2nPolynomialField
- */
-public abstract class GF2nField
-{
-
- /**
- * the degree of this field
- */
- protected int mDegree;
-
- /**
- * the irreducible fieldPolynomial stored in normal order (also for ONB)
- */
- protected GF2Polynomial fieldPolynomial;
-
- /**
- * holds a list of GF2nFields to which elements have been converted and thus
- * a COB-Matrix exists
- */
- protected Vector fields;
-
- /**
- * the COB matrices
- */
- protected Vector matrices;
-
- /**
- * Returns the degree <i>n</i> of this field.
- *
- * @return the degree <i>n</i> of this field
- */
- public final int getDegree()
- {
- return mDegree;
- }
-
- /**
- * Returns the fieldpolynomial as a new Bitstring.
- *
- * @return a copy of the fieldpolynomial as a new Bitstring
- */
- public final GF2Polynomial getFieldPolynomial()
- {
- if (fieldPolynomial == null)
- {
- computeFieldPolynomial();
- }
- return new GF2Polynomial(fieldPolynomial);
- }
-
- /**
- * Decides whether the given object <tt>other</tt> is the same as this
- * field.
- *
- * @param other another object
- * @return (this == other)
- */
- public final boolean equals(Object other)
- {
- if (other == null || !(other instanceof GF2nField))
- {
- return false;
- }
-
- GF2nField otherField = (GF2nField)other;
-
- if (otherField.mDegree != mDegree)
- {
- return false;
- }
- if (!fieldPolynomial.equals(otherField.fieldPolynomial))
- {
- return false;
- }
- if ((this instanceof GF2nPolynomialField)
- && !(otherField instanceof GF2nPolynomialField))
- {
- return false;
- }
- if ((this instanceof GF2nONBField)
- && !(otherField instanceof GF2nONBField))
- {
- return false;
- }
- return true;
- }
-
- /**
- * @return the hash code of this field
- */
- public int hashCode()
- {
- return mDegree + fieldPolynomial.hashCode();
- }
-
- /**
- * Computes a random root from the given irreducible fieldpolynomial
- * according to IEEE 1363 algorithm A.5.6. This cal take very long for big
- * degrees.
- *
- * @param B0FieldPolynomial the fieldpolynomial if the other basis as a Bitstring
- * @return a random root of BOFieldPolynomial in representation according to
- * this field
- * @see "P1363 A.5.6, p103f"
- */
- protected abstract GF2nElement getRandomRoot(GF2Polynomial B0FieldPolynomial);
-
- /**
- * Computes the change-of-basis matrix for basis conversion according to
- * 1363. The result is stored in the lists fields and matrices.
- *
- * @param B1 the GF2nField to convert to
- * @see "P1363 A.7.3, p111ff"
- */
- protected abstract void computeCOBMatrix(GF2nField B1);
-
- /**
- * Computes the fieldpolynomial. This can take a long time for big degrees.
- */
- protected abstract void computeFieldPolynomial();
-
- /**
- * Inverts the given matrix represented as bitstrings.
- *
- * @param matrix the matrix to invert as a Bitstring[]
- * @return matrix^(-1)
- */
- protected final GF2Polynomial[] invertMatrix(GF2Polynomial[] matrix)
- {
- GF2Polynomial[] a = new GF2Polynomial[matrix.length];
- GF2Polynomial[] inv = new GF2Polynomial[matrix.length];
- GF2Polynomial dummy;
- int i, j;
- // initialize a as a copy of matrix and inv as E(inheitsmatrix)
- for (i = 0; i < mDegree; i++)
- {
- try
- {
- a[i] = new GF2Polynomial(matrix[i]);
- inv[i] = new GF2Polynomial(mDegree);
- inv[i].setBit(mDegree - 1 - i);
- }
- catch (RuntimeException BDNEExc)
- {
- BDNEExc.printStackTrace();
- }
- }
- // construct triangle matrix so that for each a[i] the first i bits are
- // zero
- for (i = 0; i < mDegree - 1; i++)
- {
- // find column where bit i is set
- j = i;
- while ((j < mDegree) && !a[j].testBit(mDegree - 1 - i))
- {
- j++;
- }
- if (j >= mDegree)
- {
- throw new RuntimeException(
- "GF2nField.invertMatrix: Matrix cannot be inverted!");
- }
- if (i != j)
- { // swap a[i]/a[j] and inv[i]/inv[j]
- dummy = a[i];
- a[i] = a[j];
- a[j] = dummy;
- dummy = inv[i];
- inv[i] = inv[j];
- inv[j] = dummy;
- }
- for (j = i + 1; j < mDegree; j++)
- { // add column i to all columns>i
- // having their i-th bit set
- if (a[j].testBit(mDegree - 1 - i))
- {
- a[j].addToThis(a[i]);
- inv[j].addToThis(inv[i]);
- }
- }
- }
- // construct Einheitsmatrix from a
- for (i = mDegree - 1; i > 0; i--)
- {
- for (j = i - 1; j >= 0; j--)
- { // eliminate the i-th bit in all
- // columns < i
- if (a[j].testBit(mDegree - 1 - i))
- {
- a[j].addToThis(a[i]);
- inv[j].addToThis(inv[i]);
- }
- }
- }
- return inv;
- }
-
- /**
- * Converts the given element in representation according to this field to a
- * new element in representation according to B1 using the change-of-basis
- * matrix calculated by computeCOBMatrix.
- *
- * @param elem the GF2nElement to convert
- * @param basis the basis to convert <tt>elem</tt> to
- * @return <tt>elem</tt> converted to a new element representation
- * according to <tt>basis</tt>
- * @throws DifferentFieldsException if <tt>elem</tt> cannot be converted according to
- * <tt>basis</tt>.
- * @see GF2nField#computeCOBMatrix
- * @see GF2nField#getRandomRoot
- * @see GF2nPolynomial
- * @see "P1363 A.7 p109ff"
- */
- public final GF2nElement convert(GF2nElement elem, GF2nField basis)
- throws RuntimeException
- {
- if (basis == this)
- {
- return (GF2nElement)elem.clone();
- }
- if (fieldPolynomial.equals(basis.fieldPolynomial))
- {
- return (GF2nElement)elem.clone();
- }
- if (mDegree != basis.mDegree)
- {
- throw new RuntimeException("GF2nField.convert: B1 has a"
- + " different degree and thus cannot be coverted to!");
- }
-
- int i;
- GF2Polynomial[] COBMatrix;
- i = fields.indexOf(basis);
- if (i == -1)
- {
- computeCOBMatrix(basis);
- i = fields.indexOf(basis);
- }
- COBMatrix = (GF2Polynomial[])matrices.elementAt(i);
-
- GF2nElement elemCopy = (GF2nElement)elem.clone();
- if (elemCopy instanceof GF2nONBElement)
- {
- // remember: ONB treats its bits in reverse order
- ((GF2nONBElement)elemCopy).reverseOrder();
- }
- GF2Polynomial bs = new GF2Polynomial(mDegree, elemCopy.toFlexiBigInt());
- bs.expandN(mDegree);
- GF2Polynomial result = new GF2Polynomial(mDegree);
- for (i = 0; i < mDegree; i++)
- {
- if (bs.vectorMult(COBMatrix[i]))
- {
- result.setBit(mDegree - 1 - i);
- }
- }
- if (basis instanceof GF2nPolynomialField)
- {
- return new GF2nPolynomialElement((GF2nPolynomialField)basis,
- result);
- }
- else if (basis instanceof GF2nONBField)
- {
- GF2nONBElement res = new GF2nONBElement((GF2nONBField)basis,
- result.toFlexiBigInt());
- // TODO Remember: ONB treats its Bits in reverse order !!!
- res.reverseOrder();
- return res;
- }
- else
- {
- throw new RuntimeException(
- "GF2nField.convert: B1 must be an instance of "
- + "GF2nPolynomialField or GF2nONBField!");
- }
-
- }
-
-}
diff --git a/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2nONBElement.java b/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2nONBElement.java
deleted file mode 100644
index 8b4b473..0000000
--- a/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2nONBElement.java
+++ /dev/null
@@ -1,1154 +0,0 @@
-package org.bouncycastle.pqc.math.linearalgebra;
-
-
-import java.math.BigInteger;
-import java.util.Random;
-
-/**
- * This class implements an element of the finite field <i>GF(2<sup>n </sup>)</i>.
- * It is represented in an optimal normal basis representation and holds the
- * pointer <tt>mField</tt> to its corresponding field.
- *
- * @see GF2nField
- * @see GF2nElement
- */
-public class GF2nONBElement
- extends GF2nElement
-{
-
- // /////////////////////////////////////////////////////////////////////
- // member variables
- // /////////////////////////////////////////////////////////////////////
-
- private static final long[] mBitmask = new long[]{0x0000000000000001L,
- 0x0000000000000002L, 0x0000000000000004L, 0x0000000000000008L,
- 0x0000000000000010L, 0x0000000000000020L, 0x0000000000000040L,
- 0x0000000000000080L, 0x0000000000000100L, 0x0000000000000200L,
- 0x0000000000000400L, 0x0000000000000800L, 0x0000000000001000L,
- 0x0000000000002000L, 0x0000000000004000L, 0x0000000000008000L,
- 0x0000000000010000L, 0x0000000000020000L, 0x0000000000040000L,
- 0x0000000000080000L, 0x0000000000100000L, 0x0000000000200000L,
- 0x0000000000400000L, 0x0000000000800000L, 0x0000000001000000L,
- 0x0000000002000000L, 0x0000000004000000L, 0x0000000008000000L,
- 0x0000000010000000L, 0x0000000020000000L, 0x0000000040000000L,
- 0x0000000080000000L, 0x0000000100000000L, 0x0000000200000000L,
- 0x0000000400000000L, 0x0000000800000000L, 0x0000001000000000L,
- 0x0000002000000000L, 0x0000004000000000L, 0x0000008000000000L,
- 0x0000010000000000L, 0x0000020000000000L, 0x0000040000000000L,
- 0x0000080000000000L, 0x0000100000000000L, 0x0000200000000000L,
- 0x0000400000000000L, 0x0000800000000000L, 0x0001000000000000L,
- 0x0002000000000000L, 0x0004000000000000L, 0x0008000000000000L,
- 0x0010000000000000L, 0x0020000000000000L, 0x0040000000000000L,
- 0x0080000000000000L, 0x0100000000000000L, 0x0200000000000000L,
- 0x0400000000000000L, 0x0800000000000000L, 0x1000000000000000L,
- 0x2000000000000000L, 0x4000000000000000L, 0x8000000000000000L};
-
- private static final long[] mMaxmask = new long[]{0x0000000000000001L,
- 0x0000000000000003L, 0x0000000000000007L, 0x000000000000000FL,
- 0x000000000000001FL, 0x000000000000003FL, 0x000000000000007FL,
- 0x00000000000000FFL, 0x00000000000001FFL, 0x00000000000003FFL,
- 0x00000000000007FFL, 0x0000000000000FFFL, 0x0000000000001FFFL,
- 0x0000000000003FFFL, 0x0000000000007FFFL, 0x000000000000FFFFL,
- 0x000000000001FFFFL, 0x000000000003FFFFL, 0x000000000007FFFFL,
- 0x00000000000FFFFFL, 0x00000000001FFFFFL, 0x00000000003FFFFFL,
- 0x00000000007FFFFFL, 0x0000000000FFFFFFL, 0x0000000001FFFFFFL,
- 0x0000000003FFFFFFL, 0x0000000007FFFFFFL, 0x000000000FFFFFFFL,
- 0x000000001FFFFFFFL, 0x000000003FFFFFFFL, 0x000000007FFFFFFFL,
- 0x00000000FFFFFFFFL, 0x00000001FFFFFFFFL, 0x00000003FFFFFFFFL,
- 0x00000007FFFFFFFFL, 0x0000000FFFFFFFFFL, 0x0000001FFFFFFFFFL,
- 0x0000003FFFFFFFFFL, 0x0000007FFFFFFFFFL, 0x000000FFFFFFFFFFL,
- 0x000001FFFFFFFFFFL, 0x000003FFFFFFFFFFL, 0x000007FFFFFFFFFFL,
- 0x00000FFFFFFFFFFFL, 0x00001FFFFFFFFFFFL, 0x00003FFFFFFFFFFFL,
- 0x00007FFFFFFFFFFFL, 0x0000FFFFFFFFFFFFL, 0x0001FFFFFFFFFFFFL,
- 0x0003FFFFFFFFFFFFL, 0x0007FFFFFFFFFFFFL, 0x000FFFFFFFFFFFFFL,
- 0x001FFFFFFFFFFFFFL, 0x003FFFFFFFFFFFFFL, 0x007FFFFFFFFFFFFFL,
- 0x00FFFFFFFFFFFFFFL, 0x01FFFFFFFFFFFFFFL, 0x03FFFFFFFFFFFFFFL,
- 0x07FFFFFFFFFFFFFFL, 0x0FFFFFFFFFFFFFFFL, 0x1FFFFFFFFFFFFFFFL,
- 0x3FFFFFFFFFFFFFFFL, 0x7FFFFFFFFFFFFFFFL, 0xFFFFFFFFFFFFFFFFL};
-
- // mIBy64[j * 16 + i] = (j * 16 + i)/64
- // i =
- // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
- //
- private static final int[] mIBY64 = new int[]{
- // j =
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 8
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 9
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 10
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 11
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 12
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 13
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 14
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 15
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, // 16
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, // 17
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, // 18
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, // 19
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, // 20
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, // 21
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, // 22
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 // 23
- };
-
- private static final int MAXLONG = 64;
-
- /**
- * holds the lenght of the polynomial with 64 bit sized fields.
- */
- private int mLength;
-
- /**
- * holds the value of mDeg % MAXLONG.
- */
- private int mBit;
-
- /**
- * holds this element in ONB representation.
- */
- private long[] mPol;
-
- // /////////////////////////////////////////////////////////////////////
- // constructors
- // /////////////////////////////////////////////////////////////////////
-
- /**
- * Construct a random element over the field <tt>gf2n</tt>, using the
- * specified source of randomness.
- *
- * @param gf2n the field
- * @param rand the source of randomness
- */
- public GF2nONBElement(GF2nONBField gf2n, Random rand)
- {
- mField = gf2n;
- mDegree = mField.getDegree();
- mLength = gf2n.getONBLength();
- mBit = gf2n.getONBBit();
- mPol = new long[mLength];
- if (mLength > 1)
- {
- for (int j = 0; j < mLength - 1; j++)
- {
- mPol[j] = rand.nextLong();
- }
- long last = rand.nextLong();
- mPol[mLength - 1] = last >>> (MAXLONG - mBit);
- }
- else
- {
- mPol[0] = rand.nextLong();
- mPol[0] = mPol[0] >>> (MAXLONG - mBit);
- }
- }
-
- /**
- * Construct a new GF2nONBElement from its encoding.
- *
- * @param gf2n the field
- * @param e the encoded element
- */
- public GF2nONBElement(GF2nONBField gf2n, byte[] e)
- {
- mField = gf2n;
- mDegree = mField.getDegree();
- mLength = gf2n.getONBLength();
- mBit = gf2n.getONBBit();
- mPol = new long[mLength];
- assign(e);
- }
-
- /**
- * Construct the element of the field <tt>gf2n</tt> with the specified
- * value <tt>val</tt>.
- *
- * @param gf2n the field
- * @param val the value represented by a BigInteger
- */
- public GF2nONBElement(GF2nONBField gf2n, BigInteger val)
- {
- mField = gf2n;
- mDegree = mField.getDegree();
- mLength = gf2n.getONBLength();
- mBit = gf2n.getONBBit();
- mPol = new long[mLength];
- assign(val);
- }
-
- /**
- * Construct the element of the field <tt>gf2n</tt> with the specified
- * value <tt>val</tt>.
- *
- * @param gf2n the field
- * @param val the value in ONB representation
- */
- private GF2nONBElement(GF2nONBField gf2n, long[] val)
- {
- mField = gf2n;
- mDegree = mField.getDegree();
- mLength = gf2n.getONBLength();
- mBit = gf2n.getONBBit();
- mPol = val;
- }
-
- // /////////////////////////////////////////////////////////////////////
- // pseudo-constructors
- // /////////////////////////////////////////////////////////////////////
-
- /**
- * Copy constructor.
- *
- * @param gf2n the field
- */
- public GF2nONBElement(GF2nONBElement gf2n)
- {
-
- mField = gf2n.mField;
- mDegree = mField.getDegree();
- mLength = ((GF2nONBField)mField).getONBLength();
- mBit = ((GF2nONBField)mField).getONBBit();
- mPol = new long[mLength];
- assign(gf2n.getElement());
- }
-
- /**
- * Create a new GF2nONBElement by cloning this GF2nPolynomialElement.
- *
- * @return a copy of this element
- */
- public Object clone()
- {
- return new GF2nONBElement(this);
- }
-
- /**
- * Create the zero element.
- *
- * @param gf2n the finite field
- * @return the zero element in the given finite field
- */
- public static GF2nONBElement ZERO(GF2nONBField gf2n)
- {
- long[] polynomial = new long[gf2n.getONBLength()];
- return new GF2nONBElement(gf2n, polynomial);
- }
-
- /**
- * Create the one element.
- *
- * @param gf2n the finite field
- * @return the one element in the given finite field
- */
- public static GF2nONBElement ONE(GF2nONBField gf2n)
- {
- int mLength = gf2n.getONBLength();
- long[] polynomial = new long[mLength];
-
- // fill mDegree coefficients with one's
- for (int i = 0; i < mLength - 1; i++)
- {
- polynomial[i] = 0xffffffffffffffffL;
- }
- polynomial[mLength - 1] = mMaxmask[gf2n.getONBBit() - 1];
-
- return new GF2nONBElement(gf2n, polynomial);
- }
-
- // /////////////////////////////////////////////////////////////////////
- // assignments
- // /////////////////////////////////////////////////////////////////////
-
- /**
- * assigns to this element the zero element
- */
- void assignZero()
- {
- mPol = new long[mLength];
- }
-
- /**
- * assigns to this element the one element
- */
- void assignOne()
- {
- // fill mDegree coefficients with one's
- for (int i = 0; i < mLength - 1; i++)
- {
- mPol[i] = 0xffffffffffffffffL;
- }
- mPol[mLength - 1] = mMaxmask[mBit - 1];
- }
-
- /**
- * assigns to this element the value <tt>val</tt>.
- *
- * @param val the value represented by a BigInteger
- */
- private void assign(BigInteger val)
- {
- assign(val.toByteArray());
- }
-
- /**
- * assigns to this element the value <tt>val</tt>.
- *
- * @param val the value in ONB representation
- */
- private void assign(long[] val)
- {
- System.arraycopy(val, 0, mPol, 0, mLength);
- }
-
- /**
- * assigns to this element the value <tt>val</tt>. First: inverting the
- * order of val into reversed[]. That means: reversed[0] = val[length - 1],
- * ..., reversed[reversed.length - 1] = val[0]. Second: mPol[0] = sum{i = 0,
- * ... 7} (val[i]<<(i*8)) .... mPol[1] = sum{i = 8, ... 15} (val[i]<<(i*8))
- *
- * @param val the value in ONB representation
- */
- private void assign(byte[] val)
- {
- int j;
- mPol = new long[mLength];
- for (j = 0; j < val.length; j++)
- {
- mPol[j >>> 3] |= (val[val.length - 1 - j] & 0x00000000000000ffL) << ((j & 0x07) << 3);
- }
- }
-
- // /////////////////////////////////////////////////////////////////
- // comparison
- // /////////////////////////////////////////////////////////////////
-
- /**
- * Checks whether this element is zero.
- *
- * @return <tt>true</tt> if <tt>this</tt> is the zero element
- */
- public boolean isZero()
- {
-
- boolean result = true;
-
- for (int i = 0; i < mLength && result; i++)
- {
- result = result && ((mPol[i] & 0xFFFFFFFFFFFFFFFFL) == 0);
- }
-
- return result;
- }
-
- /**
- * Checks whether this element is one.
- *
- * @return <tt>true</tt> if <tt>this</tt> is the one element
- */
- public boolean isOne()
- {
-
- boolean result = true;
-
- for (int i = 0; i < mLength - 1 && result; i++)
- {
- result = result
- && ((mPol[i] & 0xFFFFFFFFFFFFFFFFL) == 0xFFFFFFFFFFFFFFFFL);
- }
-
- if (result)
- {
- result = result
- && ((mPol[mLength - 1] & mMaxmask[mBit - 1]) == mMaxmask[mBit - 1]);
- }
-
- return result;
- }
-
- /**
- * Compare this element with another object.
- *
- * @param other the other object
- * @return <tt>true</tt> if the two objects are equal, <tt>false</tt>
- * otherwise
- */
- public boolean equals(Object other)
- {
- if (other == null || !(other instanceof GF2nONBElement))
- {
- return false;
- }
-
- GF2nONBElement otherElem = (GF2nONBElement)other;
-
- for (int i = 0; i < mLength; i++)
- {
- if (mPol[i] != otherElem.mPol[i])
- {
- return false;
- }
- }
-
- return true;
- }
-
- /**
- * @return the hash code of this element
- */
- public int hashCode()
- {
- return mPol.hashCode();
- }
-
- // /////////////////////////////////////////////////////////////////////
- // access
- // /////////////////////////////////////////////////////////////////////
-
- /**
- * Returns whether the highest bit of the bit representation is set
- *
- * @return true, if the highest bit of mPol is set, false, otherwise
- */
- public boolean testRightmostBit()
- {
- // due to the reverse bit order (compared to 1363) this method returns
- // the value of the leftmost bit
- return (mPol[mLength - 1] & mBitmask[mBit - 1]) != 0L;
- }
-
- /**
- * Checks whether the indexed bit of the bit representation is set. Warning:
- * GF2nONBElement currently stores its bits in reverse order (compared to
- * 1363) !!!
- *
- * @param index the index of the bit to test
- * @return <tt>true</tt> if the indexed bit of mPol is set, <tt>false</tt>
- * otherwise.
- */
- boolean testBit(int index)
- {
- if (index < 0 || index > mDegree)
- {
- return false;
- }
- long test = mPol[index >>> 6] & mBitmask[index & 0x3f];
- return test != 0x0L;
- }
-
- /**
- * @return this element in its ONB representation
- */
- private long[] getElement()
- {
-
- long[] result = new long[mPol.length];
- System.arraycopy(mPol, 0, result, 0, mPol.length);
-
- return result;
- }
-
- /**
- * Returns the ONB representation of this element. The Bit-Order is
- * exchanged (according to 1363)!
- *
- * @return this element in its representation and reverse bit-order
- */
- private long[] getElementReverseOrder()
- {
- long[] result = new long[mPol.length];
- for (int i = 0; i < mDegree; i++)
- {
- if (testBit(mDegree - i - 1))
- {
- result[i >>> 6] |= mBitmask[i & 0x3f];
- }
- }
- return result;
- }
-
- /**
- * Reverses the bit-order in this element(according to 1363). This is a
- * hack!
- */
- void reverseOrder()
- {
- mPol = getElementReverseOrder();
- }
-
- // /////////////////////////////////////////////////////////////////////
- // arithmetic
- // /////////////////////////////////////////////////////////////////////
-
- /**
- * Compute the sum of this element and <tt>addend</tt>.
- *
- * @param addend the addend
- * @return <tt>this + other</tt> (newly created)
- * @throws DifferentFieldsException if the elements are of different fields.
- */
- public GFElement add(GFElement addend)
- throws RuntimeException
- {
- GF2nONBElement result = new GF2nONBElement(this);
- result.addToThis(addend);
- return result;
- }
-
- /**
- * Compute <tt>this + addend</tt> (overwrite <tt>this</tt>).
- *
- * @param addend the addend
- * @throws DifferentFieldsException if the elements are of different fields.
- */
- public void addToThis(GFElement addend)
- throws RuntimeException
- {
- if (!(addend instanceof GF2nONBElement))
- {
- throw new RuntimeException();
- }
- if (!mField.equals(((GF2nONBElement)addend).mField))
- {
- throw new RuntimeException();
- }
-
- for (int i = 0; i < mLength; i++)
- {
- mPol[i] ^= ((GF2nONBElement)addend).mPol[i];
- }
- }
-
- /**
- * returns <tt>this</tt> element + 1.
- *
- * @return <tt>this</tt> + 1
- */
- public GF2nElement increase()
- {
- GF2nONBElement result = new GF2nONBElement(this);
- result.increaseThis();
- return result;
- }
-
- /**
- * increases <tt>this</tt> element.
- */
- public void increaseThis()
- {
- addToThis(ONE((GF2nONBField)mField));
- }
-
- /**
- * Compute the product of this element and <tt>factor</tt>.
- *
- * @param factor the factor
- * @return <tt>this * factor</tt> (newly created)
- * @throws DifferentFieldsException if the elements are of different fields.
- */
- public GFElement multiply(GFElement factor)
- throws RuntimeException
- {
- GF2nONBElement result = new GF2nONBElement(this);
- result.multiplyThisBy(factor);
- return result;
- }
-
- /**
- * Compute <tt>this * factor</tt> (overwrite <tt>this</tt>).
- *
- * @param factor the factor
- * @throws DifferentFieldsException if the elements are of different fields.
- */
- public void multiplyThisBy(GFElement factor)
- throws RuntimeException
- {
-
- if (!(factor instanceof GF2nONBElement))
- {
- throw new RuntimeException("The elements have different"
- + " representation: not yet" + " implemented");
- }
- if (!mField.equals(((GF2nONBElement)factor).mField))
- {
- throw new RuntimeException();
- }
-
- if (equals(factor))
- {
- squareThis();
- }
- else
- {
-
- long[] a = mPol;
- long[] b = ((GF2nONBElement)factor).mPol;
- long[] c = new long[mLength];
-
- int[][] m = ((GF2nONBField)mField).mMult;
-
- int degf, degb, s, fielda, fieldb, bita, bitb;
- degf = mLength - 1;
- degb = mBit - 1;
- s = 0;
-
- long TWOTOMAXLONGM1 = mBitmask[MAXLONG - 1];
- long TWOTODEGB = mBitmask[degb];
-
- boolean old, now;
-
- // the product c of a and b (a*b = c) is calculated in mDegree
- // cicles
- // in every cicle one coefficient of c is calculated and stored
- // k indicates the coefficient
- //
- for (int k = 0; k < mDegree; k++)
- {
-
- s = 0;
-
- for (int i = 0; i < mDegree; i++)
- {
-
- // fielda = i / MAXLONG
- //
- fielda = mIBY64[i];
-
- // bita = i % MAXLONG
- //
- bita = i & (MAXLONG - 1);
-
- // fieldb = m[i][0] / MAXLONG
- //
- fieldb = mIBY64[m[i][0]];
-
- // bitb = m[i][0] % MAXLONG
- //
- bitb = m[i][0] & (MAXLONG - 1);
-
- if ((a[fielda] & mBitmask[bita]) != 0)
- {
-
- if ((b[fieldb] & mBitmask[bitb]) != 0)
- {
- s ^= 1;
- }
-
- if (m[i][1] != -1)
- {
-
- // fieldb = m[i][1] / MAXLONG
- //
- fieldb = mIBY64[m[i][1]];
-
- // bitb = m[i][1] % MAXLONG
- //
- bitb = m[i][1] & (MAXLONG - 1);
-
- if ((b[fieldb] & mBitmask[bitb]) != 0)
- {
- s ^= 1;
- }
-
- }
- }
- }
- fielda = mIBY64[k];
- bita = k & (MAXLONG - 1);
-
- if (s != 0)
- {
- c[fielda] ^= mBitmask[bita];
- }
-
- // Circular shift of x and y one bit to the right,
- // respectively.
-
- if (mLength > 1)
- {
-
- // Shift x.
- //
- old = (a[degf] & 1) == 1;
-
- for (int i = degf - 1; i >= 0; i--)
- {
- now = (a[i] & 1) != 0;
-
- a[i] = a[i] >>> 1;
-
- if (old)
- {
- a[i] ^= TWOTOMAXLONGM1;
- }
-
- old = now;
- }
- a[degf] = a[degf] >>> 1;
-
- if (old)
- {
- a[degf] ^= TWOTODEGB;
- }
-
- // Shift y.
- //
- old = (b[degf] & 1) == 1;
-
- for (int i = degf - 1; i >= 0; i--)
- {
- now = (b[i] & 1) != 0;
-
- b[i] = b[i] >>> 1;
-
- if (old)
- {
- b[i] ^= TWOTOMAXLONGM1;
- }
-
- old = now;
- }
-
- b[degf] = b[degf] >>> 1;
-
- if (old)
- {
- b[degf] ^= TWOTODEGB;
- }
- }
- else
- {
- old = (a[0] & 1) == 1;
- a[0] = a[0] >>> 1;
-
- if (old)
- {
- a[0] ^= TWOTODEGB;
- }
-
- old = (b[0] & 1) == 1;
- b[0] = b[0] >>> 1;
-
- if (old)
- {
- b[0] ^= TWOTODEGB;
- }
- }
- }
- assign(c);
- }
- }
-
- /**
- * returns <tt>this</tt> element to the power of 2.
- *
- * @return <tt>this</tt><sup>2</sup>
- */
- public GF2nElement square()
- {
- GF2nONBElement result = new GF2nONBElement(this);
- result.squareThis();
- return result;
- }
-
- /**
- * squares <tt>this</tt> element.
- */
- public void squareThis()
- {
-
- long[] pol = getElement();
-
- int f = mLength - 1;
- int b = mBit - 1;
-
- // Shift the coefficients one bit to the left.
- //
- long TWOTOMAXLONGM1 = mBitmask[MAXLONG - 1];
- boolean old, now;
-
- old = (pol[f] & mBitmask[b]) != 0;
-
- for (int i = 0; i < f; i++)
- {
-
- now = (pol[i] & TWOTOMAXLONGM1) != 0;
-
- pol[i] = pol[i] << 1;
-
- if (old)
- {
- pol[i] ^= 1;
- }
-
- old = now;
- }
- now = (pol[f] & mBitmask[b]) != 0;
-
- pol[f] = pol[f] << 1;
-
- if (old)
- {
- pol[f] ^= 1;
- }
-
- // Set the bit with index mDegree to zero.
- //
- if (now)
- {
- pol[f] ^= mBitmask[b + 1];
- }
-
- assign(pol);
- }
-
- /**
- * Compute the multiplicative inverse of this element.
- *
- * @return <tt>this<sup>-1</sup></tt> (newly created)
- * @throws ArithmeticException if <tt>this</tt> is the zero element.
- */
- public GFElement invert()
- throws ArithmeticException
- {
- GF2nONBElement result = new GF2nONBElement(this);
- result.invertThis();
- return result;
- }
-
- /**
- * Multiplicatively invert of this element (overwrite <tt>this</tt>).
- *
- * @throws ArithmeticException if <tt>this</tt> is the zero element.
- */
- public void invertThis()
- throws ArithmeticException
- {
-
- if (isZero())
- {
- throw new ArithmeticException();
- }
- int r = 31; // mDegree kann nur 31 Bits lang sein!!!
-
- // Bitlaenge von mDegree:
- for (boolean found = false; !found && r >= 0; r--)
- {
-
- if (((mDegree - 1) & mBitmask[r]) != 0)
- {
- found = true;
- }
- }
- r++;
-
- GF2nElement m = ZERO((GF2nONBField)mField);
- GF2nElement n = new GF2nONBElement(this);
-
- int k = 1;
-
- for (int i = r - 1; i >= 0; i--)
- {
- m = (GF2nElement)n.clone();
- for (int j = 1; j <= k; j++)
- {
- m.squareThis();
- }
-
- n.multiplyThisBy(m);
-
- k <<= 1;
- if (((mDegree - 1) & mBitmask[i]) != 0)
- {
- n.squareThis();
-
- n.multiplyThisBy(this);
-
- k++;
- }
- }
- n.squareThis();
- }
-
- /**
- * returns the root of<tt>this</tt> element.
- *
- * @return <tt>this</tt><sup>1/2</sup>
- */
- public GF2nElement squareRoot()
- {
- GF2nONBElement result = new GF2nONBElement(this);
- result.squareRootThis();
- return result;
- }
-
- /**
- * square roots <tt>this</tt> element.
- */
- public void squareRootThis()
- {
-
- long[] pol = getElement();
-
- int f = mLength - 1;
- int b = mBit - 1;
-
- // Shift the coefficients one bit to the right.
- //
- long TWOTOMAXLONGM1 = mBitmask[MAXLONG - 1];
- boolean old, now;
-
- old = (pol[0] & 1) != 0;
-
- for (int i = f; i >= 0; i--)
- {
- now = (pol[i] & 1) != 0;
- pol[i] = pol[i] >>> 1;
-
- if (old)
- {
- if (i == f)
- {
- pol[i] ^= mBitmask[b];
- }
- else
- {
- pol[i] ^= TWOTOMAXLONGM1;
- }
- }
- old = now;
- }
- assign(pol);
- }
-
- /**
- * Returns the trace of this element.
- *
- * @return the trace of this element
- */
- public int trace()
- {
-
- // trace = sum of coefficients
- //
-
- int result = 0;
-
- int max = mLength - 1;
-
- for (int i = 0; i < max; i++)
- {
-
- for (int j = 0; j < MAXLONG; j++)
- {
-
- if ((mPol[i] & mBitmask[j]) != 0)
- {
- result ^= 1;
- }
- }
- }
-
- int b = mBit;
-
- for (int j = 0; j < b; j++)
- {
-
- if ((mPol[max] & mBitmask[j]) != 0)
- {
- result ^= 1;
- }
- }
- return result;
- }
-
- /**
- * Solves a quadratic equation.<br>
- * Let z<sup>2</sup> + z = <tt>this</tt>. Then this method returns z.
- *
- * @return z with z<sup>2</sup> + z = <tt>this</tt>
- * @throws NoSolutionException if z<sup>2</sup> + z = <tt>this</tt> does not have a
- * solution
- */
- public GF2nElement solveQuadraticEquation()
- throws RuntimeException
- {
-
- if (trace() == 1)
- {
- throw new RuntimeException();
- }
-
- long TWOTOMAXLONGM1 = mBitmask[MAXLONG - 1];
- long ZERO = 0L;
- long ONE = 1L;
-
- long[] p = new long[mLength];
- long z = 0L;
- int j = 1;
- for (int i = 0; i < mLength - 1; i++)
- {
-
- for (j = 1; j < MAXLONG; j++)
- {
-
- //
- if (!((((mBitmask[j] & mPol[i]) != ZERO) && ((z & mBitmask[j - 1]) != ZERO)) || (((mPol[i] & mBitmask[j]) == ZERO) && ((z & mBitmask[j - 1]) == ZERO))))
- {
- z ^= mBitmask[j];
- }
- }
- p[i] = z;
-
- if (((TWOTOMAXLONGM1 & z) != ZERO && (ONE & mPol[i + 1]) == ONE)
- || ((TWOTOMAXLONGM1 & z) == ZERO && (ONE & mPol[i + 1]) == ZERO))
- {
- z = ZERO;
- }
- else
- {
- z = ONE;
- }
- }
-
- int b = mDegree & (MAXLONG - 1);
-
- long LASTLONG = mPol[mLength - 1];
-
- for (j = 1; j < b; j++)
- {
- if (!((((mBitmask[j] & LASTLONG) != ZERO) && ((mBitmask[j - 1] & z) != ZERO)) || (((mBitmask[j] & LASTLONG) == ZERO) && ((mBitmask[j - 1] & z) == ZERO))))
- {
- z ^= mBitmask[j];
- }
- }
- p[mLength - 1] = z;
- return new GF2nONBElement((GF2nONBField)mField, p);
- }
-
- // /////////////////////////////////////////////////////////////////
- // conversion
- // /////////////////////////////////////////////////////////////////
-
- /**
- * Returns a String representation of this element.
- *
- * @return String representation of this element with the specified radix
- */
- public String toString()
- {
- return toString(16);
- }
-
- /**
- * Returns a String representation of this element. <tt>radix</tt>
- * specifies the radix of the String representation.<br>
- * NOTE: ONLY <tt>radix = 2</tt> or <tt>radix = 16</tt> IS IMPLEMENTED
- *
- * @param radix specifies the radix of the String representation
- * @return String representation of this element with the specified radix
- */
- public String toString(int radix)
- {
- String s = "";
-
- long[] a = getElement();
- int b = mBit;
-
- if (radix == 2)
- {
-
- for (int j = b - 1; j >= 0; j--)
- {
- if ((a[a.length - 1] & ((long)1 << j)) == 0)
- {
- s += "0";
- }
- else
- {
- s += "1";
- }
- }
-
- for (int i = a.length - 2; i >= 0; i--)
- {
- for (int j = MAXLONG - 1; j >= 0; j--)
- {
- if ((a[i] & mBitmask[j]) == 0)
- {
- s += "0";
- }
- else
- {
- s += "1";
- }
- }
- }
- }
- else if (radix == 16)
- {
- final char[] HEX_CHARS = {'0', '1', '2', '3', '4', '5', '6', '7',
- '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
- for (int i = a.length - 1; i >= 0; i--)
- {
- s += HEX_CHARS[(int)(a[i] >>> 60) & 0x0f];
- s += HEX_CHARS[(int)(a[i] >>> 56) & 0x0f];
- s += HEX_CHARS[(int)(a[i] >>> 52) & 0x0f];
- s += HEX_CHARS[(int)(a[i] >>> 48) & 0x0f];
- s += HEX_CHARS[(int)(a[i] >>> 44) & 0x0f];
- s += HEX_CHARS[(int)(a[i] >>> 40) & 0x0f];
- s += HEX_CHARS[(int)(a[i] >>> 36) & 0x0f];
- s += HEX_CHARS[(int)(a[i] >>> 32) & 0x0f];
- s += HEX_CHARS[(int)(a[i] >>> 28) & 0x0f];
- s += HEX_CHARS[(int)(a[i] >>> 24) & 0x0f];
- s += HEX_CHARS[(int)(a[i] >>> 20) & 0x0f];
- s += HEX_CHARS[(int)(a[i] >>> 16) & 0x0f];
- s += HEX_CHARS[(int)(a[i] >>> 12) & 0x0f];
- s += HEX_CHARS[(int)(a[i] >>> 8) & 0x0f];
- s += HEX_CHARS[(int)(a[i] >>> 4) & 0x0f];
- s += HEX_CHARS[(int)(a[i]) & 0x0f];
- s += " ";
- }
- }
- return s;
- }
-
- /**
- * Returns this element as FlexiBigInt. The conversion is <a href =
- * "http://grouper.ieee.org/groups/1363/">P1363</a>-conform.
- *
- * @return this element as BigInteger
- */
- public BigInteger toFlexiBigInt()
- {
- /** @todo this method does not reverse the bit-order as it should!!! */
-
- return new BigInteger(1, toByteArray());
- }
-
- /**
- * Returns this element as byte array. The conversion is <a href =
- * "http://grouper.ieee.org/groups/1363/">P1363</a>-conform.
- *
- * @return this element as byte array
- */
- public byte[] toByteArray()
- {
- /** @todo this method does not reverse the bit-order as it should!!! */
-
- int k = ((mDegree - 1) >> 3) + 1;
- byte[] result = new byte[k];
- int i;
- for (i = 0; i < k; i++)
- {
- result[k - i - 1] = (byte)((mPol[i >>> 3] & (0x00000000000000ffL << ((i & 0x07) << 3))) >>> ((i & 0x07) << 3));
- }
- return result;
- }
-
-}
diff --git a/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2nONBField.java b/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2nONBField.java
deleted file mode 100644
index 1e4c8b2..0000000
--- a/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2nONBField.java
+++ /dev/null
@@ -1,546 +0,0 @@
-package org.bouncycastle.pqc.math.linearalgebra;
-
-
-import java.util.Random;
-import java.util.Vector;
-
-
-/**
- * This class implements the abstract class <tt>GF2nField</tt> for ONB
- * representation. It computes the fieldpolynomial, multiplication matrix and
- * one of its roots mONBRoot, (see for example <a
- * href=http://www2.certicom.com/ecc/intro.htm>Certicoms Whitepapers</a>).
- * GF2nField is used by GF2nONBElement which implements the elements of this
- * field.
- *
- * @see GF2nField
- * @see GF2nONBElement
- */
-public class GF2nONBField
- extends GF2nField
-{
-
- // ///////////////////////////////////////////////////////////////////
- // Hashtable for irreducible normal polynomials //
- // ///////////////////////////////////////////////////////////////////
-
- // i*5 + 0 i*5 + 1 i*5 + 2 i*5 + 3 i*5 + 4
- /*
- * private static int[][] mNB = {{0, 0, 0}, {0, 0, 0}, {1, 0, 0}, {1, 0, 0},
- * {1, 0, 0}, // i = 0 {2, 0, 0}, {1, 0, 0}, {1, 0, 0}, {4, 3, 1}, {1, 0,
- * 0}, // i = 1 {3, 0, 0}, {2, 0, 0}, {3, 0, 0}, {4, 3, 1}, {5, 0, 0}, // i =
- * 2 {1, 0, 0}, {5, 3, 1}, {3, 0, 0}, {3, 0, 0}, {5, 2, 1}, // i = 3 {3, 0,
- * 0}, {2, 0, 0}, {1, 0, 0}, {5, 0, 0}, {4, 3, 1}, // i = 4 {3, 0, 0}, {4,
- * 3, 1}, {5, 2, 1}, {1, 0, 0}, {2, 0, 0}, // i = 5 {1, 0, 0}, {3, 0, 0},
- * {7, 3, 2}, {10, 0, 0}, {7, 0, 0}, // i = 6 {2, 0, 0}, {9, 0, 0}, {6, 4,
- * 1}, {6, 5, 1}, {4, 0, 0}, // i = 7 {5, 4, 3}, {3, 0, 0}, {7, 0, 0}, {6,
- * 4, 3}, {5, 0, 0}, // i = 8 {4, 3, 1}, {1, 0, 0}, {5, 0, 0}, {5, 3, 2},
- * {9, 0, 0}, // i = 9 {4, 3, 2}, {6, 3, 1}, {3, 0, 0}, {6, 2, 1}, {9, 0,
- * 0}, // i = 10 {7, 0, 0}, {7, 4, 2}, {4, 0, 0}, {19, 0, 0}, {7, 4, 2}, //
- * i = 11 {1, 0, 0}, {5, 2, 1}, {29, 0, 0}, {1, 0, 0}, {4, 3, 1}, // i = 12
- * {18, 0, 0}, {3, 0, 0}, {5, 2, 1}, {9, 0, 0}, {6, 5, 2}, // i = 13 {5, 3,
- * 1}, {6, 0, 0}, {10, 9, 3}, {25, 0, 0}, {35, 0, 0}, // i = 14 {6, 3, 1},
- * {21, 0, 0}, {6, 5, 2}, {6, 5, 3}, {9, 0, 0}, // i = 15 {9, 4, 2}, {4, 0,
- * 0}, {8, 3, 1}, {7, 4, 2}, {5, 0, 0}, // i = 16 {8, 2, 1}, {21, 0, 0},
- * {13, 0, 0}, {7, 6, 2}, {38, 0, 0}, // i = 17 {27, 0, 0}, {8, 5, 1}, {21,
- * 0, 0}, {2, 0, 0}, {21, 0, 0}, // i = 18 {11, 0, 0}, {10, 9, 6}, {6, 0,
- * 0}, {11, 0, 0}, {6, 3, 1}, // i = 19 {15, 0, 0}, {7, 6, 1}, {29, 0, 0},
- * {9, 0, 0}, {4, 3, 1}, // i = 20 {4, 0, 0}, {15, 0, 0}, {9, 7, 4}, {17, 0,
- * 0}, {5, 4, 2}, // i = 21 {33, 0, 0}, {10, 0, 0}, {5, 4, 3}, {9, 0, 0},
- * {5, 3, 2}, // i = 22 {8, 7, 5}, {4, 2, 1}, {5, 2, 1}, {33, 0, 0}, {8, 0,
- * 0}, // i = 23 {4, 3, 1}, {18, 0, 0}, {6, 2, 1}, {2, 0, 0}, {19, 0, 0}, //
- * i = 24 {7, 6, 5}, {21, 0, 0}, {1, 0, 0}, {7, 2, 1}, {5, 0, 0}, // i = 25
- * {3, 0, 0}, {8, 3, 2}, {17, 0, 0}, {9, 8, 2}, {57, 0, 0}, // i = 26 {11,
- * 0, 0}, {5, 3, 2}, {21, 0, 0}, {8, 7, 1}, {8, 5, 3}, // i = 27 {15, 0, 0},
- * {10, 4, 1}, {21, 0, 0}, {5, 3, 2}, {7, 4, 2}, // i = 28 {52, 0, 0}, {71,
- * 0, 0}, {14, 0, 0}, {27, 0, 0}, {10, 9, 7}, // i = 29 {53, 0, 0}, {3, 0,
- * 0}, {6, 3, 2}, {1, 0, 0}, {15, 0, 0}, // i = 30 {62, 0, 0}, {9, 0, 0},
- * {6, 5, 2}, {8, 6, 5}, {31, 0, 0}, // i = 31 {5, 3, 2}, {18, 0, 0 }, {27,
- * 0, 0}, {7, 6, 3}, {10, 8, 7}, // i = 32 {9, 8, 3}, {37, 0, 0}, {6, 0, 0},
- * {15, 3, 2}, {34, 0, 0}, // i = 33 {11, 0, 0}, {6, 5, 2}, {1, 0, 0}, {8,
- * 5, 2}, {13, 0, 0}, // i = 34 {6, 0, 0}, {11, 3, 2}, {8, 0, 0}, {31, 0,
- * 0}, {4, 2, 1}, // i = 35 {3, 0, 0}, {7, 6, 1}, {81, 0, 0}, {56, 0, 0},
- * {9, 8, 7}, // i = 36 {24, 0, 0}, {11, 0, 0}, {7, 6, 5}, {6, 5, 2}, {6, 5,
- * 2}, // i = 37 {8, 7, 6}, {9, 0, 0}, {7, 2, 1}, {15, 0, 0}, {87, 0, 0}, //
- * i = 38 {8, 3, 2}, {3, 0, 0}, {9, 4, 2}, {9, 0, 0}, {34, 0, 0}, // i = 39
- * {5, 3, 2}, {14, 0, 0}, {55, 0, 0}, {8, 7, 1}, {27, 0, 0}, // i = 40 {9,
- * 5, 2}, {10, 9, 5}, {43, 0, 0}, {8, 6, 2}, {6, 0, 0}, // i = 41 {7, 0, 0},
- * {11, 10, 8}, {105, 0, 0}, {6, 5, 2}, {73, 0, 0}}; // i = 42
- */
- // /////////////////////////////////////////////////////////////////////
- // member variables
- // /////////////////////////////////////////////////////////////////////
- private static final int MAXLONG = 64;
-
- /**
- * holds the length of the array-representation of degree mDegree.
- */
- private int mLength;
-
- /**
- * holds the number of relevant bits in mONBPol[mLength-1].
- */
- private int mBit;
-
- /**
- * holds the type of mONB
- */
- private int mType;
-
- /**
- * holds the multiplication matrix
- */
- int[][] mMult;
-
- // /////////////////////////////////////////////////////////////////////
- // constructors
- // /////////////////////////////////////////////////////////////////////
-
- /**
- * constructs an instance of the finite field with 2<sup>deg</sup>
- * elements and characteristic 2.
- *
- * @param deg -
- * the extention degree of this field
- * @throws NoSuchBasisException if an ONB-implementation other than type 1 or type 2 is
- * requested.
- */
- public GF2nONBField(int deg)
- throws RuntimeException
- {
- if (deg < 3)
- {
- throw new IllegalArgumentException("k must be at least 3");
- }
-
- mDegree = deg;
- mLength = mDegree / MAXLONG;
- mBit = mDegree & (MAXLONG - 1);
- if (mBit == 0)
- {
- mBit = MAXLONG;
- }
- else
- {
- mLength++;
- }
-
- computeType();
-
- // only ONB-implementations for type 1 and type 2
- //
- if (mType < 3)
- {
- mMult = new int[mDegree][2];
- for (int i = 0; i < mDegree; i++)
- {
- mMult[i][0] = -1;
- mMult[i][1] = -1;
- }
- computeMultMatrix();
- }
- else
- {
- throw new RuntimeException("\nThe type of this field is "
- + mType);
- }
- computeFieldPolynomial();
- fields = new Vector();
- matrices = new Vector();
- }
-
- // /////////////////////////////////////////////////////////////////////
- // access
- // /////////////////////////////////////////////////////////////////////
-
- int getONBLength()
- {
- return mLength;
- }
-
- int getONBBit()
- {
- return mBit;
- }
-
- // /////////////////////////////////////////////////////////////////////
- // arithmetic
- // /////////////////////////////////////////////////////////////////////
-
- /**
- * Computes a random root of the given polynomial.
- *
- * @param polynomial a polynomial
- * @return a random root of the polynomial
- * @see "P1363 A.5.6, p103f"
- */
- protected GF2nElement getRandomRoot(GF2Polynomial polynomial)
- {
- // We are in B1!!!
- GF2nPolynomial c;
- GF2nPolynomial ut;
- GF2nElement u;
- GF2nPolynomial h;
- int hDegree;
- // 1. Set g(t) <- f(t)
- GF2nPolynomial g = new GF2nPolynomial(polynomial, this);
- int gDegree = g.getDegree();
- int i;
-
- // 2. while deg(g) > 1
- while (gDegree > 1)
- {
- do
- {
- // 2.1 choose random u (element of) GF(2^m)
- u = new GF2nONBElement(this, new Random());
- ut = new GF2nPolynomial(2, GF2nONBElement.ZERO(this));
- // 2.2 Set c(t) <- ut
- ut.set(1, u);
- c = new GF2nPolynomial(ut);
- // 2.3 For i from 1 to m-1 do
- for (i = 1; i <= mDegree - 1; i++)
- {
- // 2.3.1 c(t) <- (c(t)^2 + ut) mod g(t)
- c = c.multiplyAndReduce(c, g);
- c = c.add(ut);
- }
- // 2.4 set h(t) <- GCD(c(t), g(t))
- h = c.gcd(g);
- // 2.5 if h(t) is constant or deg(g) = deg(h) then go to
- // step 2.1
- hDegree = h.getDegree();
- gDegree = g.getDegree();
- }
- while ((hDegree == 0) || (hDegree == gDegree));
- // 2.6 If 2deg(h) > deg(g) then set g(t) <- g(t)/h(t) ...
- if ((hDegree << 1) > gDegree)
- {
- g = g.quotient(h);
- }
- else
- {
- // ... else g(t) <- h(t)
- g = new GF2nPolynomial(h);
- }
- gDegree = g.getDegree();
- }
- // 3. Output g(0)
- return g.at(0);
-
- }
-
- /**
- * Computes the change-of-basis matrix for basis conversion according to
- * 1363. The result is stored in the lists fields and matrices.
- *
- * @param B1 the GF2nField to convert to
- * @see "P1363 A.7.3, p111ff"
- */
- protected void computeCOBMatrix(GF2nField B1)
- {
- // we are in B0 here!
- if (mDegree != B1.mDegree)
- {
- throw new IllegalArgumentException(
- "GF2nField.computeCOBMatrix: B1 has a "
- + "different degree and thus cannot be coverted to!");
- }
- int i, j;
- GF2nElement[] gamma;
- GF2nElement u;
- GF2Polynomial[] COBMatrix = new GF2Polynomial[mDegree];
- for (i = 0; i < mDegree; i++)
- {
- COBMatrix[i] = new GF2Polynomial(mDegree);
- }
-
- // find Random Root
- do
- {
- // u is in representation according to B1
- u = B1.getRandomRoot(fieldPolynomial);
- }
- while (u.isZero());
-
- gamma = new GF2nPolynomialElement[mDegree];
- // build gamma matrix by squaring
- gamma[0] = (GF2nElement)u.clone();
- for (i = 1; i < mDegree; i++)
- {
- gamma[i] = gamma[i - 1].square();
- }
- // convert horizontal gamma matrix by vertical Bitstrings
- for (i = 0; i < mDegree; i++)
- {
- for (j = 0; j < mDegree; j++)
- {
- if (gamma[i].testBit(j))
- {
- COBMatrix[mDegree - j - 1].setBit(mDegree - i - 1);
- }
- }
- }
-
- fields.addElement(B1);
- matrices.addElement(COBMatrix);
- B1.fields.addElement(this);
- B1.matrices.addElement(invertMatrix(COBMatrix));
- }
-
- /**
- * Computes the field polynomial for a ONB according to IEEE 1363 A.7.2
- * (p110f).
- *
- * @see "P1363 A.7.2, p110f"
- */
- protected void computeFieldPolynomial()
- {
- if (mType == 1)
- {
- fieldPolynomial = new GF2Polynomial(mDegree + 1, "ALL");
- }
- else if (mType == 2)
- {
- // 1. q = 1
- GF2Polynomial q = new GF2Polynomial(mDegree + 1, "ONE");
- // 2. p = t+1
- GF2Polynomial p = new GF2Polynomial(mDegree + 1, "X");
- p.addToThis(q);
- GF2Polynomial r;
- int i;
- // 3. for i = 1 to (m-1) do
- for (i = 1; i < mDegree; i++)
- {
- // r <- q
- r = q;
- // q <- p
- q = p;
- // p = tq+r
- p = q.shiftLeft();
- p.addToThis(r);
- }
- fieldPolynomial = p;
- }
- }
-
- /**
- * Compute the inverse of a matrix <tt>a</tt>.
- *
- * @param a the matrix
- * @return <tt>a<sup>-1</sup></tt>
- */
- int[][] invMatrix(int[][] a)
- {
-
- int[][] A = new int[mDegree][mDegree];
- A = a;
- int[][] inv = new int[mDegree][mDegree];
-
- for (int i = 0; i < mDegree; i++)
- {
- inv[i][i] = 1;
- }
-
- for (int i = 0; i < mDegree; i++)
- {
- for (int j = i; j < mDegree; j++)
- {
- A[mDegree - 1 - i][j] = A[i][i];
- }
- }
- return null;
- }
-
- private void computeType()
- throws RuntimeException
- {
- if ((mDegree & 7) == 0)
- {
- throw new RuntimeException(
- "The extension degree is divisible by 8!");
- }
- // checking for the type
- int s = 0;
- int k = 0;
- mType = 1;
- for (int d = 0; d != 1; mType++)
- {
- s = mType * mDegree + 1;
- if (IntegerFunctions.isPrime(s))
- {
- k = IntegerFunctions.order(2, s);
- d = IntegerFunctions.gcd(mType * mDegree / k, mDegree);
- }
- }
- mType--;
- if (mType == 1)
- {
- s = (mDegree << 1) + 1;
- if (IntegerFunctions.isPrime(s))
- {
- k = IntegerFunctions.order(2, s);
- int d = IntegerFunctions.gcd((mDegree << 1) / k, mDegree);
- if (d == 1)
- {
- mType++;
- }
- }
- }
- }
-
- private void computeMultMatrix()
- {
-
- if ((mType & 7) != 0)
- {
- int p = mType * mDegree + 1;
-
- // compute sequence F[1] ... F[p-1] via A.3.7. of 1363.
- // F[0] will not be filled!
- //
- int[] F = new int[p];
-
- int u;
- if (mType == 1)
- {
- u = 1;
- }
- else if (mType == 2)
- {
- u = p - 1;
- }
- else
- {
- u = elementOfOrder(mType, p);
- }
-
- int w = 1;
- int n;
- for (int j = 0; j < mType; j++)
- {
- n = w;
-
- for (int i = 0; i < mDegree; i++)
- {
- F[n] = i;
- n = (n << 1) % p;
- if (n < 0)
- {
- n += p;
- }
- }
- w = u * w % p;
- if (w < 0)
- {
- w += p;
- }
- }
-
- // building the matrix (mDegree * 2)
- //
- if (mType == 1)
- {
- for (int k = 1; k < p - 1; k++)
- {
- if (mMult[F[k + 1]][0] == -1)
- {
- mMult[F[k + 1]][0] = F[p - k];
- }
- else
- {
- mMult[F[k + 1]][1] = F[p - k];
- }
- }
-
- int m_2 = mDegree >> 1;
- for (int k = 1; k <= m_2; k++)
- {
-
- if (mMult[k - 1][0] == -1)
- {
- mMult[k - 1][0] = m_2 + k - 1;
- }
- else
- {
- mMult[k - 1][1] = m_2 + k - 1;
- }
-
- if (mMult[m_2 + k - 1][0] == -1)
- {
- mMult[m_2 + k - 1][0] = k - 1;
- }
- else
- {
- mMult[m_2 + k - 1][1] = k - 1;
- }
- }
- }
- else if (mType == 2)
- {
- for (int k = 1; k < p - 1; k++)
- {
- if (mMult[F[k + 1]][0] == -1)
- {
- mMult[F[k + 1]][0] = F[p - k];
- }
- else
- {
- mMult[F[k + 1]][1] = F[p - k];
- }
- }
- }
- else
- {
- throw new RuntimeException("only type 1 or type 2 implemented");
- }
- }
- else
- {
- throw new RuntimeException("bisher nur fuer Gausssche Normalbasen"
- + " implementiert");
- }
- }
-
- private int elementOfOrder(int k, int p)
- {
- Random random = new Random();
- int m = 0;
- while (m == 0)
- {
- m = random.nextInt();
- m %= p - 1;
- if (m < 0)
- {
- m += p - 1;
- }
- }
-
- int l = IntegerFunctions.order(m, p);
-
- while (l % k != 0 || l == 0)
- {
- while (m == 0)
- {
- m = random.nextInt();
- m %= p - 1;
- if (m < 0)
- {
- m += p - 1;
- }
- }
- l = IntegerFunctions.order(m, p);
- }
- int r = m;
-
- l = k / l;
-
- for (int i = 2; i <= l; i++)
- {
- r *= m;
- }
-
- return r;
- }
-
-}
diff --git a/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2nPolynomial.java b/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2nPolynomial.java
deleted file mode 100644
index f122be0..0000000
--- a/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2nPolynomial.java
+++ /dev/null
@@ -1,587 +0,0 @@
-package org.bouncycastle.pqc.math.linearalgebra;
-
-
-/**
- * This class implements polynomials over GF2nElements.
- *
- * @see GF2nElement
- */
-
-public class GF2nPolynomial
-{
-
- private GF2nElement[] coeff; // keeps the coefficients of this polynomial
-
- private int size; // the size of this polynomial
-
- /**
- * Creates a new PolynomialGF2n of size <i>deg</i> and elem as
- * coefficients.
- *
- * @param deg -
- * the maximum degree + 1
- * @param elem -
- * a GF2nElement
- */
- public GF2nPolynomial(int deg, GF2nElement elem)
- {
- size = deg;
- coeff = new GF2nElement[size];
- for (int i = 0; i < size; i++)
- {
- coeff[i] = (GF2nElement)elem.clone();
- }
- }
-
- /**
- * Creates a new PolynomialGF2n of size <i>deg</i>.
- *
- * @param deg the maximum degree + 1
- */
- private GF2nPolynomial(int deg)
- {
- size = deg;
- coeff = new GF2nElement[size];
- }
-
- /**
- * Creates a new PolynomialGF2n by cloning the given PolynomialGF2n <i>a</i>.
- *
- * @param a the PolynomialGF2n to clone
- */
- public GF2nPolynomial(GF2nPolynomial a)
- {
- int i;
- coeff = new GF2nElement[a.size];
- size = a.size;
- for (i = 0; i < size; i++)
- {
- coeff[i] = (GF2nElement)a.coeff[i].clone();
- }
- }
-
- /**
- * Creates a new PolynomialGF2n from the given Bitstring <i>polynomial</i>
- * over the GF2nField <i>B1</i>.
- *
- * @param polynomial the Bitstring to use
- * @param B1 the field
- */
- public GF2nPolynomial(GF2Polynomial polynomial, GF2nField B1)
- {
- size = B1.getDegree() + 1;
- coeff = new GF2nElement[size];
- int i;
- if (B1 instanceof GF2nONBField)
- {
- for (i = 0; i < size; i++)
- {
- if (polynomial.testBit(i))
- {
- coeff[i] = GF2nONBElement.ONE((GF2nONBField)B1);
- }
- else
- {
- coeff[i] = GF2nONBElement.ZERO((GF2nONBField)B1);
- }
- }
- }
- else if (B1 instanceof GF2nPolynomialField)
- {
- for (i = 0; i < size; i++)
- {
- if (polynomial.testBit(i))
- {
- coeff[i] = GF2nPolynomialElement
- .ONE((GF2nPolynomialField)B1);
- }
- else
- {
- coeff[i] = GF2nPolynomialElement
- .ZERO((GF2nPolynomialField)B1);
- }
- }
- }
- else
- {
- throw new IllegalArgumentException(
- "PolynomialGF2n(Bitstring, GF2nField): B1 must be "
- + "an instance of GF2nONBField or GF2nPolynomialField!");
- }
- }
-
- public final void assignZeroToElements()
- {
- int i;
- for (i = 0; i < size; i++)
- {
- coeff[i].assignZero();
- }
- }
-
- /**
- * Returns the size (=maximum degree + 1) of this PolynomialGF2n. This is
- * not the degree, use getDegree instead.
- *
- * @return the size (=maximum degree + 1) of this PolynomialGF2n.
- */
- public final int size()
- {
- return size;
- }
-
- /**
- * Returns the degree of this PolynomialGF2n.
- *
- * @return the degree of this PolynomialGF2n.
- */
- public final int getDegree()
- {
- int i;
- for (i = size - 1; i >= 0; i--)
- {
- if (!coeff[i].isZero())
- {
- return i;
- }
- }
- return -1;
- }
-
- /**
- * Enlarges the size of this PolynomialGF2n to <i>k</i> + 1.
- *
- * @param k the new maximum degree
- */
- public final void enlarge(int k)
- {
- if (k <= size)
- {
- return;
- }
- int i;
- GF2nElement[] res = new GF2nElement[k];
- System.arraycopy(coeff, 0, res, 0, size);
- GF2nField f = coeff[0].getField();
- if (coeff[0] instanceof GF2nPolynomialElement)
- {
- for (i = size; i < k; i++)
- {
- res[i] = GF2nPolynomialElement.ZERO((GF2nPolynomialField)f);
- }
- }
- else if (coeff[0] instanceof GF2nONBElement)
- {
- for (i = size; i < k; i++)
- {
- res[i] = GF2nONBElement.ZERO((GF2nONBField)f);
- }
- }
- size = k;
- coeff = res;
- }
-
- public final void shrink()
- {
- int i = size - 1;
- while (coeff[i].isZero() && (i > 0))
- {
- i--;
- }
- i++;
- if (i < size)
- {
- GF2nElement[] res = new GF2nElement[i];
- System.arraycopy(coeff, 0, res, 0, i);
- coeff = res;
- size = i;
- }
- }
-
- /**
- * Sets the coefficient at <i>index</i> to <i>elem</i>.
- *
- * @param index the index
- * @param elem the GF2nElement to store as coefficient <i>index</i>
- */
- public final void set(int index, GF2nElement elem)
- {
- if (!(elem instanceof GF2nPolynomialElement)
- && !(elem instanceof GF2nONBElement))
- {
- throw new IllegalArgumentException(
- "PolynomialGF2n.set f must be an "
- + "instance of either GF2nPolynomialElement or GF2nONBElement!");
- }
- coeff[index] = (GF2nElement)elem.clone();
- }
-
- /**
- * Returns the coefficient at <i>index</i>.
- *
- * @param index the index
- * @return the GF2nElement stored as coefficient <i>index</i>
- */
- public final GF2nElement at(int index)
- {
- return coeff[index];
- }
-
- /**
- * Returns true if all coefficients equal zero.
- *
- * @return true if all coefficients equal zero.
- */
- public final boolean isZero()
- {
- int i;
- for (i = 0; i < size; i++)
- {
- if (coeff[i] != null)
- {
- if (!coeff[i].isZero())
- {
- return false;
- }
- }
- }
- return true;
- }
-
- public final boolean equals(Object other)
- {
- if (other == null || !(other instanceof GF2nPolynomial))
- {
- return false;
- }
-
- GF2nPolynomial otherPol = (GF2nPolynomial)other;
-
- if (getDegree() != otherPol.getDegree())
- {
- return false;
- }
- int i;
- for (i = 0; i < size; i++)
- {
- if (!coeff[i].equals(otherPol.coeff[i]))
- {
- return false;
- }
- }
- return true;
- }
-
- /**
- * @return the hash code of this polynomial
- */
- public int hashCode()
- {
- return getDegree() + coeff.hashCode();
- }
-
- /**
- * Adds the PolynomialGF2n <tt>b</tt> to <tt>this</tt> and returns the
- * result in a new <tt>PolynomialGF2n</tt>.
- *
- * @param b -
- * the <tt>PolynomialGF2n</tt> to add
- * @return <tt>this + b</tt>
- * @throws DifferentFieldsException if <tt>this</tt> and <tt>b</tt> are not defined over
- * the same field.
- */
- public final GF2nPolynomial add(GF2nPolynomial b)
- throws RuntimeException
- {
- GF2nPolynomial result;
- if (size() >= b.size())
- {
- result = new GF2nPolynomial(size());
- int i;
- for (i = 0; i < b.size(); i++)
- {
- result.coeff[i] = (GF2nElement)coeff[i].add(b.coeff[i]);
- }
- for (; i < size(); i++)
- {
- result.coeff[i] = coeff[i];
- }
- }
- else
- {
- result = new GF2nPolynomial(b.size());
- int i;
- for (i = 0; i < size(); i++)
- {
- result.coeff[i] = (GF2nElement)coeff[i].add(b.coeff[i]);
- }
- for (; i < b.size(); i++)
- {
- result.coeff[i] = b.coeff[i];
- }
- }
- return result;
- }
-
- /**
- * Multiplies the scalar <i>s</i> to each coefficient of this
- * PolynomialGF2n and returns the result in a new PolynomialGF2n.
- *
- * @param s the scalar to multiply
- * @return <i>this</i> x <i>s</i>
- * @throws DifferentFieldsException if <tt>this</tt> and <tt>s</tt> are not defined over
- * the same field.
- */
- public final GF2nPolynomial scalarMultiply(GF2nElement s)
- throws RuntimeException
- {
- GF2nPolynomial result = new GF2nPolynomial(size());
- int i;
- for (i = 0; i < size(); i++)
- {
- result.coeff[i] = (GF2nElement)coeff[i].multiply(s); // result[i]
- // =
- // a[i]*s
- }
- return result;
- }
-
- /**
- * Multiplies <i>this</i> by <i>b</i> and returns the result in a new
- * PolynomialGF2n.
- *
- * @param b the PolynomialGF2n to multiply
- * @return <i>this</i> * <i>b</i>
- * @throws DifferentFieldsException if <tt>this</tt> and <tt>b</tt> are not defined over
- * the same field.
- */
- public final GF2nPolynomial multiply(GF2nPolynomial b)
- throws RuntimeException
- {
- int i, j;
- int aDegree = size();
- int bDegree = b.size();
- if (aDegree != bDegree)
- {
- throw new IllegalArgumentException(
- "PolynomialGF2n.multiply: this and b must "
- + "have the same size!");
- }
- GF2nPolynomial result = new GF2nPolynomial((aDegree << 1) - 1);
- for (i = 0; i < size(); i++)
- {
- for (j = 0; j < b.size(); j++)
- {
- if (result.coeff[i + j] == null)
- {
- result.coeff[i + j] = (GF2nElement)coeff[i]
- .multiply(b.coeff[j]);
- }
- else
- {
- result.coeff[i + j] = (GF2nElement)result.coeff[i + j]
- .add(coeff[i].multiply(b.coeff[j]));
- }
- }
- }
- return result;
- }
-
- /**
- * Multiplies <i>this</i> by <i>b</i>, reduces the result by <i>g</i> and
- * returns it in a new PolynomialGF2n.
- *
- * @param b the PolynomialGF2n to multiply
- * @param g the modul
- * @return <i>this</i> * <i>b</i> mod <i>g</i>
- * @throws DifferentFieldsException if <tt>this</tt>, <tt>b</tt> and <tt>g</tt> are
- * not all defined over the same field.
- */
- public final GF2nPolynomial multiplyAndReduce(GF2nPolynomial b,
- GF2nPolynomial g)
- throws RuntimeException,
- ArithmeticException
- {
- return multiply(b).reduce(g);
- }
-
- /**
- * Reduces <i>this</i> by <i>g</i> and returns the result in a new
- * PolynomialGF2n.
- *
- * @param g -
- * the modulus
- * @return <i>this</i> % <i>g</i>
- * @throws DifferentFieldsException if <tt>this</tt> and <tt>g</tt> are not defined over
- * the same field.
- */
- public final GF2nPolynomial reduce(GF2nPolynomial g)
- throws RuntimeException, ArithmeticException
- {
- return remainder(g); // return this % g
- }
-
- /**
- * Shifts left <i>this</i> by <i>amount</i> and stores the result in
- * <i>this</i> PolynomialGF2n.
- *
- * @param amount the amount to shift the coefficients
- */
- public final void shiftThisLeft(int amount)
- {
- if (amount > 0)
- {
- int i;
- int oldSize = size;
- GF2nField f = coeff[0].getField();
- enlarge(size + amount);
- for (i = oldSize - 1; i >= 0; i--)
- {
- coeff[i + amount] = coeff[i];
- }
- if (coeff[0] instanceof GF2nPolynomialElement)
- {
- for (i = amount - 1; i >= 0; i--)
- {
- coeff[i] = GF2nPolynomialElement
- .ZERO((GF2nPolynomialField)f);
- }
- }
- else if (coeff[0] instanceof GF2nONBElement)
- {
- for (i = amount - 1; i >= 0; i--)
- {
- coeff[i] = GF2nONBElement.ZERO((GF2nONBField)f);
- }
- }
- }
- }
-
- public final GF2nPolynomial shiftLeft(int amount)
- {
- if (amount <= 0)
- {
- return new GF2nPolynomial(this);
- }
- GF2nPolynomial result = new GF2nPolynomial(size + amount, coeff[0]);
- result.assignZeroToElements();
- for (int i = 0; i < size; i++)
- {
- result.coeff[i + amount] = coeff[i];
- }
- return result;
- }
-
- /**
- * Divides <i>this</i> by <i>b</i> and stores the result in a new
- * PolynomialGF2n[2], quotient in result[0] and remainder in result[1].
- *
- * @param b the divisor
- * @return the quotient and remainder of <i>this</i> / <i>b</i>
- * @throws DifferentFieldsException if <tt>this</tt> and <tt>b</tt> are not defined over
- * the same field.
- */
- public final GF2nPolynomial[] divide(GF2nPolynomial b)
- throws RuntimeException, ArithmeticException
- {
- GF2nPolynomial[] result = new GF2nPolynomial[2];
- GF2nPolynomial a = new GF2nPolynomial(this);
- a.shrink();
- GF2nPolynomial shift;
- GF2nElement factor;
- int bDegree = b.getDegree();
- GF2nElement inv = (GF2nElement)b.coeff[bDegree].invert();
- if (a.getDegree() < bDegree)
- {
- result[0] = new GF2nPolynomial(this);
- result[0].assignZeroToElements();
- result[0].shrink();
- result[1] = new GF2nPolynomial(this);
- result[1].shrink();
- return result;
- }
- result[0] = new GF2nPolynomial(this);
- result[0].assignZeroToElements();
- int i = a.getDegree() - bDegree;
- while (i >= 0)
- {
- factor = (GF2nElement)a.coeff[a.getDegree()].multiply(inv);
- shift = b.scalarMultiply(factor);
- shift.shiftThisLeft(i);
- a = a.add(shift);
- a.shrink();
- result[0].coeff[i] = (GF2nElement)factor.clone();
- i = a.getDegree() - bDegree;
- }
- result[1] = a;
- result[0].shrink();
- return result;
- }
-
- /**
- * Divides <i>this</i> by <i>b</i> and stores the remainder in a new
- * PolynomialGF2n.
- *
- * @param b the divisor
- * @return the remainder <i>this</i> % <i>b</i>
- * @throws DifferentFieldsException if <tt>this</tt> and <tt>b</tt> are not defined over
- * the same field.
- */
- public final GF2nPolynomial remainder(GF2nPolynomial b)
- throws RuntimeException, ArithmeticException
- {
- GF2nPolynomial[] result = new GF2nPolynomial[2];
- result = divide(b);
- return result[1];
- }
-
- /**
- * Divides <i>this</i> by <i>b</i> and stores the quotient in a new
- * PolynomialGF2n.
- *
- * @param b the divisor
- * @return the quotient <i>this</i> / <i>b</i>
- * @throws DifferentFieldsException if <tt>this</tt> and <tt>b</tt> are not defined over
- * the same field.
- */
- public final GF2nPolynomial quotient(GF2nPolynomial b)
- throws RuntimeException, ArithmeticException
- {
- GF2nPolynomial[] result = new GF2nPolynomial[2];
- result = divide(b);
- return result[0];
- }
-
- /**
- * Computes the greatest common divisor of <i>this</i> and <i>g</i> and
- * returns the result in a new PolynomialGF2n.
- *
- * @param g -
- * a GF2nPolynomial
- * @return gcd(<i>this</i>, <i>g</i>)
- * @throws DifferentFieldsException if the coefficients of <i>this</i> and <i>g</i> use
- * different fields
- * @throws ArithmeticException if coefficients are zero.
- */
- public final GF2nPolynomial gcd(GF2nPolynomial g)
- throws RuntimeException, ArithmeticException
- {
- GF2nPolynomial a = new GF2nPolynomial(this);
- GF2nPolynomial b = new GF2nPolynomial(g);
- a.shrink();
- b.shrink();
- GF2nPolynomial c;
- GF2nPolynomial result;
- GF2nElement alpha;
- while (!b.isZero())
- {
- c = a.remainder(b);
- a = b;
- b = c;
- }
- alpha = a.coeff[a.getDegree()];
- result = a.scalarMultiply((GF2nElement)alpha.invert());
- return result;
- }
-
-}
diff --git a/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2nPolynomialElement.java b/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2nPolynomialElement.java
deleted file mode 100644
index f175365..0000000
--- a/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2nPolynomialElement.java
+++ /dev/null
@@ -1,1021 +0,0 @@
-package org.bouncycastle.pqc.math.linearalgebra;
-
-
-import java.math.BigInteger;
-import java.util.Random;
-
-
-/**
- * This class implements elements of finite binary fields <i>GF(2<sup>n</sup>)</i>
- * using polynomial representation. For more information on the arithmetic see
- * for example IEEE Standard 1363 or <a
- * href=http://www.certicom.com/research/online.html> Certicom online-tutorial</a>.
- *
- * @see "GF2nField"
- * @see GF2nPolynomialField
- * @see GF2nONBElement
- * @see GF2Polynomial
- */
-public class GF2nPolynomialElement
- extends GF2nElement
-{
-
- // pre-computed Bitmask for fast masking, bitMask[a]=0x1 << a
- private static final int[] bitMask = {0x00000001, 0x00000002, 0x00000004,
- 0x00000008, 0x00000010, 0x00000020, 0x00000040, 0x00000080,
- 0x00000100, 0x00000200, 0x00000400, 0x00000800, 0x00001000,
- 0x00002000, 0x00004000, 0x00008000, 0x00010000, 0x00020000,
- 0x00040000, 0x00080000, 0x00100000, 0x00200000, 0x00400000,
- 0x00800000, 0x01000000, 0x02000000, 0x04000000, 0x08000000,
- 0x10000000, 0x20000000, 0x40000000, 0x80000000, 0x00000000};
-
- // the used GF2Polynomial which stores the coefficients
- private GF2Polynomial polynomial;
-
- /**
- * Create a new random GF2nPolynomialElement using the given field and
- * source of randomness.
- *
- * @param f the GF2nField to use
- * @param rand the source of randomness
- */
- public GF2nPolynomialElement(GF2nPolynomialField f, Random rand)
- {
- mField = f;
- mDegree = mField.getDegree();
- polynomial = new GF2Polynomial(mDegree);
- randomize(rand);
- }
-
- /**
- * Creates a new GF2nPolynomialElement using the given field and Bitstring.
- *
- * @param f the GF2nPolynomialField to use
- * @param bs the desired value as Bitstring
- */
- public GF2nPolynomialElement(GF2nPolynomialField f, GF2Polynomial bs)
- {
- mField = f;
- mDegree = mField.getDegree();
- polynomial = new GF2Polynomial(bs);
- polynomial.expandN(mDegree);
- }
-
- /**
- * Creates a new GF2nPolynomialElement using the given field <i>f</i> and
- * byte[] <i>os</i> as value. The conversion is done according to 1363.
- *
- * @param f the GF2nField to use
- * @param os the octet string to assign to this GF2nPolynomialElement
- * @see "P1363 5.5.5 p23, OS2FEP/OS2BSP"
- */
- public GF2nPolynomialElement(GF2nPolynomialField f, byte[] os)
- {
- mField = f;
- mDegree = mField.getDegree();
- polynomial = new GF2Polynomial(mDegree, os);
- polynomial.expandN(mDegree);
- }
-
- /**
- * Creates a new GF2nPolynomialElement using the given field <i>f</i> and
- * int[] <i>is</i> as value.
- *
- * @param f the GF2nField to use
- * @param is the integer string to assign to this GF2nPolynomialElement
- */
- public GF2nPolynomialElement(GF2nPolynomialField f, int[] is)
- {
- mField = f;
- mDegree = mField.getDegree();
- polynomial = new GF2Polynomial(mDegree, is);
- polynomial.expandN(f.mDegree);
- }
-
- /**
- * Creates a new GF2nPolynomialElement by cloning the given
- * GF2nPolynomialElement <i>b</i>.
- *
- * @param other the GF2nPolynomialElement to clone
- */
- public GF2nPolynomialElement(GF2nPolynomialElement other)
- {
- mField = other.mField;
- mDegree = other.mDegree;
- polynomial = new GF2Polynomial(other.polynomial);
- }
-
- // /////////////////////////////////////////////////////////////////////
- // pseudo-constructors
- // /////////////////////////////////////////////////////////////////////
-
- /**
- * Creates a new GF2nPolynomialElement by cloning this
- * GF2nPolynomialElement.
- *
- * @return a copy of this element
- */
- public Object clone()
- {
- return new GF2nPolynomialElement(this);
- }
-
- // /////////////////////////////////////////////////////////////////////
- // assignments
- // /////////////////////////////////////////////////////////////////////
-
- /**
- * Assigns the value 'zero' to this Polynomial.
- */
- void assignZero()
- {
- polynomial.assignZero();
- }
-
- /**
- * Create the zero element.
- *
- * @param f the finite field
- * @return the zero element in the given finite field
- */
- public static GF2nPolynomialElement ZERO(GF2nPolynomialField f)
- {
- GF2Polynomial polynomial = new GF2Polynomial(f.getDegree());
- return new GF2nPolynomialElement(f, polynomial);
- }
-
- /**
- * Create the one element.
- *
- * @param f the finite field
- * @return the one element in the given finite field
- */
- public static GF2nPolynomialElement ONE(GF2nPolynomialField f)
- {
- GF2Polynomial polynomial = new GF2Polynomial(f.getDegree(),
- new int[]{1});
- return new GF2nPolynomialElement(f, polynomial);
- }
-
- /**
- * Assigns the value 'one' to this Polynomial.
- */
- void assignOne()
- {
- polynomial.assignOne();
- }
-
- /**
- * Assign a random value to this GF2nPolynomialElement using the specified
- * source of randomness.
- *
- * @param rand the source of randomness
- */
- private void randomize(Random rand)
- {
- polynomial.expandN(mDegree);
- polynomial.randomize(rand);
- }
-
- // /////////////////////////////////////////////////////////////////////
- // comparison
- // /////////////////////////////////////////////////////////////////////
-
- /**
- * Checks whether this element is zero.
- *
- * @return <tt>true</tt> if <tt>this</tt> is the zero element
- */
- public boolean isZero()
- {
- return polynomial.isZero();
- }
-
- /**
- * Tests if the GF2nPolynomialElement has 'one' as value.
- *
- * @return true if <i>this</i> equals one (this == 1)
- */
- public boolean isOne()
- {
- return polynomial.isOne();
- }
-
- /**
- * Compare this element with another object.
- *
- * @param other the other object
- * @return <tt>true</tt> if the two objects are equal, <tt>false</tt>
- * otherwise
- */
- public boolean equals(Object other)
- {
- if (other == null || !(other instanceof GF2nPolynomialElement))
- {
- return false;
- }
- GF2nPolynomialElement otherElem = (GF2nPolynomialElement)other;
-
- if (mField != otherElem.mField)
- {
- if (!mField.getFieldPolynomial().equals(
- otherElem.mField.getFieldPolynomial()))
- {
- return false;
- }
- }
-
- return polynomial.equals(otherElem.polynomial);
- }
-
- /**
- * @return the hash code of this element
- */
- public int hashCode()
- {
- return mField.hashCode() + polynomial.hashCode();
- }
-
- // /////////////////////////////////////////////////////////////////////
- // access
- // /////////////////////////////////////////////////////////////////////
-
- /**
- * Returns the value of this GF2nPolynomialElement in a new Bitstring.
- *
- * @return the value of this GF2nPolynomialElement in a new Bitstring
- */
- private GF2Polynomial getGF2Polynomial()
- {
- return new GF2Polynomial(polynomial);
- }
-
- /**
- * Checks whether the indexed bit of the bit representation is set.
- *
- * @param index the index of the bit to test
- * @return <tt>true</tt> if the indexed bit is set
- */
- boolean testBit(int index)
- {
- return polynomial.testBit(index);
- }
-
- /**
- * Returns whether the rightmost bit of the bit representation is set. This
- * is needed for data conversion according to 1363.
- *
- * @return true if the rightmost bit of this element is set
- */
- public boolean testRightmostBit()
- {
- return polynomial.testBit(0);
- }
-
- /**
- * Compute the sum of this element and <tt>addend</tt>.
- *
- * @param addend the addend
- * @return <tt>this + other</tt> (newly created)
- * @throws DifferentFieldsException if the elements are of different fields.
- */
- public GFElement add(GFElement addend)
- throws RuntimeException
- {
- GF2nPolynomialElement result = new GF2nPolynomialElement(this);
- result.addToThis(addend);
- return result;
- }
-
- /**
- * Compute <tt>this + addend</tt> (overwrite <tt>this</tt>).
- *
- * @param addend the addend
- * @throws DifferentFieldsException if the elements are of different fields.
- */
- public void addToThis(GFElement addend)
- throws RuntimeException
- {
- if (!(addend instanceof GF2nPolynomialElement))
- {
- throw new RuntimeException();
- }
- if (!mField.equals(((GF2nPolynomialElement)addend).mField))
- {
- throw new RuntimeException();
- }
- polynomial.addToThis(((GF2nPolynomialElement)addend).polynomial);
- }
-
- /**
- * Returns <tt>this</tt> element + 'one".
- *
- * @return <tt>this</tt> + 'one'
- */
- public GF2nElement increase()
- {
- GF2nPolynomialElement result = new GF2nPolynomialElement(this);
- result.increaseThis();
- return result;
- }
-
- /**
- * Increases this element by 'one'.
- */
- public void increaseThis()
- {
- polynomial.increaseThis();
- }
-
- /**
- * Compute the product of this element and <tt>factor</tt>.
- *
- * @param factor the factor
- * @return <tt>this * factor</tt> (newly created)
- * @throws DifferentFieldsException if the elements are of different fields.
- */
- public GFElement multiply(GFElement factor)
- throws RuntimeException
- {
- GF2nPolynomialElement result = new GF2nPolynomialElement(this);
- result.multiplyThisBy(factor);
- return result;
- }
-
- /**
- * Compute <tt>this * factor</tt> (overwrite <tt>this</tt>).
- *
- * @param factor the factor
- * @throws DifferentFieldsException if the elements are of different fields.
- */
- public void multiplyThisBy(GFElement factor)
- throws RuntimeException
- {
- if (!(factor instanceof GF2nPolynomialElement))
- {
- throw new RuntimeException();
- }
- if (!mField.equals(((GF2nPolynomialElement)factor).mField))
- {
- throw new RuntimeException();
- }
- if (equals(factor))
- {
- squareThis();
- return;
- }
- polynomial = polynomial
- .multiply(((GF2nPolynomialElement)factor).polynomial);
- reduceThis();
- }
-
- /**
- * Compute the multiplicative inverse of this element.
- *
- * @return <tt>this<sup>-1</sup></tt> (newly created)
- * @throws ArithmeticException if <tt>this</tt> is the zero element.
- * @see GF2nPolynomialElement#invertMAIA
- * @see GF2nPolynomialElement#invertEEA
- * @see GF2nPolynomialElement#invertSquare
- */
- public GFElement invert()
- throws ArithmeticException
- {
- return invertMAIA();
- }
-
- /**
- * Calculates the multiplicative inverse of <i>this</i> and returns the
- * result in a new GF2nPolynomialElement.
- *
- * @return <i>this</i>^(-1)
- * @throws ArithmeticException if <i>this</i> equals zero
- */
- public GF2nPolynomialElement invertEEA()
- throws ArithmeticException
- {
- if (isZero())
- {
- throw new ArithmeticException();
- }
- GF2Polynomial b = new GF2Polynomial(mDegree + 32, "ONE");
- b.reduceN();
- GF2Polynomial c = new GF2Polynomial(mDegree + 32);
- c.reduceN();
- GF2Polynomial u = getGF2Polynomial();
- GF2Polynomial v = mField.getFieldPolynomial();
- GF2Polynomial h;
- int j;
- u.reduceN();
- while (!u.isOne())
- {
- u.reduceN();
- v.reduceN();
- j = u.getLength() - v.getLength();
- if (j < 0)
- {
- h = u;
- u = v;
- v = h;
- h = b;
- b = c;
- c = h;
- j = -j;
- c.reduceN(); // this increases the performance
- }
- u.shiftLeftAddThis(v, j);
- b.shiftLeftAddThis(c, j);
- }
- b.reduceN();
- return new GF2nPolynomialElement((GF2nPolynomialField)mField, b);
- }
-
- /**
- * Calculates the multiplicative inverse of <i>this</i> and returns the
- * result in a new GF2nPolynomialElement.
- *
- * @return <i>this</i>^(-1)
- * @throws ArithmeticException if <i>this</i> equals zero
- */
- public GF2nPolynomialElement invertSquare()
- throws ArithmeticException
- {
- GF2nPolynomialElement n;
- GF2nPolynomialElement u;
- int i, j, k, b;
-
- if (isZero())
- {
- throw new ArithmeticException();
- }
- // b = (n-1)
- b = mField.getDegree() - 1;
- // n = a
- n = new GF2nPolynomialElement(this);
- n.polynomial.expandN((mDegree << 1) + 32); // increase performance
- n.polynomial.reduceN();
- // k = 1
- k = 1;
-
- // for i = (r-1) downto 0 do, r=bitlength(b)
- for (i = IntegerFunctions.floorLog(b) - 1; i >= 0; i--)
- {
- // u = n
- u = new GF2nPolynomialElement(n);
- // for j = 1 to k do
- for (j = 1; j <= k; j++)
- {
- // u = u^2
- u.squareThisPreCalc();
- }
- // n = nu
- n.multiplyThisBy(u);
- // k = 2k
- k <<= 1;
- // if b(i)==1
- if ((b & bitMask[i]) != 0)
- {
- // n = n^2 * b
- n.squareThisPreCalc();
- n.multiplyThisBy(this);
- // k = k+1
- k += 1;
- }
- }
-
- // outpur n^2
- n.squareThisPreCalc();
- return n;
- }
-
- /**
- * Calculates the multiplicative inverse of <i>this</i> using the modified
- * almost inverse algorithm and returns the result in a new
- * GF2nPolynomialElement.
- *
- * @return <i>this</i>^(-1)
- * @throws ArithmeticException if <i>this</i> equals zero
- */
- public GF2nPolynomialElement invertMAIA()
- throws ArithmeticException
- {
- if (isZero())
- {
- throw new ArithmeticException();
- }
- GF2Polynomial b = new GF2Polynomial(mDegree, "ONE");
- GF2Polynomial c = new GF2Polynomial(mDegree);
- GF2Polynomial u = getGF2Polynomial();
- GF2Polynomial v = mField.getFieldPolynomial();
- GF2Polynomial h;
- while (true)
- {
- while (!u.testBit(0))
- { // x|u (x divides u)
- u.shiftRightThis(); // u = u / x
- if (!b.testBit(0))
- {
- b.shiftRightThis();
- }
- else
- {
- b.addToThis(mField.getFieldPolynomial());
- b.shiftRightThis();
- }
- }
- if (u.isOne())
- {
- return new GF2nPolynomialElement((GF2nPolynomialField)mField,
- b);
- }
- u.reduceN();
- v.reduceN();
- if (u.getLength() < v.getLength())
- {
- h = u;
- u = v;
- v = h;
- h = b;
- b = c;
- c = h;
- }
- u.addToThis(v);
- b.addToThis(c);
- }
- }
-
- /**
- * This method is used internally to map the square()-calls within
- * GF2nPolynomialElement to one of the possible squaring methods.
- *
- * @return <tt>this<sup>2</sup></tt> (newly created)
- * @see GF2nPolynomialElement#squarePreCalc
- */
- public GF2nElement square()
- {
- return squarePreCalc();
- }
-
- /**
- * This method is used internally to map the square()-calls within
- * GF2nPolynomialElement to one of the possible squaring methods.
- */
- public void squareThis()
- {
- squareThisPreCalc();
- }
-
- /**
- * Squares this GF2nPolynomialElement using GF2nField's squaring matrix.
- * This is supposed to be fast when using a polynomial (no tri- or
- * pentanomial) as fieldpolynomial. Use squarePreCalc when using a tri- or
- * pentanomial as fieldpolynomial instead.
- *
- * @return <tt>this<sup>2</sup></tt> (newly created)
- * @see GF2Polynomial#vectorMult
- * @see GF2nPolynomialElement#squarePreCalc
- * @see GF2nPolynomialElement#squareBitwise
- */
- public GF2nPolynomialElement squareMatrix()
- {
- GF2nPolynomialElement result = new GF2nPolynomialElement(this);
- result.squareThisMatrix();
- result.reduceThis();
- return result;
- }
-
- /**
- * Squares this GF2nPolynomialElement using GF2nFields squaring matrix. This
- * is supposed to be fast when using a polynomial (no tri- or pentanomial)
- * as fieldpolynomial. Use squarePreCalc when using a tri- or pentanomial as
- * fieldpolynomial instead.
- *
- * @see GF2Polynomial#vectorMult
- * @see GF2nPolynomialElement#squarePreCalc
- * @see GF2nPolynomialElement#squareBitwise
- */
- public void squareThisMatrix()
- {
- GF2Polynomial result = new GF2Polynomial(mDegree);
- for (int i = 0; i < mDegree; i++)
- {
- if (polynomial
- .vectorMult(((GF2nPolynomialField)mField).squaringMatrix[mDegree
- - i - 1]))
- {
- result.setBit(i);
-
- }
- }
- polynomial = result;
- }
-
- /**
- * Squares this GF2nPolynomialElement by shifting left its Bitstring and
- * reducing. This is supposed to be the slowest method. Use squarePreCalc or
- * squareMatrix instead.
- *
- * @return <tt>this<sup>2</sup></tt> (newly created)
- * @see GF2nPolynomialElement#squareMatrix
- * @see GF2nPolynomialElement#squarePreCalc
- * @see GF2Polynomial#squareThisBitwise
- */
- public GF2nPolynomialElement squareBitwise()
- {
- GF2nPolynomialElement result = new GF2nPolynomialElement(this);
- result.squareThisBitwise();
- result.reduceThis();
- return result;
- }
-
- /**
- * Squares this GF2nPolynomialElement by shifting left its Bitstring and
- * reducing. This is supposed to be the slowest method. Use squarePreCalc or
- * squareMatrix instead.
- *
- * @see GF2nPolynomialElement#squareMatrix
- * @see GF2nPolynomialElement#squarePreCalc
- * @see GF2Polynomial#squareThisBitwise
- */
- public void squareThisBitwise()
- {
- polynomial.squareThisBitwise();
- reduceThis();
- }
-
- /**
- * Squares this GF2nPolynomialElement by using precalculated values and
- * reducing. This is supposed to de fastest when using a trinomial or
- * pentanomial as field polynomial. Use squareMatrix when using a ordinary
- * polynomial as field polynomial.
- *
- * @return <tt>this<sup>2</sup></tt> (newly created)
- * @see GF2nPolynomialElement#squareMatrix
- * @see GF2Polynomial#squareThisPreCalc
- */
- public GF2nPolynomialElement squarePreCalc()
- {
- GF2nPolynomialElement result = new GF2nPolynomialElement(this);
- result.squareThisPreCalc();
- result.reduceThis();
- return result;
- }
-
- /**
- * Squares this GF2nPolynomialElement by using precalculated values and
- * reducing. This is supposed to de fastest when using a tri- or pentanomial
- * as fieldpolynomial. Use squareMatrix when using a ordinary polynomial as
- * fieldpolynomial.
- *
- * @see GF2nPolynomialElement#squareMatrix
- * @see GF2Polynomial#squareThisPreCalc
- */
- public void squareThisPreCalc()
- {
- polynomial.squareThisPreCalc();
- reduceThis();
- }
-
- /**
- * Calculates <i>this</i> to the power of <i>k</i> and returns the result
- * in a new GF2nPolynomialElement.
- *
- * @param k the power
- * @return <i>this</i>^<i>k</i> in a new GF2nPolynomialElement
- */
- public GF2nPolynomialElement power(int k)
- {
- if (k == 1)
- {
- return new GF2nPolynomialElement(this);
- }
-
- GF2nPolynomialElement result = GF2nPolynomialElement
- .ONE((GF2nPolynomialField)mField);
- if (k == 0)
- {
- return result;
- }
-
- GF2nPolynomialElement x = new GF2nPolynomialElement(this);
- x.polynomial.expandN((x.mDegree << 1) + 32); // increase performance
- x.polynomial.reduceN();
-
- for (int i = 0; i < mDegree; i++)
- {
- if ((k & (1 << i)) != 0)
- {
- result.multiplyThisBy(x);
- }
- x.square();
- }
-
- return result;
- }
-
- /**
- * Compute the square root of this element and return the result in a new
- * {@link GF2nPolynomialElement}.
- *
- * @return <tt>this<sup>1/2</sup></tt> (newly created)
- */
- public GF2nElement squareRoot()
- {
- GF2nPolynomialElement result = new GF2nPolynomialElement(this);
- result.squareRootThis();
- return result;
- }
-
- /**
- * Compute the square root of this element.
- */
- public void squareRootThis()
- {
- // increase performance
- polynomial.expandN((mDegree << 1) + 32);
- polynomial.reduceN();
- for (int i = 0; i < mField.getDegree() - 1; i++)
- {
- squareThis();
- }
- }
-
- /**
- * Solves the quadratic equation <tt>z<sup>2</sup> + z = this</tt> if
- * such a solution exists. This method returns one of the two possible
- * solutions. The other solution is <tt>z + 1</tt>. Use z.increase() to
- * compute this solution.
- *
- * @return a GF2nPolynomialElement representing one z satisfying the
- * equation <tt>z<sup>2</sup> + z = this</tt>
- * @throws NoSolutionException if no solution exists
- * @see "IEEE 1363, Annex A.4.7"
- */
- public GF2nElement solveQuadraticEquation()
- throws RuntimeException
- {
- if (isZero())
- {
- return ZERO((GF2nPolynomialField)mField);
- }
-
- if ((mDegree & 1) == 1)
- {
- return halfTrace();
- }
-
- // TODO this can be sped-up by precomputation of p and w's
- GF2nPolynomialElement z, w;
- do
- {
- // step 1.
- GF2nPolynomialElement p = new GF2nPolynomialElement(
- (GF2nPolynomialField)mField, new Random());
- // step 2.
- z = ZERO((GF2nPolynomialField)mField);
- w = (GF2nPolynomialElement)p.clone();
- // step 3.
- for (int i = 1; i < mDegree; i++)
- {
- // compute z = z^2 + w^2 * this
- // and w = w^2 + p
- z.squareThis();
- w.squareThis();
- z.addToThis(w.multiply(this));
- w.addToThis(p);
- }
- }
- while (w.isZero()); // step 4.
-
- if (!equals(z.square().add(z)))
- {
- throw new RuntimeException();
- }
-
- // step 5.
- return z;
- }
-
- /**
- * Returns the trace of this GF2nPolynomialElement.
- *
- * @return the trace of this GF2nPolynomialElement
- */
- public int trace()
- {
- GF2nPolynomialElement t = new GF2nPolynomialElement(this);
- int i;
-
- for (i = 1; i < mDegree; i++)
- {
- t.squareThis();
- t.addToThis(this);
- }
-
- if (t.isOne())
- {
- return 1;
- }
- return 0;
- }
-
- /**
- * Returns the half-trace of this GF2nPolynomialElement.
- *
- * @return a GF2nPolynomialElement representing the half-trace of this
- * GF2nPolynomialElement.
- * @throws DegreeIsEvenException if the degree of this GF2nPolynomialElement is even.
- */
- private GF2nPolynomialElement halfTrace()
- throws RuntimeException
- {
- if ((mDegree & 0x01) == 0)
- {
- throw new RuntimeException();
- }
- int i;
- GF2nPolynomialElement h = new GF2nPolynomialElement(this);
-
- for (i = 1; i <= ((mDegree - 1) >> 1); i++)
- {
- h.squareThis();
- h.squareThis();
- h.addToThis(this);
- }
-
- return h;
- }
-
- /**
- * Reduces this GF2nPolynomialElement modulo the field-polynomial.
- *
- * @see GF2Polynomial#reduceTrinomial
- * @see GF2Polynomial#reducePentanomial
- */
- private void reduceThis()
- {
- if (polynomial.getLength() > mDegree)
- { // really reduce ?
- if (((GF2nPolynomialField)mField).isTrinomial())
- { // fieldpolonomial
- // is trinomial
- int tc;
- try
- {
- tc = ((GF2nPolynomialField)mField).getTc();
- }
- catch (RuntimeException NATExc)
- {
- throw new RuntimeException(
- "GF2nPolynomialElement.reduce: the field"
- + " polynomial is not a trinomial");
- }
- if (((mDegree - tc) <= 32) // do we have to use slow
- // bitwise reduction ?
- || (polynomial.getLength() > (mDegree << 1)))
- {
- reduceTrinomialBitwise(tc);
- return;
- }
- polynomial.reduceTrinomial(mDegree, tc);
- return;
- }
- else if (((GF2nPolynomialField)mField).isPentanomial())
- { // fieldpolynomial
- // is
- // pentanomial
- int[] pc;
- try
- {
- pc = ((GF2nPolynomialField)mField).getPc();
- }
- catch (RuntimeException NATExc)
- {
- throw new RuntimeException(
- "GF2nPolynomialElement.reduce: the field"
- + " polynomial is not a pentanomial");
- }
- if (((mDegree - pc[2]) <= 32) // do we have to use slow
- // bitwise reduction ?
- || (polynomial.getLength() > (mDegree << 1)))
- {
- reducePentanomialBitwise(pc);
- return;
- }
- polynomial.reducePentanomial(mDegree, pc);
- return;
- }
- else
- { // fieldpolynomial is something else
- polynomial = polynomial.remainder(mField.getFieldPolynomial());
- polynomial.expandN(mDegree);
- return;
- }
- }
- if (polynomial.getLength() < mDegree)
- {
- polynomial.expandN(mDegree);
- }
- }
-
- /**
- * Reduce this GF2nPolynomialElement using the trinomial x^n + x^tc + 1 as
- * fieldpolynomial. The coefficients are reduced bit by bit.
- */
- private void reduceTrinomialBitwise(int tc)
- {
- int i;
- int k = mDegree - tc;
- for (i = polynomial.getLength() - 1; i >= mDegree; i--)
- {
- if (polynomial.testBit(i))
- {
-
- polynomial.xorBit(i);
- polynomial.xorBit(i - k);
- polynomial.xorBit(i - mDegree);
-
- }
- }
- polynomial.reduceN();
- polynomial.expandN(mDegree);
- }
-
- /**
- * Reduce this GF2nPolynomialElement using the pentanomial x^n + x^pc[2] +
- * x^pc[1] + x^pc[0] + 1 as fieldpolynomial. The coefficients are reduced
- * bit by bit.
- */
- private void reducePentanomialBitwise(int[] pc)
- {
- int i;
- int k = mDegree - pc[2];
- int l = mDegree - pc[1];
- int m = mDegree - pc[0];
- for (i = polynomial.getLength() - 1; i >= mDegree; i--)
- {
- if (polynomial.testBit(i))
- {
- polynomial.xorBit(i);
- polynomial.xorBit(i - k);
- polynomial.xorBit(i - l);
- polynomial.xorBit(i - m);
- polynomial.xorBit(i - mDegree);
-
- }
- }
- polynomial.reduceN();
- polynomial.expandN(mDegree);
- }
-
- // /////////////////////////////////////////////////////////////////////
- // conversion
- // /////////////////////////////////////////////////////////////////////
-
- /**
- * Returns a string representing this Bitstrings value using hexadecimal
- * radix in MSB-first order.
- *
- * @return a String representing this Bitstrings value.
- */
- public String toString()
- {
- return polynomial.toString(16);
- }
-
- /**
- * Returns a string representing this Bitstrings value using hexadecimal or
- * binary radix in MSB-first order.
- *
- * @param radix the radix to use (2 or 16, otherwise 2 is used)
- * @return a String representing this Bitstrings value.
- */
- public String toString(int radix)
- {
- return polynomial.toString(radix);
- }
-
- /**
- * Converts this GF2nPolynomialElement to a byte[] according to 1363.
- *
- * @return a byte[] representing the value of this GF2nPolynomialElement
- * @see "P1363 5.5.2 p22f BS2OSP, FE2OSP"
- */
- public byte[] toByteArray()
- {
- return polynomial.toByteArray();
- }
-
- /**
- * Converts this GF2nPolynomialElement to an integer according to 1363.
- *
- * @return a BigInteger representing the value of this
- * GF2nPolynomialElement
- * @see "P1363 5.5.1 p22 BS2IP"
- */
- public BigInteger toFlexiBigInt()
- {
- return polynomial.toFlexiBigInt();
- }
-
-}
diff --git a/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2nPolynomialField.java b/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2nPolynomialField.java
deleted file mode 100644
index f66ec20..0000000
--- a/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GF2nPolynomialField.java
+++ /dev/null
@@ -1,553 +0,0 @@
-package org.bouncycastle.pqc.math.linearalgebra;
-
-
-import java.util.Random;
-import java.util.Vector;
-
-
-/**
- * This class implements the abstract class <tt>GF2nField</tt> for polynomial
- * representation. It computes the field polynomial and the squaring matrix.
- * GF2nField is used by GF2nPolynomialElement which implements the elements of
- * this field.
- *
- * @see GF2nField
- * @see GF2nPolynomialElement
- */
-public class GF2nPolynomialField
- extends GF2nField
-{
-
- /**
- * Matrix used for fast squaring
- */
- GF2Polynomial[] squaringMatrix;
-
- // field polynomial is a trinomial
- private boolean isTrinomial = false;
-
- // field polynomial is a pentanomial
- private boolean isPentanomial = false;
-
- // middle coefficient of the field polynomial in case it is a trinomial
- private int tc;
-
- // middle 3 coefficients of the field polynomial in case it is a pentanomial
- private int[] pc = new int[3];
-
- /**
- * constructs an instance of the finite field with 2<sup>deg</sup>
- * elements and characteristic 2.
- *
- * @param deg the extention degree of this field
- */
- public GF2nPolynomialField(int deg)
- {
- if (deg < 3)
- {
- throw new IllegalArgumentException("k must be at least 3");
- }
- mDegree = deg;
- computeFieldPolynomial();
- computeSquaringMatrix();
- fields = new Vector();
- matrices = new Vector();
- }
-
- /**
- * constructs an instance of the finite field with 2<sup>deg</sup>
- * elements and characteristic 2.
- *
- * @param deg the degree of this field
- * @param file true if you want to read the field polynomial from the
- * file false if you want to use a random fielpolynomial
- * (this can take very long for huge degrees)
- */
- public GF2nPolynomialField(int deg, boolean file)
- {
- if (deg < 3)
- {
- throw new IllegalArgumentException("k must be at least 3");
- }
- mDegree = deg;
- if (file)
- {
- computeFieldPolynomial();
- }
- else
- {
- computeFieldPolynomial2();
- }
- computeSquaringMatrix();
- fields = new Vector();
- matrices = new Vector();
- }
-
- /**
- * Creates a new GF2nField of degree <i>i</i> and uses the given
- * <i>polynomial</i> as field polynomial. The <i>polynomial</i> is checked
- * whether it is irreducible. This can take some time if <i>i</i> is huge!
- *
- * @param deg degree of the GF2nField
- * @param polynomial the field polynomial to use
- * @throws PolynomialIsNotIrreducibleException if the given polynomial is not irreducible in GF(2^<i>i</i>)
- */
- public GF2nPolynomialField(int deg, GF2Polynomial polynomial)
- throws RuntimeException
- {
- if (deg < 3)
- {
- throw new IllegalArgumentException("degree must be at least 3");
- }
- if (polynomial.getLength() != deg + 1)
- {
- throw new RuntimeException();
- }
- if (!polynomial.isIrreducible())
- {
- throw new RuntimeException();
- }
- mDegree = deg;
- // fieldPolynomial = new Bitstring(polynomial);
- fieldPolynomial = polynomial;
- computeSquaringMatrix();
- int k = 2; // check if the polynomial is a trinomial or pentanomial
- for (int j = 1; j < fieldPolynomial.getLength() - 1; j++)
- {
- if (fieldPolynomial.testBit(j))
- {
- k++;
- if (k == 3)
- {
- tc = j;
- }
- if (k <= 5)
- {
- pc[k - 3] = j;
- }
- }
- }
- if (k == 3)
- {
- isTrinomial = true;
- }
- if (k == 5)
- {
- isPentanomial = true;
- }
- fields = new Vector();
- matrices = new Vector();
- }
-
- /**
- * Returns true if the field polynomial is a trinomial. The coefficient can
- * be retrieved using getTc().
- *
- * @return true if the field polynomial is a trinomial
- */
- public boolean isTrinomial()
- {
- return isTrinomial;
- }
-
- /**
- * Returns true if the field polynomial is a pentanomial. The coefficients
- * can be retrieved using getPc().
- *
- * @return true if the field polynomial is a pentanomial
- */
- public boolean isPentanomial()
- {
- return isPentanomial;
- }
-
- /**
- * Returns the degree of the middle coefficient of the used field trinomial
- * (x^n + x^(getTc()) + 1).
- *
- * @return the middle coefficient of the used field trinomial
- * @throws GFException if the field polynomial is not a trinomial
- */
- public int getTc()
- throws RuntimeException
- {
- if (!isTrinomial)
- {
- throw new RuntimeException();
- }
- return tc;
- }
-
- /**
- * Returns the degree of the middle coefficients of the used field
- * pentanomial (x^n + x^(getPc()[2]) + x^(getPc()[1]) + x^(getPc()[0]) + 1).
- *
- * @return the middle coefficients of the used field pentanomial
- * @throws GFException if the field polynomial is not a pentanomial
- */
- public int[] getPc()
- throws RuntimeException
- {
- if (!isPentanomial)
- {
- throw new RuntimeException();
- }
- int[] result = new int[3];
- System.arraycopy(pc, 0, result, 0, 3);
- return result;
- }
-
- /**
- * Return row vector i of the squaring matrix.
- *
- * @param i the index of the row vector to return
- * @return a copy of squaringMatrix[i]
- * @see GF2nPolynomialElement#squareMatrix
- */
- public GF2Polynomial getSquaringVector(int i)
- {
- return new GF2Polynomial(squaringMatrix[i]);
- }
-
- /**
- * Compute a random root of the given GF2Polynomial.
- *
- * @param polynomial the polynomial
- * @return a random root of <tt>polynomial</tt>
- */
- protected GF2nElement getRandomRoot(GF2Polynomial polynomial)
- {
- // We are in B1!!!
- GF2nPolynomial c;
- GF2nPolynomial ut;
- GF2nElement u;
- GF2nPolynomial h;
- int hDegree;
- // 1. Set g(t) <- f(t)
- GF2nPolynomial g = new GF2nPolynomial(polynomial, this);
- int gDegree = g.getDegree();
- int i;
-
- // 2. while deg(g) > 1
- while (gDegree > 1)
- {
- do
- {
- // 2.1 choose random u (element of) GF(2^m)
- u = new GF2nPolynomialElement(this, new Random());
- ut = new GF2nPolynomial(2, GF2nPolynomialElement.ZERO(this));
- // 2.2 Set c(t) <- ut
- ut.set(1, u);
- c = new GF2nPolynomial(ut);
- // 2.3 For i from 1 to m-1 do
- for (i = 1; i <= mDegree - 1; i++)
- {
- // 2.3.1 c(t) <- (c(t)^2 + ut) mod g(t)
- c = c.multiplyAndReduce(c, g);
- c = c.add(ut);
- }
- // 2.4 set h(t) <- GCD(c(t), g(t))
- h = c.gcd(g);
- // 2.5 if h(t) is constant or deg(g) = deg(h) then go to
- // step 2.1
- hDegree = h.getDegree();
- gDegree = g.getDegree();
- }
- while ((hDegree == 0) || (hDegree == gDegree));
- // 2.6 If 2deg(h) > deg(g) then set g(t) <- g(t)/h(t) ...
- if ((hDegree << 1) > gDegree)
- {
- g = g.quotient(h);
- }
- else
- {
- // ... else g(t) <- h(t)
- g = new GF2nPolynomial(h);
- }
- gDegree = g.getDegree();
- }
- // 3. Output g(0)
- return g.at(0);
-
- }
-
- /**
- * Computes the change-of-basis matrix for basis conversion according to
- * 1363. The result is stored in the lists fields and matrices.
- *
- * @param B1 the GF2nField to convert to
- * @see "P1363 A.7.3, p111ff"
- */
- protected void computeCOBMatrix(GF2nField B1)
- {
- // we are in B0 here!
- if (mDegree != B1.mDegree)
- {
- throw new IllegalArgumentException(
- "GF2nPolynomialField.computeCOBMatrix: B1 has a different "
- + "degree and thus cannot be coverted to!");
- }
- if (B1 instanceof GF2nONBField)
- {
- // speedup (calculation is done in PolynomialElements instead of
- // ONB)
- B1.computeCOBMatrix(this);
- return;
- }
- int i, j;
- GF2nElement[] gamma;
- GF2nElement u;
- GF2Polynomial[] COBMatrix = new GF2Polynomial[mDegree];
- for (i = 0; i < mDegree; i++)
- {
- COBMatrix[i] = new GF2Polynomial(mDegree);
- }
-
- // find Random Root
- do
- {
- // u is in representation according to B1
- u = B1.getRandomRoot(fieldPolynomial);
- }
- while (u.isZero());
-
- // build gamma matrix by multiplying by u
- if (u instanceof GF2nONBElement)
- {
- gamma = new GF2nONBElement[mDegree];
- gamma[mDegree - 1] = GF2nONBElement.ONE((GF2nONBField)B1);
- }
- else
- {
- gamma = new GF2nPolynomialElement[mDegree];
- gamma[mDegree - 1] = GF2nPolynomialElement
- .ONE((GF2nPolynomialField)B1);
- }
- gamma[mDegree - 2] = u;
- for (i = mDegree - 3; i >= 0; i--)
- {
- gamma[i] = (GF2nElement)gamma[i + 1].multiply(u);
- }
- if (B1 instanceof GF2nONBField)
- {
- // convert horizontal gamma matrix by vertical Bitstrings
- for (i = 0; i < mDegree; i++)
- {
- for (j = 0; j < mDegree; j++)
- {
- // TODO remember: ONB treats its Bits in reverse order !!!
- if (gamma[i].testBit(mDegree - j - 1))
- {
- COBMatrix[mDegree - j - 1].setBit(mDegree - i - 1);
- }
- }
- }
- }
- else
- {
- // convert horizontal gamma matrix by vertical Bitstrings
- for (i = 0; i < mDegree; i++)
- {
- for (j = 0; j < mDegree; j++)
- {
- if (gamma[i].testBit(j))
- {
- COBMatrix[mDegree - j - 1].setBit(mDegree - i - 1);
- }
- }
- }
- }
-
- // store field and matrix for further use
- fields.addElement(B1);
- matrices.addElement(COBMatrix);
- // store field and inverse matrix for further use in B1
- B1.fields.addElement(this);
- B1.matrices.addElement(invertMatrix(COBMatrix));
- }
-
- /**
- * Computes a new squaring matrix used for fast squaring.
- *
- * @see GF2nPolynomialElement#square
- */
- private void computeSquaringMatrix()
- {
- GF2Polynomial[] d = new GF2Polynomial[mDegree - 1];
- int i, j;
- squaringMatrix = new GF2Polynomial[mDegree];
- for (i = 0; i < squaringMatrix.length; i++)
- {
- squaringMatrix[i] = new GF2Polynomial(mDegree, "ZERO");
- }
-
- for (i = 0; i < mDegree - 1; i++)
- {
- d[i] = new GF2Polynomial(1, "ONE").shiftLeft(mDegree + i)
- .remainder(fieldPolynomial);
- }
- for (i = 1; i <= Math.abs(mDegree >> 1); i++)
- {
- for (j = 1; j <= mDegree; j++)
- {
- if (d[mDegree - (i << 1)].testBit(mDegree - j))
- {
- squaringMatrix[j - 1].setBit(mDegree - i);
- }
- }
- }
- for (i = Math.abs(mDegree >> 1) + 1; i <= mDegree; i++)
- {
- squaringMatrix[(i << 1) - mDegree - 1].setBit(mDegree - i);
- }
-
- }
-
- /**
- * Computes the field polynomial. This can take a long time for big degrees.
- */
- protected void computeFieldPolynomial()
- {
- if (testTrinomials())
- {
- return;
- }
- if (testPentanomials())
- {
- return;
- }
- testRandom();
- }
-
- /**
- * Computes the field polynomial. This can take a long time for big degrees.
- */
- protected void computeFieldPolynomial2()
- {
- if (testTrinomials())
- {
- return;
- }
- if (testPentanomials())
- {
- return;
- }
- testRandom();
- }
-
- /**
- * Tests all trinomials of degree (n+1) until a irreducible is found and
- * stores the result in <i>field polynomial</i>. Returns false if no
- * irreducible trinomial exists in GF(2^n). This can take very long for huge
- * degrees.
- *
- * @return true if an irreducible trinomial is found
- */
- private boolean testTrinomials()
- {
- int i, l;
- boolean done = false;
- l = 0;
-
- fieldPolynomial = new GF2Polynomial(mDegree + 1);
- fieldPolynomial.setBit(0);
- fieldPolynomial.setBit(mDegree);
- for (i = 1; (i < mDegree) && !done; i++)
- {
- fieldPolynomial.setBit(i);
- done = fieldPolynomial.isIrreducible();
- l++;
- if (done)
- {
- isTrinomial = true;
- tc = i;
- return done;
- }
- fieldPolynomial.resetBit(i);
- done = fieldPolynomial.isIrreducible();
- }
-
- return done;
- }
-
- /**
- * Tests all pentanomials of degree (n+1) until a irreducible is found and
- * stores the result in <i>field polynomial</i>. Returns false if no
- * irreducible pentanomial exists in GF(2^n). This can take very long for
- * huge degrees.
- *
- * @return true if an irreducible pentanomial is found
- */
- private boolean testPentanomials()
- {
- int i, j, k, l;
- boolean done = false;
- l = 0;
-
- fieldPolynomial = new GF2Polynomial(mDegree + 1);
- fieldPolynomial.setBit(0);
- fieldPolynomial.setBit(mDegree);
- for (i = 1; (i <= (mDegree - 3)) && !done; i++)
- {
- fieldPolynomial.setBit(i);
- for (j = i + 1; (j <= (mDegree - 2)) && !done; j++)
- {
- fieldPolynomial.setBit(j);
- for (k = j + 1; (k <= (mDegree - 1)) && !done; k++)
- {
- fieldPolynomial.setBit(k);
- if (((mDegree & 1) != 0) | ((i & 1) != 0) | ((j & 1) != 0)
- | ((k & 1) != 0))
- {
- done = fieldPolynomial.isIrreducible();
- l++;
- if (done)
- {
- isPentanomial = true;
- pc[0] = i;
- pc[1] = j;
- pc[2] = k;
- return done;
- }
- }
- fieldPolynomial.resetBit(k);
- }
- fieldPolynomial.resetBit(j);
- }
- fieldPolynomial.resetBit(i);
- }
-
- return done;
- }
-
- /**
- * Tests random polynomials of degree (n+1) until an irreducible is found
- * and stores the result in <i>field polynomial</i>. This can take very
- * long for huge degrees.
- *
- * @return true
- */
- private boolean testRandom()
- {
- int l;
- boolean done = false;
-
- fieldPolynomial = new GF2Polynomial(mDegree + 1);
- l = 0;
- while (!done)
- {
- l++;
- fieldPolynomial.randomize();
- fieldPolynomial.setBit(mDegree);
- fieldPolynomial.setBit(0);
- if (fieldPolynomial.isIrreducible())
- {
- done = true;
- return done;
- }
- }
-
- return done;
- }
-
-}
diff --git a/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GFElement.java b/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GFElement.java
deleted file mode 100644
index 1e93e15..0000000
--- a/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GFElement.java
+++ /dev/null
@@ -1,158 +0,0 @@
-package org.bouncycastle.pqc.math.linearalgebra;
-
-import java.math.BigInteger;
-
-
-/**
- * This interface defines a finite field element. It is implemented by the
- * classes {@link GFPElement} and {@link GF2nElement}.
- *
- * @see GFPElement
- * @see GF2nElement
- */
-public interface GFElement
-{
-
- /**
- * @return a copy of this GFElement
- */
- Object clone();
-
- // /////////////////////////////////////////////////////////////////
- // comparison
- // /////////////////////////////////////////////////////////////////
-
- /**
- * Compare this curve with another object.
- *
- * @param other the other object
- * @return the result of the comparison
- */
- boolean equals(Object other);
-
- /**
- * @return the hash code of this element
- */
- int hashCode();
-
- /**
- * Checks whether this element is zero.
- *
- * @return <tt>true</tt> if <tt>this</tt> is the zero element
- */
- boolean isZero();
-
- /**
- * Checks whether this element is one.
- *
- * @return <tt>true</tt> if <tt>this</tt> is the one element
- */
- boolean isOne();
-
- // /////////////////////////////////////////////////////////////////////
- // arithmetic
- // /////////////////////////////////////////////////////////////////////
-
- /**
- * Compute the sum of this element and the addend.
- *
- * @param addend the addend
- * @return <tt>this + other</tt> (newly created)
- * @throws DifferentFieldsException if the elements are of different fields.
- */
- GFElement add(GFElement addend)
- throws RuntimeException;
-
- /**
- * Compute the sum of this element and the addend, overwriting this element.
- *
- * @param addend the addend
- * @throws DifferentFieldsException if the elements are of different fields.
- */
- void addToThis(GFElement addend)
- throws RuntimeException;
-
- /**
- * Compute the difference of this element and <tt>minuend</tt>.
- *
- * @param minuend the minuend
- * @return <tt>this - minuend</tt> (newly created)
- * @throws DifferentFieldsException if the elements are of different fields.
- */
- GFElement subtract(GFElement minuend)
- throws RuntimeException;
-
- /**
- * Compute the difference of this element and <tt>minuend</tt>,
- * overwriting this element.
- *
- * @param minuend the minuend
- * @throws DifferentFieldsException if the elements are of different fields.
- */
- void subtractFromThis(GFElement minuend);
-
- /**
- * Compute the product of this element and <tt>factor</tt>.
- *
- * @param factor the factor
- * @return <tt>this * factor</tt> (newly created)
- * @throws DifferentFieldsException if the elements are of different fields.
- */
- GFElement multiply(GFElement factor)
- throws RuntimeException;
-
- /**
- * Compute <tt>this * factor</tt> (overwrite <tt>this</tt>).
- *
- * @param factor the factor
- * @throws DifferentFieldsException if the elements are of different fields.
- */
- void multiplyThisBy(GFElement factor)
- throws RuntimeException;
-
- /**
- * Compute the multiplicative inverse of this element.
- *
- * @return <tt>this<sup>-1</sup></tt> (newly created)
- * @throws ArithmeticException if <tt>this</tt> is the zero element.
- */
- GFElement invert()
- throws ArithmeticException;
-
- // /////////////////////////////////////////////////////////////////////
- // conversion
- // /////////////////////////////////////////////////////////////////////
-
- /**
- * Returns this element as FlexiBigInt. The conversion is <a
- * href="http://grouper.ieee.org/groups/1363/">P1363</a>-conform.
- *
- * @return this element as BigInt
- */
- BigInteger toFlexiBigInt();
-
- /**
- * Returns this element as byte array. The conversion is <a href =
- * "http://grouper.ieee.org/groups/1363/">P1363</a>-conform.
- *
- * @return this element as byte array
- */
- byte[] toByteArray();
-
- /**
- * Return a String representation of this element.
- *
- * @return String representation of this element
- */
- String toString();
-
- /**
- * Return a String representation of this element. <tt>radix</tt>
- * specifies the radix of the String representation.
- *
- * @param radix specifies the radix of the String representation
- * @return String representation of this element with the specified radix
- */
- String toString(int radix);
-
-}
diff --git a/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GoppaCode.java b/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GoppaCode.java
deleted file mode 100644
index cf82eae..0000000
--- a/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/GoppaCode.java
+++ /dev/null
@@ -1,310 +0,0 @@
-package org.bouncycastle.pqc.math.linearalgebra;
-
-import java.security.SecureRandom;
-
-/**
- * This class describes decoding operations of an irreducible binary Goppa code.
- * A check matrix H of the Goppa code and an irreducible Goppa polynomial are
- * used the operations are worked over a finite field GF(2^m)
- *
- * @see GF2mField
- * @see PolynomialGF2mSmallM
- */
-public final class GoppaCode
-{
-
- /**
- * Default constructor (private).
- */
- private GoppaCode()
- {
- // empty
- }
-
- /**
- * This class is a container for two instances of {@link GF2Matrix} and one
- * instance of {@link Permutation}. It is used to hold the systematic form
- * <tt>S*H*P = (Id|M)</tt> of the check matrix <tt>H</tt> as returned by
- * {@link GoppaCode#computeSystematicForm(GF2Matrix, SecureRandom)}.
- *
- * @see GF2Matrix
- * @see Permutation
- */
- public static class MaMaPe
- {
-
- private GF2Matrix s, h;
-
- private Permutation p;
-
- /**
- * Construct a new {@link MaMaPe} container with the given parameters.
- *
- * @param s the first matrix
- * @param h the second matrix
- * @param p the permutation
- */
- public MaMaPe(GF2Matrix s, GF2Matrix h, Permutation p)
- {
- this.s = s;
- this.h = h;
- this.p = p;
- }
-
- /**
- * @return the first matrix
- */
- public GF2Matrix getFirstMatrix()
- {
- return s;
- }
-
- /**
- * @return the second matrix
- */
- public GF2Matrix getSecondMatrix()
- {
- return h;
- }
-
- /**
- * @return the permutation
- */
- public Permutation getPermutation()
- {
- return p;
- }
- }
-
- /**
- * This class is a container for an instance of {@link GF2Matrix} and one
- * int[]. It is used to hold a generator matrix and the set of indices such
- * that the submatrix of the generator matrix consisting of the specified
- * columns is the identity.
- *
- * @see GF2Matrix
- * @see Permutation
- */
- public static class MatrixSet
- {
-
- private GF2Matrix g;
-
- private int[] setJ;
-
- /**
- * Construct a new {@link MatrixSet} container with the given
- * parameters.
- *
- * @param g the generator matrix
- * @param setJ the set of indices such that the submatrix of the
- * generator matrix consisting of the specified columns
- * is the identity
- */
- public MatrixSet(GF2Matrix g, int[] setJ)
- {
- this.g = g;
- this.setJ = setJ;
- }
-
- /**
- * @return the generator matrix
- */
- public GF2Matrix getG()
- {
- return g;
- }
-
- /**
- * @return the set of indices such that the submatrix of the generator
- * matrix consisting of the specified columns is the identity
- */
- public int[] getSetJ()
- {
- return setJ;
- }
- }
-
- /**
- * Construct the check matrix of a Goppa code in canonical form from the
- * irreducible Goppa polynomial over the finite field
- * <tt>GF(2<sup>m</sup>)</tt>.
- *
- * @param field the finite field
- * @param gp the irreducible Goppa polynomial
- */
- public static GF2Matrix createCanonicalCheckMatrix(GF2mField field,
- PolynomialGF2mSmallM gp)
- {
- int m = field.getDegree();
- int n = 1 << m;
- int t = gp.getDegree();
-
- /* create matrix H over GF(2^m) */
-
- int[][] hArray = new int[t][n];
-
- // create matrix YZ
- int[][] yz = new int[t][n];
- for (int j = 0; j < n; j++)
- {
- // here j is used as index and as element of field GF(2^m)
- yz[0][j] = field.inverse(gp.evaluateAt(j));
- }
-
- for (int i = 1; i < t; i++)
- {
- for (int j = 0; j < n; j++)
- {
- // here j is used as index and as element of field GF(2^m)
- yz[i][j] = field.mult(yz[i - 1][j], j);
- }
- }
-
- // create matrix H = XYZ
- for (int i = 0; i < t; i++)
- {
- for (int j = 0; j < n; j++)
- {
- for (int k = 0; k <= i; k++)
- {
- hArray[i][j] = field.add(hArray[i][j], field.mult(yz[k][j],
- gp.getCoefficient(t + k - i)));
- }
- }
- }
-
- /* convert to matrix over GF(2) */
-
- int[][] result = new int[t * m][(n + 31) >>> 5];
-
- for (int j = 0; j < n; j++)
- {
- int q = j >>> 5;
- int r = 1 << (j & 0x1f);
- for (int i = 0; i < t; i++)
- {
- int e = hArray[i][j];
- for (int u = 0; u < m; u++)
- {
- int b = (e >>> u) & 1;
- if (b != 0)
- {
- int ind = (i + 1) * m - u - 1;
- result[ind][q] ^= r;
- }
- }
- }
- }
-
- return new GF2Matrix(n, result);
- }
-
- /**
- * Given a check matrix <tt>H</tt>, compute matrices <tt>S</tt>,
- * <tt>M</tt>, and a random permutation <tt>P</tt> such that
- * <tt>S*H*P = (Id|M)</tt>. Return <tt>S^-1</tt>, <tt>M</tt>, and
- * <tt>P</tt> as {@link MaMaPe}. The matrix <tt>(Id | M)</tt> is called
- * the systematic form of H.
- *
- * @param h the check matrix
- * @param sr a source of randomness
- * @return the tuple <tt>(S^-1, M, P)</tt>
- */
- public static MaMaPe computeSystematicForm(GF2Matrix h, SecureRandom sr)
- {
- int n = h.getNumColumns();
- GF2Matrix hp, sInv;
- GF2Matrix s = null;
- Permutation p;
- boolean found = false;
-
- do
- {
- p = new Permutation(n, sr);
- hp = (GF2Matrix)h.rightMultiply(p);
- sInv = hp.getLeftSubMatrix();
- try
- {
- found = true;
- s = (GF2Matrix)sInv.computeInverse();
- }
- catch (ArithmeticException ae)
- {
- found = false;
- }
- }
- while (!found);
-
- GF2Matrix shp = (GF2Matrix)s.rightMultiply(hp);
- GF2Matrix m = shp.getRightSubMatrix();
-
- return new MaMaPe(sInv, m, p);
- }
-
- /**
- * Find an error vector <tt>e</tt> over <tt>GF(2)</tt> from an input
- * syndrome <tt>s</tt> over <tt>GF(2<sup>m</sup>)</tt>.
- *
- * @param syndVec the syndrome
- * @param field the finite field
- * @param gp the irreducible Goppa polynomial
- * @param sqRootMatrix the matrix for computing square roots in
- * <tt>(GF(2<sup>m</sup>))<sup>t</sup></tt>
- * @return the error vector
- */
- public static GF2Vector syndromeDecode(GF2Vector syndVec, GF2mField field,
- PolynomialGF2mSmallM gp, PolynomialGF2mSmallM[] sqRootMatrix)
- {
-
- int n = 1 << field.getDegree();
-
- // the error vector
- GF2Vector errors = new GF2Vector(n);
-
- // if the syndrome vector is zero, the error vector is also zero
- if (!syndVec.isZero())
- {
- // convert syndrome vector to polynomial over GF(2^m)
- PolynomialGF2mSmallM syndrome = new PolynomialGF2mSmallM(syndVec
- .toExtensionFieldVector(field));
-
- // compute T = syndrome^-1 mod gp
- PolynomialGF2mSmallM t = syndrome.modInverse(gp);
-
- // compute tau = sqRoot(T + X) mod gp
- PolynomialGF2mSmallM tau = t.addMonomial(1);
- tau = tau.modSquareRootMatrix(sqRootMatrix);
-
- // compute polynomials a and b satisfying a + b*tau = 0 mod gp
- PolynomialGF2mSmallM[] ab = tau.modPolynomialToFracton(gp);
-
- // compute the polynomial a^2 + X*b^2
- PolynomialGF2mSmallM a2 = ab[0].multiply(ab[0]);
- PolynomialGF2mSmallM b2 = ab[1].multiply(ab[1]);
- PolynomialGF2mSmallM xb2 = b2.multWithMonomial(1);
- PolynomialGF2mSmallM a2plusXb2 = a2.add(xb2);
-
- // normalize a^2 + X*b^2 to obtain the error locator polynomial
- int headCoeff = a2plusXb2.getHeadCoefficient();
- int invHeadCoeff = field.inverse(headCoeff);
- PolynomialGF2mSmallM elp = a2plusXb2.multWithElement(invHeadCoeff);
-
- // for all elements i of GF(2^m)
- for (int i = 0; i < n; i++)
- {
- // evaluate the error locator polynomial at i
- int z = elp.evaluateAt(i);
- // if polynomial evaluates to zero
- if (z == 0)
- {
- // set the i-th coefficient of the error vector
- errors.setBit(i);
- }
- }
- }
-
- return errors;
- }
-
-}
diff --git a/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/IntUtils.java b/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/IntUtils.java
deleted file mode 100644
index 90a3c60..0000000
--- a/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/IntUtils.java
+++ /dev/null
@@ -1,202 +0,0 @@
-package org.bouncycastle.pqc.math.linearalgebra;
-
-import java.math.BigInteger;
-
-/**
- *
- *
- *
- */
-public final 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 boolean equals(int[] left, int[] right)
- {
- if (left.length != right.length)
- {
- return false;
- }
- boolean result = true;
- for (int i = left.length - 1; i >= 0; i--)
- {
- result &= left[i] == right[i];
- }
- return result;
- }
-
- /**
- * 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)
- {
- int[] result = new int[array.length];
- System.arraycopy(array, 0, result, 0, array.length);
- return result;
- }
-
- /**
- * 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)
- {
- for (int i = array.length - 1; i >= 0; i--)
- {
- array[i] = 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;
-
- for (int i = left; i < right; i++)
- {
- if (source[i] <= pivot)
- {
- int tmp = source[index];
- source[index] = source[i];
- source[i] = tmp;
- index++;
- }
- }
-
- int 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(final int[] input, final int start,
- final int end)
- {
- int[] result = new int[end - start];
- System.arraycopy(input, start, result, 0, end - start);
- return result;
- }
-
- /**
- * Convert an int array to a {@link FlexiBigInt} array.
- *
- * @param input the int array
- * @return the {@link FlexiBigInt} array
- */
- public static BigInteger[] toFlexiBigIntArray(int[] input)
- {
- BigInteger[] result = new BigInteger[input.length];
- for (int i = 0; i < input.length; i++)
- {
- result[i] = BigInteger.valueOf(input[i]);
- }
- 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;
- }
-
- /**
- * @param input an int arary
- * @return the int array as hex string
- */
- public static String toHexString(int[] input)
- {
- return ByteUtils.toHexString(BigEndianConversions.toByteArray(input));
- }
-
-}
diff --git a/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/IntegerFunctions.java b/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/IntegerFunctions.java
deleted file mode 100644
index 779f384..0000000
--- a/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/IntegerFunctions.java
+++ /dev/null
@@ -1,1423 +0,0 @@
-package org.bouncycastle.pqc.math.linearalgebra;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-/**
- * Class of number-theory related functions for use with integers represented as
- * <tt>int</tt>'s or <tt>BigInteger</tt> objects.
- */
-public final class IntegerFunctions
-{
-
- private static final BigInteger ZERO = BigInteger.valueOf(0);
-
- private static final BigInteger ONE = BigInteger.valueOf(1);
-
- private static final BigInteger TWO = BigInteger.valueOf(2);
-
- private static final BigInteger FOUR = BigInteger.valueOf(4);
-
- private static final int[] SMALL_PRIMES = {3, 5, 7, 11, 13, 17, 19, 23,
- 29, 31, 37, 41};
-
- private static final long SMALL_PRIME_PRODUCT = 3L * 5 * 7 * 11 * 13 * 17
- * 19 * 23 * 29 * 31 * 37 * 41;
-
- private static SecureRandom sr = null;
-
- // the jacobi function uses this lookup table
- private static final int[] jacobiTable = {0, 1, 0, -1, 0, -1, 0, 1};
-
- private IntegerFunctions()
- {
- // empty
- }
-
- /**
- * Computes the value of the Jacobi symbol (A|B). The following properties
- * hold for the Jacobi symbol which makes it a very efficient way to
- * evaluate the Legendre symbol
- * <p>
- * (A|B) = 0 IF gcd(A,B) &gt; 1<br>
- * (-1|B) = 1 IF n = 1 (mod 1)<br>
- * (-1|B) = -1 IF n = 3 (mod 4)<br>
- * (A|B) (C|B) = (AC|B)<br>
- * (A|B) (A|C) = (A|CB)<br>
- * (A|B) = (C|B) IF A = C (mod B)<br>
- * (2|B) = 1 IF N = 1 OR 7 (mod 8)<br>
- * (2|B) = 1 IF N = 3 OR 5 (mod 8)
- *
- * @param A integer value
- * @param B integer value
- * @return value of the jacobi symbol (A|B)
- */
- public static int jacobi(BigInteger A, BigInteger B)
- {
- BigInteger a, b, v;
- long k = 1;
-
- k = 1;
-
- // test trivial cases
- if (B.equals(ZERO))
- {
- a = A.abs();
- return a.equals(ONE) ? 1 : 0;
- }
-
- if (!A.testBit(0) && !B.testBit(0))
- {
- return 0;
- }
-
- a = A;
- b = B;
-
- if (b.signum() == -1)
- { // b < 0
- b = b.negate(); // b = -b
- if (a.signum() == -1)
- {
- k = -1;
- }
- }
-
- v = ZERO;
- while (!b.testBit(0))
- {
- v = v.add(ONE); // v = v + 1
- b = b.divide(TWO); // b = b/2
- }
-
- if (v.testBit(0))
- {
- k = k * jacobiTable[a.intValue() & 7];
- }
-
- if (a.signum() < 0)
- { // a < 0
- if (b.testBit(1))
- {
- k = -k; // k = -k
- }
- a = a.negate(); // a = -a
- }
-
- // main loop
- while (a.signum() != 0)
- {
- v = ZERO;
- while (!a.testBit(0))
- { // a is even
- v = v.add(ONE);
- a = a.divide(TWO);
- }
- if (v.testBit(0))
- {
- k = k * jacobiTable[b.intValue() & 7];
- }
-
- if (a.compareTo(b) < 0)
- { // a < b
- // swap and correct intermediate result
- BigInteger x = a;
- a = b;
- b = x;
- if (a.testBit(1) && b.testBit(1))
- {
- k = -k;
- }
- }
- a = a.subtract(b);
- }
-
- return b.equals(ONE) ? (int)k : 0;
- }
-
- /**
- * Computes the square root of a BigInteger modulo a prime employing the
- * Shanks-Tonelli algorithm.
- *
- * @param a value out of which we extract the square root
- * @param p prime modulus that determines the underlying field
- * @return a number <tt>b</tt> such that b<sup>2</sup> = a (mod p) if
- * <tt>a</tt> is a quadratic residue modulo <tt>p</tt>.
- * @throws NoQuadraticResidueException if <tt>a</tt> is a quadratic non-residue modulo <tt>p</tt>
- */
- public static BigInteger ressol(BigInteger a, BigInteger p)
- throws IllegalArgumentException
- {
-
- BigInteger v = null;
-
- if (a.compareTo(ZERO) < 0)
- {
- a = a.add(p);
- }
-
- if (a.equals(ZERO))
- {
- return ZERO;
- }
-
- if (p.equals(TWO))
- {
- return a;
- }
-
- // p = 3 mod 4
- if (p.testBit(0) && p.testBit(1))
- {
- if (jacobi(a, p) == 1)
- { // a quadr. residue mod p
- v = p.add(ONE); // v = p+1
- v = v.shiftRight(2); // v = v/4
- return a.modPow(v, p); // return a^v mod p
- // return --> a^((p+1)/4) mod p
- }
- throw new IllegalArgumentException("No quadratic residue: " + a + ", " + p);
- }
-
- long t = 0;
-
- // initialization
- // compute k and s, where p = 2^s (2k+1) +1
-
- BigInteger k = p.subtract(ONE); // k = p-1
- long s = 0;
- while (!k.testBit(0))
- { // while k is even
- s++; // s = s+1
- k = k.shiftRight(1); // k = k/2
- }
-
- k = k.subtract(ONE); // k = k - 1
- k = k.shiftRight(1); // k = k/2
-
- // initial values
- BigInteger r = a.modPow(k, p); // r = a^k mod p
-
- BigInteger n = r.multiply(r).remainder(p); // n = r^2 % p
- n = n.multiply(a).remainder(p); // n = n * a % p
- r = r.multiply(a).remainder(p); // r = r * a %p
-
- if (n.equals(ONE))
- {
- return r;
- }
-
- // non-quadratic residue
- BigInteger z = TWO; // z = 2
- while (jacobi(z, p) == 1)
- {
- // while z quadratic residue
- z = z.add(ONE); // z = z + 1
- }
-
- v = k;
- v = v.multiply(TWO); // v = 2k
- v = v.add(ONE); // v = 2k + 1
- BigInteger c = z.modPow(v, p); // c = z^v mod p
-
- // iteration
- while (n.compareTo(ONE) == 1)
- { // n > 1
- k = n; // k = n
- t = s; // t = s
- s = 0;
-
- while (!k.equals(ONE))
- { // k != 1
- k = k.multiply(k).mod(p); // k = k^2 % p
- s++; // s = s + 1
- }
-
- t -= s; // t = t - s
- if (t == 0)
- {
- throw new IllegalArgumentException("No quadratic residue: " + a + ", " + p);
- }
-
- v = ONE;
- for (long i = 0; i < t - 1; i++)
- {
- v = v.shiftLeft(1); // v = 1 * 2^(t - 1)
- }
- c = c.modPow(v, p); // c = c^v mod p
- r = r.multiply(c).remainder(p); // r = r * c % p
- c = c.multiply(c).remainder(p); // c = c^2 % p
- n = n.multiply(c).mod(p); // n = n * c % p
- }
- return r;
- }
-
- /**
- * Computes the greatest common divisor of the two specified integers
- *
- * @param u - first integer
- * @param v - second integer
- * @return gcd(a, b)
- */
- public static int gcd(int u, int v)
- {
- return BigInteger.valueOf(u).gcd(BigInteger.valueOf(v)).intValue();
- }
-
- /**
- * Extended euclidian algorithm (computes gcd and representation).
- *
- * @param a the first integer
- * @param b the second integer
- * @return <tt>(g,u,v)</tt>, where <tt>g = gcd(abs(a),abs(b)) = ua + vb</tt>
- */
- public static int[] extGCD(int a, int b)
- {
- BigInteger ba = BigInteger.valueOf(a);
- BigInteger bb = BigInteger.valueOf(b);
- BigInteger[] bresult = extgcd(ba, bb);
- int[] result = new int[3];
- result[0] = bresult[0].intValue();
- result[1] = bresult[1].intValue();
- result[2] = bresult[2].intValue();
- return result;
- }
-
- public static BigInteger divideAndRound(BigInteger a, BigInteger b)
- {
- if (a.signum() < 0)
- {
- return divideAndRound(a.negate(), b).negate();
- }
- if (b.signum() < 0)
- {
- return divideAndRound(a, b.negate()).negate();
- }
- return a.shiftLeft(1).add(b).divide(b.shiftLeft(1));
- }
-
- public static BigInteger[] divideAndRound(BigInteger[] a, BigInteger b)
- {
- BigInteger[] out = new BigInteger[a.length];
- for (int i = 0; i < a.length; i++)
- {
- out[i] = divideAndRound(a[i], b);
- }
- return out;
- }
-
- /**
- * Compute the smallest integer that is greater than or equal to the
- * logarithm to the base 2 of the given BigInteger.
- *
- * @param a the integer
- * @return ceil[log(a)]
- */
- public static int ceilLog(BigInteger a)
- {
- int result = 0;
- BigInteger p = ONE;
- while (p.compareTo(a) < 0)
- {
- result++;
- p = p.shiftLeft(1);
- }
- return result;
- }
-
- /**
- * Compute the smallest integer that is greater than or equal to the
- * logarithm to the base 2 of the given integer.
- *
- * @param a the integer
- * @return ceil[log(a)]
- */
- public static int ceilLog(int a)
- {
- int log = 0;
- int i = 1;
- while (i < a)
- {
- i <<= 1;
- log++;
- }
- return log;
- }
-
- /**
- * Compute <tt>ceil(log_256 n)</tt>, the number of bytes needed to encode
- * the integer <tt>n</tt>.
- *
- * @param n the integer
- * @return the number of bytes needed to encode <tt>n</tt>
- */
- public static int ceilLog256(int n)
- {
- if (n == 0)
- {
- return 1;
- }
- int m;
- if (n < 0)
- {
- m = -n;
- }
- else
- {
- m = n;
- }
-
- int d = 0;
- while (m > 0)
- {
- d++;
- m >>>= 8;
- }
- return d;
- }
-
- /**
- * Compute <tt>ceil(log_256 n)</tt>, the number of bytes needed to encode
- * the long integer <tt>n</tt>.
- *
- * @param n the long integer
- * @return the number of bytes needed to encode <tt>n</tt>
- */
- public static int ceilLog256(long n)
- {
- if (n == 0)
- {
- return 1;
- }
- long m;
- if (n < 0)
- {
- m = -n;
- }
- else
- {
- m = n;
- }
-
- int d = 0;
- while (m > 0)
- {
- d++;
- m >>>= 8;
- }
- return d;
- }
-
- /**
- * Compute the integer part of the logarithm to the base 2 of the given
- * integer.
- *
- * @param a the integer
- * @return floor[log(a)]
- */
- public static int floorLog(BigInteger a)
- {
- int result = -1;
- BigInteger p = ONE;
- while (p.compareTo(a) <= 0)
- {
- result++;
- p = p.shiftLeft(1);
- }
- return result;
- }
-
- /**
- * Compute the integer part of the logarithm to the base 2 of the given
- * integer.
- *
- * @param a the integer
- * @return floor[log(a)]
- */
- public static int floorLog(int a)
- {
- int h = 0;
- if (a <= 0)
- {
- return -1;
- }
- int p = a >>> 1;
- while (p > 0)
- {
- h++;
- p >>>= 1;
- }
-
- return h;
- }
-
- /**
- * Compute the largest <tt>h</tt> with <tt>2^h | a</tt> if <tt>a!=0</tt>.
- *
- * @param a an integer
- * @return the largest <tt>h</tt> with <tt>2^h | a</tt> if <tt>a!=0</tt>,
- * <tt>0</tt> otherwise
- */
- public static int maxPower(int a)
- {
- int h = 0;
- if (a != 0)
- {
- int p = 1;
- while ((a & p) == 0)
- {
- h++;
- p <<= 1;
- }
- }
-
- return h;
- }
-
- /**
- * @param a an integer
- * @return the number of ones in the binary representation of an integer
- * <tt>a</tt>
- */
- public static int bitCount(int a)
- {
- int h = 0;
- while (a != 0)
- {
- h += a & 1;
- a >>>= 1;
- }
-
- return h;
- }
-
- /**
- * determines the order of g modulo p, p prime and 1 &lt; g &lt; p. This algorithm
- * is only efficient for small p (see X9.62-1998, p. 68).
- *
- * @param g an integer with 1 &lt; g &lt; p
- * @param p a prime
- * @return the order k of g (that is k is the smallest integer with
- * g<sup>k</sup> = 1 mod p
- */
- public static int order(int g, int p)
- {
- int b, j;
-
- b = g % p; // Reduce g mod p first.
- j = 1;
-
- // Check whether g == 0 mod p (avoiding endless loop).
- if (b == 0)
- {
- throw new IllegalArgumentException(g + " is not an element of Z/("
- + p + "Z)^*; it is not meaningful to compute its order.");
- }
-
- // Compute the order of g mod p:
- while (b != 1)
- {
- b *= g;
- b %= p;
- if (b < 0)
- {
- b += p;
- }
- j++;
- }
-
- return j;
- }
-
- /**
- * Reduces an integer into a given interval
- *
- * @param n - the integer
- * @param begin - left bound of the interval
- * @param end - right bound of the interval
- * @return <tt>n</tt> reduced into <tt>[begin,end]</tt>
- */
- public static BigInteger reduceInto(BigInteger n, BigInteger begin,
- BigInteger end)
- {
- return n.subtract(begin).mod(end.subtract(begin)).add(begin);
- }
-
- /**
- * Compute <tt>a<sup>e</sup></tt>.
- *
- * @param a the base
- * @param e the exponent
- * @return <tt>a<sup>e</sup></tt>
- */
- public static int pow(int a, int e)
- {
- int result = 1;
- while (e > 0)
- {
- if ((e & 1) == 1)
- {
- result *= a;
- }
- a *= a;
- e >>>= 1;
- }
- return result;
- }
-
- /**
- * Compute <tt>a<sup>e</sup></tt>.
- *
- * @param a the base
- * @param e the exponent
- * @return <tt>a<sup>e</sup></tt>
- */
- public static long pow(long a, int e)
- {
- long result = 1;
- while (e > 0)
- {
- if ((e & 1) == 1)
- {
- result *= a;
- }
- a *= a;
- e >>>= 1;
- }
- return result;
- }
-
- /**
- * Compute <tt>a<sup>e</sup> mod n</tt>.
- *
- * @param a the base
- * @param e the exponent
- * @param n the modulus
- * @return <tt>a<sup>e</sup> mod n</tt>
- */
- public static int modPow(int a, int e, int n)
- {
- if (n <= 0 || (n * n) > Integer.MAX_VALUE || e < 0)
- {
- return 0;
- }
- int result = 1;
- a = (a % n + n) % n;
- while (e > 0)
- {
- if ((e & 1) == 1)
- {
- result = (result * a) % n;
- }
- a = (a * a) % n;
- e >>>= 1;
- }
- return result;
- }
-
- /**
- * Extended euclidian algorithm (computes gcd and representation).
- *
- * @param a - the first integer
- * @param b - the second integer
- * @return <tt>(d,u,v)</tt>, where <tt>d = gcd(a,b) = ua + vb</tt>
- */
- public static BigInteger[] extgcd(BigInteger a, BigInteger b)
- {
- BigInteger u = ONE;
- BigInteger v = ZERO;
- BigInteger d = a;
- if (b.signum() != 0)
- {
- BigInteger v1 = ZERO;
- BigInteger v3 = b;
- while (v3.signum() != 0)
- {
- BigInteger[] tmp = d.divideAndRemainder(v3);
- BigInteger q = tmp[0];
- BigInteger t3 = tmp[1];
- BigInteger t1 = u.subtract(q.multiply(v1));
- u = v1;
- d = v3;
- v1 = t1;
- v3 = t3;
- }
- v = d.subtract(a.multiply(u)).divide(b);
- }
- return new BigInteger[]{d, u, v};
- }
-
- /**
- * Computation of the least common multiple of a set of BigIntegers.
- *
- * @param numbers - the set of numbers
- * @return the lcm(numbers)
- */
- public static BigInteger leastCommonMultiple(BigInteger[] numbers)
- {
- int n = numbers.length;
- BigInteger result = numbers[0];
- for (int i = 1; i < n; i++)
- {
- BigInteger gcd = result.gcd(numbers[i]);
- result = result.multiply(numbers[i]).divide(gcd);
- }
- return result;
- }
-
- /**
- * Returns a long integer whose value is <tt>(a mod m</tt>). This method
- * differs from <tt>%</tt> in that it always returns a <i>non-negative</i>
- * integer.
- *
- * @param a value on which the modulo operation has to be performed.
- * @param m the modulus.
- * @return <tt>a mod m</tt>
- */
- public static long mod(long a, long m)
- {
- long result = a % m;
- if (result < 0)
- {
- result += m;
- }
- return result;
- }
-
- /**
- * Computes the modular inverse of an integer a
- *
- * @param a - the integer to invert
- * @param mod - the modulus
- * @return <tt>a<sup>-1</sup> mod n</tt>
- */
- public static int modInverse(int a, int mod)
- {
- return BigInteger.valueOf(a).modInverse(BigInteger.valueOf(mod))
- .intValue();
- }
-
- /**
- * Computes the modular inverse of an integer a
- *
- * @param a - the integer to invert
- * @param mod - the modulus
- * @return <tt>a<sup>-1</sup> mod n</tt>
- */
- public static long modInverse(long a, long mod)
- {
- return BigInteger.valueOf(a).modInverse(BigInteger.valueOf(mod))
- .longValue();
- }
-
- /**
- * Tests whether an integer <tt>a</tt> is power of another integer
- * <tt>p</tt>.
- *
- * @param a - the first integer
- * @param p - the second integer
- * @return n if a = p^n or -1 otherwise
- */
- public static int isPower(int a, int p)
- {
- if (a <= 0)
- {
- return -1;
- }
- int n = 0;
- int d = a;
- while (d > 1)
- {
- if (d % p != 0)
- {
- return -1;
- }
- d /= p;
- n++;
- }
- return n;
- }
-
- /**
- * Find and return the least non-trivial divisor of an integer <tt>a</tt>.
- *
- * @param a - the integer
- * @return divisor p &gt;1 or 1 if a = -1,0,1
- */
- public static int leastDiv(int a)
- {
- if (a < 0)
- {
- a = -a;
- }
- if (a == 0)
- {
- return 1;
- }
- if ((a & 1) == 0)
- {
- return 2;
- }
- int p = 3;
- while (p <= (a / p))
- {
- if ((a % p) == 0)
- {
- return p;
- }
- p += 2;
- }
-
- return a;
- }
-
- /**
- * Miller-Rabin-Test, determines wether the given integer is probably prime
- * or composite. This method returns <tt>true</tt> if the given integer is
- * prime with probability <tt>1 - 2<sup>-20</sup></tt>.
- *
- * @param n the integer to test for primality
- * @return <tt>true</tt> if the given integer is prime with probability
- * 2<sup>-100</sup>, <tt>false</tt> otherwise
- */
- public static boolean isPrime(int n)
- {
- if (n < 2)
- {
- return false;
- }
- if (n == 2)
- {
- return true;
- }
- if ((n & 1) == 0)
- {
- return false;
- }
- if (n < 42)
- {
- for (int i = 0; i < SMALL_PRIMES.length; i++)
- {
- if (n == SMALL_PRIMES[i])
- {
- return true;
- }
- }
- }
-
- if ((n % 3 == 0) || (n % 5 == 0) || (n % 7 == 0) || (n % 11 == 0)
- || (n % 13 == 0) || (n % 17 == 0) || (n % 19 == 0)
- || (n % 23 == 0) || (n % 29 == 0) || (n % 31 == 0)
- || (n % 37 == 0) || (n % 41 == 0))
- {
- return false;
- }
-
- return BigInteger.valueOf(n).isProbablePrime(20);
- }
-
- /**
- * Short trial-division test to find out whether a number is not prime. This
- * test is usually used before a Miller-Rabin primality test.
- *
- * @param candidate the number to test
- * @return <tt>true</tt> if the number has no factor of the tested primes,
- * <tt>false</tt> if the number is definitely composite
- */
- public static boolean passesSmallPrimeTest(BigInteger candidate)
- {
- final int[] smallPrime = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37,
- 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103,
- 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167,
- 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233,
- 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307,
- 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379,
- 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449,
- 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523,
- 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607,
- 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677,
- 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761,
- 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853,
- 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937,
- 941, 947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013, 1019,
- 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, 1087,
- 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, 1153,
- 1163, 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223, 1229,
- 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291, 1297,
- 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, 1381,
- 1399, 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, 1453,
- 1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499};
-
- for (int i = 0; i < smallPrime.length; i++)
- {
- if (candidate.mod(BigInteger.valueOf(smallPrime[i])).equals(
- ZERO))
- {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Returns the largest prime smaller than the given integer
- *
- * @param n - upper bound
- * @return the largest prime smaller than <tt>n</tt>, or <tt>1</tt> if
- * <tt>n &lt;= 2</tt>
- */
- public static int nextSmallerPrime(int n)
- {
- if (n <= 2)
- {
- return 1;
- }
-
- if (n == 3)
- {
- return 2;
- }
-
- if ((n & 1) == 0)
- {
- n--;
- }
- else
- {
- n -= 2;
- }
-
- while (n > 3 & !isPrime(n))
- {
- n -= 2;
- }
- return n;
- }
-
- /**
- * Compute the next probable prime greater than <tt>n</tt> with the
- * specified certainty.
- *
- * @param n a integer number
- * @param certainty the certainty that the generated number is prime
- * @return the next prime greater than <tt>n</tt>
- */
- public static BigInteger nextProbablePrime(BigInteger n, int certainty)
- {
-
- if (n.signum() < 0 || n.signum() == 0 || n.equals(ONE))
- {
- return TWO;
- }
-
- BigInteger result = n.add(ONE);
-
- // Ensure an odd number
- if (!result.testBit(0))
- {
- result = result.add(ONE);
- }
-
- while (true)
- {
- // Do cheap "pre-test" if applicable
- if (result.bitLength() > 6)
- {
- long r = result.remainder(
- BigInteger.valueOf(SMALL_PRIME_PRODUCT)).longValue();
- if ((r % 3 == 0) || (r % 5 == 0) || (r % 7 == 0)
- || (r % 11 == 0) || (r % 13 == 0) || (r % 17 == 0)
- || (r % 19 == 0) || (r % 23 == 0) || (r % 29 == 0)
- || (r % 31 == 0) || (r % 37 == 0) || (r % 41 == 0))
- {
- result = result.add(TWO);
- continue; // Candidate is composite; try another
- }
- }
-
- // All candidates of bitLength 2 and 3 are prime by this point
- if (result.bitLength() < 4)
- {
- return result;
- }
-
- // The expensive test
- if (result.isProbablePrime(certainty))
- {
- return result;
- }
-
- result = result.add(TWO);
- }
- }
-
- /**
- * Compute the next probable prime greater than <tt>n</tt> with the default
- * certainty (20).
- *
- * @param n a integer number
- * @return the next prime greater than <tt>n</tt>
- */
- public static BigInteger nextProbablePrime(BigInteger n)
- {
- return nextProbablePrime(n, 20);
- }
-
- /**
- * Computes the next prime greater than n.
- *
- * @param n a integer number
- * @return the next prime greater than n
- */
- public static BigInteger nextPrime(long n)
- {
- long i;
- boolean found = false;
- long result = 0;
-
- if (n <= 1)
- {
- return BigInteger.valueOf(2);
- }
- if (n == 2)
- {
- return BigInteger.valueOf(3);
- }
-
- for (i = n + 1 + (n & 1); (i <= n << 1) && !found; i += 2)
- {
- for (long j = 3; (j <= i >> 1) && !found; j += 2)
- {
- if (i % j == 0)
- {
- found = true;
- }
- }
- if (found)
- {
- found = false;
- }
- else
- {
- result = i;
- found = true;
- }
- }
- return BigInteger.valueOf(result);
- }
-
- /**
- * Computes the binomial coefficient (n|t) ("n over t"). Formula:
- * <ul>
- * <li>if n !=0 and t != 0 then (n|t) = Mult(i=1, t): (n-(i-1))/i</li>
- * <li>if t = 0 then (n|t) = 1</li>
- * <li>if n = 0 and t &gt; 0 then (n|t) = 0</li>
- * </ul>
- *
- * @param n - the "upper" integer
- * @param t - the "lower" integer
- * @return the binomialcoefficient "n over t" as BigInteger
- */
- public static BigInteger binomial(int n, int t)
- {
-
- BigInteger result = ONE;
-
- if (n == 0)
- {
- if (t == 0)
- {
- return result;
- }
- return ZERO;
- }
-
- // the property (n|t) = (n|n-t) be used to reduce numbers of operations
- if (t > (n >>> 1))
- {
- t = n - t;
- }
-
- for (int i = 1; i <= t; i++)
- {
- result = (result.multiply(BigInteger.valueOf(n - (i - 1))))
- .divide(BigInteger.valueOf(i));
- }
-
- return result;
- }
-
- public static BigInteger randomize(BigInteger upperBound)
- {
- if (sr == null)
- {
- sr = new SecureRandom();
- }
- return randomize(upperBound, sr);
- }
-
- public static BigInteger randomize(BigInteger upperBound,
- SecureRandom prng)
- {
- int blen = upperBound.bitLength();
- BigInteger randomNum = BigInteger.valueOf(0);
-
- if (prng == null)
- {
- prng = sr != null ? sr : new SecureRandom();
- }
-
- for (int i = 0; i < 20; i++)
- {
- randomNum = new BigInteger(blen, prng);
- if (randomNum.compareTo(upperBound) < 0)
- {
- return randomNum;
- }
- }
- return randomNum.mod(upperBound);
- }
-
- /**
- * Extract the truncated square root of a BigInteger.
- *
- * @param a - value out of which we extract the square root
- * @return the truncated square root of <tt>a</tt>
- */
- public static BigInteger squareRoot(BigInteger a)
- {
- int bl;
- BigInteger result, remainder, b;
-
- if (a.compareTo(ZERO) < 0)
- {
- throw new ArithmeticException(
- "cannot extract root of negative number" + a + ".");
- }
-
- bl = a.bitLength();
- result = ZERO;
- remainder = ZERO;
-
- // if the bit length is odd then extra step
- if ((bl & 1) != 0)
- {
- result = result.add(ONE);
- bl--;
- }
-
- while (bl > 0)
- {
- remainder = remainder.multiply(FOUR);
- remainder = remainder.add(BigInteger.valueOf((a.testBit(--bl) ? 2
- : 0)
- + (a.testBit(--bl) ? 1 : 0)));
- b = result.multiply(FOUR).add(ONE);
- result = result.multiply(TWO);
- if (remainder.compareTo(b) != -1)
- {
- result = result.add(ONE);
- remainder = remainder.subtract(b);
- }
- }
-
- return result;
- }
-
- /**
- * Takes an approximation of the root from an integer base, using newton's
- * algorithm
- *
- * @param base the base to take the root from
- * @param root the root, for example 2 for a square root
- */
- public static float intRoot(int base, int root)
- {
- float gNew = base / root;
- float gOld = 0;
- int counter = 0;
- while (Math.abs(gOld - gNew) > 0.0001)
- {
- float gPow = floatPow(gNew, root);
- while (Float.isInfinite(gPow))
- {
- gNew = (gNew + gOld) / 2;
- gPow = floatPow(gNew, root);
- }
- counter += 1;
- gOld = gNew;
- gNew = gOld - (gPow - base) / (root * floatPow(gOld, root - 1));
- }
- return gNew;
- }
-
- /**
- * Calculation of a logarithmus of a float param
- *
- * @param param
- * @return
- */
- public static float floatLog(float param)
- {
- double arg = (param - 1) / (param + 1);
- double arg2 = arg;
- int counter = 1;
- float result = (float)arg;
-
- while (arg2 > 0.001)
- {
- counter += 2;
- arg2 *= arg * arg;
- result += (1. / counter) * arg2;
- }
- return 2 * result;
- }
-
- /**
- * int power of a base float, only use for small ints
- *
- * @param f
- * @param i
- * @return
- */
- public static float floatPow(float f, int i)
- {
- float g = 1;
- for (; i > 0; i--)
- {
- g *= f;
- }
- return g;
- }
-
- /**
- * calculate the logarithm to the base 2.
- *
- * @param x any double value
- * @return log_2(x)
- * @deprecated use MathFunctions.log(double) instead
- */
- public static double log(double x)
- {
- if (x > 0 && x < 1)
- {
- double d = 1 / x;
- double result = -log(d);
- return result;
- }
-
- int tmp = 0;
- double tmp2 = 1;
- double d = x;
-
- while (d > 2)
- {
- d = d / 2;
- tmp += 1;
- tmp2 *= 2;
- }
- double rem = x / tmp2;
- rem = logBKM(rem);
- return tmp + rem;
- }
-
- /**
- * calculate the logarithm to the base 2.
- *
- * @param x any long value &gt;=1
- * @return log_2(x)
- * @deprecated use MathFunctions.log(long) instead
- */
- public static double log(long x)
- {
- int tmp = floorLog(BigInteger.valueOf(x));
- long tmp2 = 1 << tmp;
- double rem = (double)x / (double)tmp2;
- rem = logBKM(rem);
- return tmp + rem;
- }
-
- /**
- * BKM Algorithm to calculate logarithms to the base 2.
- *
- * @param arg a double value with 1<= arg<= 4.768462058
- * @return log_2(arg)
- * @deprecated use MathFunctions.logBKM(double) instead
- */
- private static double logBKM(double arg)
- {
- double ae[] = // A_e[k] = log_2 (1 + 0.5^k)
- {
- 1.0000000000000000000000000000000000000000000000000000000000000000000000000000,
- 0.5849625007211561814537389439478165087598144076924810604557526545410982276485,
- 0.3219280948873623478703194294893901758648313930245806120547563958159347765589,
- 0.1699250014423123629074778878956330175196288153849621209115053090821964552970,
- 0.0874628412503394082540660108104043540112672823448206881266090643866965081686,
- 0.0443941193584534376531019906736094674630459333742491317685543002674288465967,
- 0.0223678130284545082671320837460849094932677948156179815932199216587899627785,
- 0.0112272554232541203378805844158839407281095943600297940811823651462712311786,
- 0.0056245491938781069198591026740666017211096815383520359072957784732489771013,
- 0.0028150156070540381547362547502839489729507927389771959487826944878598909400,
- 0.0014081943928083889066101665016890524233311715793462235597709051792834906001,
- 0.0007042690112466432585379340422201964456668872087249334581924550139514213168,
- 0.0003521774803010272377989609925281744988670304302127133979341729842842377649,
- 0.0001760994864425060348637509459678580940163670081839283659942864068257522373,
- 0.0000880524301221769086378699983597183301490534085738474534831071719854721939,
- 0.0000440268868273167176441087067175806394819146645511899503059774914593663365,
- 0.0000220136113603404964890728830697555571275493801909791504158295359319433723,
- 0.0000110068476674814423006223021573490183469930819844945565597452748333526464,
- 0.0000055034343306486037230640321058826431606183125807276574241540303833251704,
- 0.0000027517197895612831123023958331509538486493412831626219340570294203116559,
- 0.0000013758605508411382010566802834037147561973553922354232704569052932922954,
- 0.0000006879304394358496786728937442939160483304056131990916985043387874690617,
- 0.0000003439652607217645360118314743718005315334062644619363447395987584138324,
- 0.0000001719826406118446361936972479533123619972434705828085978955697643547921,
- 0.0000000859913228686632156462565208266682841603921494181830811515318381744650,
- 0.0000000429956620750168703982940244684787907148132725669106053076409624949917,
- 0.0000000214978311976797556164155504126645192380395989504741781512309853438587,
- 0.0000000107489156388827085092095702361647949603617203979413516082280717515504,
- 0.0000000053744578294520620044408178949217773318785601260677517784797554422804,
- 0.0000000026872289172287079490026152352638891824761667284401180026908031182361,
- 0.0000000013436144592400232123622589569799954658536700992739887706412976115422,
- 0.0000000006718072297764289157920422846078078155859484240808550018085324187007,
- 0.0000000003359036149273187853169587152657145221968468364663464125722491530858,
- 0.0000000001679518074734354745159899223037458278711244127245990591908996412262,
- 0.0000000000839759037391617577226571237484864917411614198675604731728132152582,
- 0.0000000000419879518701918839775296677020135040214077417929807824842667285938,
- 0.0000000000209939759352486932678195559552767641474249812845414125580747434389,
- 0.0000000000104969879676625344536740142096218372850561859495065136990936290929,
- 0.0000000000052484939838408141817781356260462777942148580518406975851213868092,
- 0.0000000000026242469919227938296243586262369156865545638305682553644113887909,
- 0.0000000000013121234959619935994960031017850191710121890821178731821983105443,
- 0.0000000000006560617479811459709189576337295395590603644549624717910616347038,
- 0.0000000000003280308739906102782522178545328259781415615142931952662153623493,
- 0.0000000000001640154369953144623242936888032768768777422997704541618141646683,
- 0.0000000000000820077184976595619616930350508356401599552034612281802599177300,
- 0.0000000000000410038592488303636807330652208397742314215159774270270147020117,
- 0.0000000000000205019296244153275153381695384157073687186580546938331088730952,
- 0.0000000000000102509648122077001764119940017243502120046885379813510430378661,
- 0.0000000000000051254824061038591928917243090559919209628584150482483994782302,
- 0.0000000000000025627412030519318726172939815845367496027046030028595094737777,
- 0.0000000000000012813706015259665053515049475574143952543145124550608158430592,
- 0.0000000000000006406853007629833949364669629701200556369782295210193569318434,
- 0.0000000000000003203426503814917330334121037829290364330169106716787999052925,
- 0.0000000000000001601713251907458754080007074659337446341494733882570243497196,
- 0.0000000000000000800856625953729399268240176265844257044861248416330071223615,
- 0.0000000000000000400428312976864705191179247866966320469710511619971334577509,
- 0.0000000000000000200214156488432353984854413866994246781519154793320684126179,
- 0.0000000000000000100107078244216177339743404416874899847406043033792202127070,
- 0.0000000000000000050053539122108088756700751579281894640362199287591340285355,
- 0.0000000000000000025026769561054044400057638132352058574658089256646014899499,
- 0.0000000000000000012513384780527022205455634651853807110362316427807660551208,
- 0.0000000000000000006256692390263511104084521222346348012116229213309001913762,
- 0.0000000000000000003128346195131755552381436585278035120438976487697544916191,
- 0.0000000000000000001564173097565877776275512286165232838833090480508502328437,
- 0.0000000000000000000782086548782938888158954641464170239072244145219054734086,
- 0.0000000000000000000391043274391469444084776945327473574450334092075712154016,
- 0.0000000000000000000195521637195734722043713378812583900953755962557525252782,
- 0.0000000000000000000097760818597867361022187915943503728909029699365320287407,
- 0.0000000000000000000048880409298933680511176764606054809062553340323879609794,
- 0.0000000000000000000024440204649466840255609083961603140683286362962192177597,
- 0.0000000000000000000012220102324733420127809717395445504379645613448652614939,
- 0.0000000000000000000006110051162366710063906152551383735699323415812152114058,
- 0.0000000000000000000003055025581183355031953399739107113727036860315024588989,
- 0.0000000000000000000001527512790591677515976780735407368332862218276873443537,
- 0.0000000000000000000000763756395295838757988410584167137033767056170417508383,
- 0.0000000000000000000000381878197647919378994210346199431733717514843471513618,
- 0.0000000000000000000000190939098823959689497106436628681671067254111334889005,
- 0.0000000000000000000000095469549411979844748553534196582286585751228071408728,
- 0.0000000000000000000000047734774705989922374276846068851506055906657137209047,
- 0.0000000000000000000000023867387352994961187138442777065843718711089344045782,
- 0.0000000000000000000000011933693676497480593569226324192944532044984865894525,
- 0.0000000000000000000000005966846838248740296784614396011477934194852481410926,
- 0.0000000000000000000000002983423419124370148392307506484490384140516252814304,
- 0.0000000000000000000000001491711709562185074196153830361933046331030629430117,
- 0.0000000000000000000000000745855854781092537098076934460888486730708440475045,
- 0.0000000000000000000000000372927927390546268549038472050424734256652501673274,
- 0.0000000000000000000000000186463963695273134274519237230207489851150821191330,
- 0.0000000000000000000000000093231981847636567137259618916352525606281553180093,
- 0.0000000000000000000000000046615990923818283568629809533488457973317312233323,
- 0.0000000000000000000000000023307995461909141784314904785572277779202790023236,
- 0.0000000000000000000000000011653997730954570892157452397493151087737428485431,
- 0.0000000000000000000000000005826998865477285446078726199923328593402722606924,
- 0.0000000000000000000000000002913499432738642723039363100255852559084863397344,
- 0.0000000000000000000000000001456749716369321361519681550201473345138307215067,
- 0.0000000000000000000000000000728374858184660680759840775119123438968122488047,
- 0.0000000000000000000000000000364187429092330340379920387564158411083803465567,
- 0.0000000000000000000000000000182093714546165170189960193783228378441837282509,
- 0.0000000000000000000000000000091046857273082585094980096891901482445902524441,
- 0.0000000000000000000000000000045523428636541292547490048446022564529197237262,
- 0.0000000000000000000000000000022761714318270646273745024223029238091160103901};
- int n = 53;
- double x = 1;
- double y = 0;
- double z;
- double s = 1;
- int k;
-
- for (k = 0; k < n; k++)
- {
- z = x + x * s;
- if (z <= arg)
- {
- x = z;
- y += ae[k];
- }
- s *= 0.5;
- }
- return y;
- }
-
- public static boolean isIncreasing(int[] a)
- {
- for (int i = 1; i < a.length; i++)
- {
- if (a[i - 1] >= a[i])
- {
- System.out.println("a[" + (i - 1) + "] = " + a[i - 1] + " >= "
- + a[i] + " = a[" + i + "]");
- return false;
- }
- }
- return true;
- }
-
- public static byte[] integerToOctets(BigInteger val)
- {
- byte[] valBytes = val.abs().toByteArray();
-
- // check whether the array includes a sign bit
- if ((val.bitLength() & 7) != 0)
- {
- return valBytes;
- }
- // get rid of the sign bit (first byte)
- byte[] tmp = new byte[val.bitLength() >> 3];
- System.arraycopy(valBytes, 1, tmp, 0, tmp.length);
- return tmp;
- }
-
- public static BigInteger octetsToInteger(byte[] data, int offset,
- int length)
- {
- byte[] val = new byte[length + 1];
-
- val[0] = 0;
- System.arraycopy(data, offset, val, 1, length);
- return new BigInteger(val);
- }
-
- public static BigInteger octetsToInteger(byte[] data)
- {
- return octetsToInteger(data, 0, data.length);
- }
-
- public static void main(String[] args)
- {
- System.out.println("test");
- // System.out.println(intRoot(37, 5));
- // System.out.println(floatPow((float)2.5, 4));
- System.out.println(floatLog(10));
- System.out.println("test2");
- }
-}
diff --git a/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/LittleEndianConversions.java b/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/LittleEndianConversions.java
deleted file mode 100644
index c97fdc5..0000000
--- a/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/LittleEndianConversions.java
+++ /dev/null
@@ -1,230 +0,0 @@
-package org.bouncycastle.pqc.math.linearalgebra;
-
-/**
- * This is a utility class containing data type conversions using little-endian
- * byte order.
- *
- * @see BigEndianConversions
- */
-public final 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 ((input[0] & 0xff)) | ((input[1] & 0xff) << 8)
- | ((input[2] & 0xff) << 16) | ((input[3] & 0xff)) << 24;
- }
-
- /**
- * 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)
- {
- int result = input[inOff++] & 0xff;
- result |= (input[inOff++] & 0xff) << 8;
- result |= (input[inOff++] & 0xff) << 16;
- result |= (input[inOff] & 0xff) << 24;
- return result;
- }
-
- /**
- * 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)
- {
- long result = input[inOff++] & 0xff;
- result |= (input[inOff++] & 0xff) << 8;
- result |= (input[inOff++] & 0xff) << 16;
- result |= ((long)input[inOff++] & 0xff) << 24;
- result |= ((long)input[inOff++] & 0xff) << 32;
- result |= ((long)input[inOff++] & 0xff) << 40;
- result |= ((long)input[inOff++] & 0xff) << 48;
- result |= ((long)input[inOff++] & 0xff) << 56;
- return result;
- }
-
- /**
- * 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)
- {
- byte[] result = new byte[4];
- result[0] = (byte)x;
- result[1] = (byte)(x >>> 8);
- result[2] = (byte)(x >>> 16);
- result[3] = (byte)(x >>> 24);
- return result;
- }
-
- /**
- * 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)
- {
- output[outOff++] = (byte)value;
- output[outOff++] = (byte)(value >>> 8);
- output[outOff++] = (byte)(value >>> 16);
- output[outOff++] = (byte)(value >>> 24);
- }
-
- /**
- * 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)
- {
- for (int i = outLen - 1; i >= 0; i--)
- {
- output[outOff + i] = (byte)(value >>> (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)
- {
- byte[] output = new byte[8];
- output[0] = (byte)input;
- output[1] = (byte)(input >>> 8);
- output[2] = (byte)(input >>> 16);
- output[3] = (byte)(input >>> 24);
- output[4] = (byte)(input >>> 32);
- output[5] = (byte)(input >>> 40);
- output[6] = (byte)(input >>> 48);
- output[7] = (byte)(input >>> 56);
- return output;
- }
-
- /**
- * 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)
- {
- output[outOff++] = (byte)input;
- output[outOff++] = (byte)(input >>> 8);
- output[outOff++] = (byte)(input >>> 16);
- output[outOff++] = (byte)(input >>> 24);
- output[outOff++] = (byte)(input >>> 32);
- output[outOff++] = (byte)(input >>> 40);
- output[outOff++] = (byte)(input >>> 48);
- output[outOff] = (byte)(input >>> 56);
- }
-
- /**
- * 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/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/Matrix.java b/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/Matrix.java
deleted file mode 100644
index 2c9a0eb..0000000
--- a/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/Matrix.java
+++ /dev/null
@@ -1,131 +0,0 @@
-package org.bouncycastle.pqc.math.linearalgebra;
-
-/**
- * This abstract class defines matrices. It holds the number of rows and the
- * number of columns of the matrix and defines some basic methods.
- */
-public abstract class Matrix
-{
-
- /**
- * number of rows
- */
- protected int numRows;
-
- /**
- * number of columns
- */
- protected int numColumns;
-
- // ----------------------------------------------------
- // some constants (matrix types)
- // ----------------------------------------------------
-
- /**
- * zero matrix
- */
- public static final char MATRIX_TYPE_ZERO = 'Z';
-
- /**
- * unit matrix
- */
- public static final char MATRIX_TYPE_UNIT = 'I';
-
- /**
- * random lower triangular matrix
- */
- public static final char MATRIX_TYPE_RANDOM_LT = 'L';
-
- /**
- * random upper triangular matrix
- */
- public static final char MATRIX_TYPE_RANDOM_UT = 'U';
-
- /**
- * random regular matrix
- */
- public static final char MATRIX_TYPE_RANDOM_REGULAR = 'R';
-
- // ----------------------------------------------------
- // getters
- // ----------------------------------------------------
-
- /**
- * @return the number of rows in the matrix
- */
- public int getNumRows()
- {
- return numRows;
- }
-
- /**
- * @return the number of columns in the binary matrix
- */
- public int getNumColumns()
- {
- return numColumns;
- }
-
- /**
- * @return the encoded matrix, i.e., this matrix in byte array form.
- */
- public abstract byte[] getEncoded();
-
- // ----------------------------------------------------
- // arithmetic
- // ----------------------------------------------------
-
- /**
- * Compute the inverse of this matrix.
- *
- * @return the inverse of this matrix (newly created).
- */
- public abstract Matrix computeInverse();
-
- /**
- * Check if this is the zero matrix (i.e., all entries are zero).
- *
- * @return <tt>true</tt> if this is the zero matrix
- */
- public abstract boolean isZero();
-
- /**
- * Compute the product of this matrix and another matrix.
- *
- * @param a the other matrix
- * @return <tt>this * a</tt> (newly created)
- */
- public abstract Matrix rightMultiply(Matrix a);
-
- /**
- * Compute the product of this matrix and a permutation.
- *
- * @param p the permutation
- * @return <tt>this * p</tt> (newly created)
- */
- public abstract Matrix rightMultiply(Permutation p);
-
- /**
- * Compute the product of a vector and this matrix. If the length of the
- * vector is greater than the number of rows of this matrix, the matrix is
- * multiplied by each m-bit part of the vector.
- *
- * @param vector a vector
- * @return <tt>vector * this</tt> (newly created)
- */
- public abstract Vector leftMultiply(Vector vector);
-
- /**
- * Compute the product of this matrix and a vector.
- *
- * @param vector a vector
- * @return <tt>this * vector</tt> (newly created)
- */
- public abstract Vector rightMultiply(Vector vector);
-
- /**
- * @return a human readable form of the matrix.
- */
- public abstract String toString();
-
-}
diff --git a/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/Permutation.java b/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/Permutation.java
deleted file mode 100644
index 28b58d3..0000000
--- a/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/Permutation.java
+++ /dev/null
@@ -1,247 +0,0 @@
-package org.bouncycastle.pqc.math.linearalgebra;
-
-import java.security.SecureRandom;
-
-/**
- * This class implements permutations of the set {0,1,...,n-1} for some given n
- * &gt; 0, i.e., ordered sequences containing each number <tt>m</tt> (<tt>0 &lt;=
- * m &lt; 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 IllegalArgumentException("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 IllegalArgumentException(
- "array is not a permutation vector");
- }
-
- this.perm = IntUtils.clone(perm);
- }
-
- /**
- * Create a permutation from an encoded permutation.
- *
- * @param enc the encoded permutation
- */
- public Permutation(byte[] enc)
- {
- if (enc.length <= 4)
- {
- throw new IllegalArgumentException("invalid encoding");
- }
-
- int n = LittleEndianConversions.OS2IP(enc, 0);
- int size = IntegerFunctions.ceilLog256(n - 1);
-
- if (enc.length != 4 + n * size)
- {
- throw new IllegalArgumentException("invalid encoding");
- }
-
- perm = new int[n];
- for (int i = 0; i < n; i++)
- {
- perm[i] = LittleEndianConversions.OS2IP(enc, 4 + i * size, size);
- }
-
- if (!isPermutation(perm))
- {
- throw new IllegalArgumentException("invalid encoding");
- }
-
- }
-
- /**
- * 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 IllegalArgumentException("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];
- }
- }
-
- /**
- * Encode this permutation as byte array.
- *
- * @return the encoded permutation
- */
- public byte[] getEncoded()
- {
- int n = perm.length;
- int size = IntegerFunctions.ceilLog256(n - 1);
- byte[] result = new byte[4 + n * size];
- LittleEndianConversions.I2OSP(n, result, 0);
- for (int i = 0; i < n; i++)
- {
- LittleEndianConversions.I2OSP(perm[i], result, 4 + i * size, size);
- }
- return result;
- }
-
- /**
- * @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 IllegalArgumentException("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 boolean equals(Object other)
- {
-
- if (!(other instanceof 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;
- }
-
- /**
- * @return the hash code of this permutation
- */
- public int hashCode()
- {
- return perm.hashCode();
- }
-
- /**
- * 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 boolean isPermutation(int[] perm)
- {
- int n = perm.length;
- boolean[] onlyOnce = new boolean[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/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/PolynomialGF2mSmallM.java b/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/PolynomialGF2mSmallM.java
deleted file mode 100644
index 866b6f7..0000000
--- a/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/PolynomialGF2mSmallM.java
+++ /dev/null
@@ -1,1124 +0,0 @@
-package org.bouncycastle.pqc.math.linearalgebra;
-
-import java.security.SecureRandom;
-
-/**
- * This class describes operations with polynomials from the ring R =
- * GF(2^m)[X], where 2 &lt;= m &lt;=31.
- *
- * @see GF2mField
- * @see PolynomialRingGF2m
- */
-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 static final 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 IllegalArgumentException(" 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 IllegalArgumentException(
- " 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 IllegalArgumentException(
- " 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 IllegalArgumentException(
- " 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)
- {
- this(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)(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];
- System.arraycopy(b, 0, result, 0, b.length);
- addend = a;
- }
- else
- {
- result = new int[a.length];
- System.arraycopy(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];
- System.arraycopy(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) &lt;
- * 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) &lt; 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;
- System.arraycopy(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];
- System.arraycopy(b, 0, a, 0, a.length);
- b = new int[c.length];
- System.arraycopy(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];
- System.arraycopy(mult1, 0, res1, 0, res1.length);
- System.arraycopy(mult1, d2, res2, 0, res2.length);
- res1 = multiply(res1, mult2);
- res2 = multiply(res2, mult2);
- res2 = multWithMonomial(res2, d2);
- result = add(res1, res2);
- }
- else
- {
- d2 = (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];
- System
- .arraycopy(mult1, 0, firstPartMult1, 0,
- firstPartMult1.length);
- System.arraycopy(mult1, d2, secondPartMult1, 0,
- secondPartMult1.length);
- System
- .arraycopy(mult2, 0, firstPartMult2, 0,
- firstPartMult2.length);
- System.arraycopy(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 boolean isIrreducible(int[] a)
- {
- if (a[0] == 0)
- {
- return false;
- }
- int d = computeDegree(a) >> 1;
- int[] u = {0, 1};
- final 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);
- System.arraycopy(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)&lt;=deg(g)/2.
- *
- * @param g the reduction polynomial
- * @return PolynomialGF2mSmallM[] {a,b} with b*this = a mod g and deg(a)&lt;=
- * 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 boolean equals(Object other)
- {
-
- if (other == null || !(other instanceof 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 boolean 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];
- System.arraycopy(a, 0, result, 0, d + 1);
- return result;
- }
-
-}
diff --git a/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/PolynomialRingGF2.java b/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/PolynomialRingGF2.java
deleted file mode 100644
index a0e2bac..0000000
--- a/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/PolynomialRingGF2.java
+++ /dev/null
@@ -1,278 +0,0 @@
-package 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 &lt;=32. For the polynomial representation the map f: R-&gt;Z,
- * poly(X)-&gt;poly(2) is used, where integers have the binary representation. For
- * example: X^7+X^3+X+1 -&gt; (00...0010001011)=139 Also for polynomials type
- * Integer is used.
- *
- * @see GF2mField
- */
-public final 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 >>>= 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 >>>= 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 >>>= 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 >>>= 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)
- {
- System.err.println("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)
- {
- System.err.println("Error: to be divided by 0");
- return 0;
- }
- long q1 = q & 0x00000000ffffffffL;
- while ((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 boolean isIrreducible(int p)
- {
- if (p == 0)
- {
- return false;
- }
- int d = degree(p) >>> 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)
- {
- System.err.println("The Degree is negative");
- return 0;
- }
- if (deg > 31)
- {
- System.err.println("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/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/PolynomialRingGF2m.java b/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/PolynomialRingGF2m.java
deleted file mode 100644
index 9e5d413..0000000
--- a/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/PolynomialRingGF2m.java
+++ /dev/null
@@ -1,175 +0,0 @@
-package org.bouncycastle.pqc.math.linearalgebra;
-
-/**
- * This class represents polynomial rings <tt>GF(2^m)[X]/p(X)</tt> for
- * <tt>m&lt;32</tt>. If <tt>p(X)</tt> is irreducible, the polynomial ring
- * is in fact an extension field of <tt>GF(2^m)</tt>.
- */
-public class PolynomialRingGF2m
-{
-
- /**
- * the finite field this polynomial ring is defined over
- */
- private GF2mField field;
-
- /**
- * the reduction polynomial
- */
- private PolynomialGF2mSmallM p;
-
- /**
- * the squaring matrix for this polynomial ring (given as the array of its
- * row vectors)
- */
- protected PolynomialGF2mSmallM[] sqMatrix;
-
- /**
- * the matrix for computing square roots in this polynomial ring (given as
- * the array of its row vectors). This matrix is computed as the inverse of
- * the squaring matrix.
- */
- protected PolynomialGF2mSmallM[] sqRootMatrix;
-
- /**
- * Constructor.
- *
- * @param field the finite field
- * @param p the reduction polynomial
- */
- public PolynomialRingGF2m(GF2mField field, PolynomialGF2mSmallM p)
- {
- this.field = field;
- this.p = p;
- computeSquaringMatrix();
- computeSquareRootMatrix();
- }
-
- /**
- * @return the squaring matrix for this polynomial ring
- */
- public PolynomialGF2mSmallM[] getSquaringMatrix()
- {
- return sqMatrix;
- }
-
- /**
- * @return the matrix for computing square roots for this polynomial ring
- */
- public PolynomialGF2mSmallM[] getSquareRootMatrix()
- {
- return sqRootMatrix;
- }
-
- /**
- * Compute the squaring matrix for this polynomial ring, using the base
- * field and the reduction polynomial.
- */
- private void computeSquaringMatrix()
- {
- int numColumns = p.getDegree();
- sqMatrix = new PolynomialGF2mSmallM[numColumns];
- for (int i = 0; i < numColumns >> 1; i++)
- {
- int[] monomCoeffs = new int[(i << 1) + 1];
- monomCoeffs[i << 1] = 1;
- sqMatrix[i] = new PolynomialGF2mSmallM(field, monomCoeffs);
- }
- for (int i = numColumns >> 1; i < numColumns; i++)
- {
- int[] monomCoeffs = new int[(i << 1) + 1];
- monomCoeffs[i << 1] = 1;
- PolynomialGF2mSmallM monomial = new PolynomialGF2mSmallM(field,
- monomCoeffs);
- sqMatrix[i] = monomial.mod(p);
- }
- }
-
- /**
- * Compute the matrix for computing square roots in this polynomial ring by
- * inverting the squaring matrix.
- */
- private void computeSquareRootMatrix()
- {
- int numColumns = p.getDegree();
-
- // clone squaring matrix
- PolynomialGF2mSmallM[] tmpMatrix = new PolynomialGF2mSmallM[numColumns];
- for (int i = numColumns - 1; i >= 0; i--)
- {
- tmpMatrix[i] = new PolynomialGF2mSmallM(sqMatrix[i]);
- }
-
- // initialize square root matrix as unit matrix
- sqRootMatrix = new PolynomialGF2mSmallM[numColumns];
- for (int i = numColumns - 1; i >= 0; i--)
- {
- sqRootMatrix[i] = new PolynomialGF2mSmallM(field, i);
- }
-
- // simultaneously compute Gaussian reduction of squaring matrix and unit
- // matrix
- for (int i = 0; i < numColumns; i++)
- {
- // if diagonal element is zero
- if (tmpMatrix[i].getCoefficient(i) == 0)
- {
- boolean foundNonZero = false;
- // find a non-zero element in the same row
- for (int j = i + 1; j < numColumns; j++)
- {
- if (tmpMatrix[j].getCoefficient(i) != 0)
- {
- // found it, swap columns ...
- foundNonZero = true;
- swapColumns(tmpMatrix, i, j);
- swapColumns(sqRootMatrix, i, j);
- // ... and quit searching
- j = numColumns;
- continue;
- }
- }
- // if no non-zero element was found
- if (!foundNonZero)
- {
- // the matrix is not invertible
- throw new ArithmeticException(
- "Squaring matrix is not invertible.");
- }
- }
-
- // normalize i-th column
- int coef = tmpMatrix[i].getCoefficient(i);
- int invCoef = field.inverse(coef);
- tmpMatrix[i].multThisWithElement(invCoef);
- sqRootMatrix[i].multThisWithElement(invCoef);
-
- // normalize all other columns
- for (int j = 0; j < numColumns; j++)
- {
- if (j != i)
- {
- coef = tmpMatrix[j].getCoefficient(i);
- if (coef != 0)
- {
- PolynomialGF2mSmallM tmpSqColumn = tmpMatrix[i]
- .multWithElement(coef);
- PolynomialGF2mSmallM tmpInvColumn = sqRootMatrix[i]
- .multWithElement(coef);
- tmpMatrix[j].addToThis(tmpSqColumn);
- sqRootMatrix[j].addToThis(tmpInvColumn);
- }
- }
- }
- }
- }
-
- private static void swapColumns(PolynomialGF2mSmallM[] matrix, int first,
- int second)
- {
- PolynomialGF2mSmallM tmp = matrix[first];
- matrix[first] = matrix[second];
- matrix[second] = tmp;
- }
-
-}
diff --git a/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/RandUtils.java b/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/RandUtils.java
deleted file mode 100644
index dbb1d4a..0000000
--- a/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/RandUtils.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package org.bouncycastle.pqc.math.linearalgebra;
-
-import java.security.SecureRandom;
-
-public class RandUtils
-{
- static int nextInt(SecureRandom rand, int n)
- {
-
- if ((n & -n) == n) // i.e., n is a power of 2
- {
- return (int)((n * (long)(rand.nextInt() >>> 1)) >> 31);
- }
-
- int bits, value;
- do
- {
- bits = rand.nextInt() >>> 1;
- value = bits % n;
- }
- while (bits - value + (n - 1) < 0);
-
- return value;
- }
-}
diff --git a/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/Vector.java b/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/Vector.java
deleted file mode 100644
index 7e17164..0000000
--- a/bcprov/src/main/java/org/bouncycastle/pqc/math/linearalgebra/Vector.java
+++ /dev/null
@@ -1,69 +0,0 @@
-package 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 final 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 boolean 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 boolean equals(Object other);
-
- /**
- * @return the hash code of this vector
- */
- public abstract int hashCode();
-
- /**
- * @return a human readable form of this vector
- */
- public abstract String toString();
-
-}
diff --git a/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/euclid/BigIntEuclidean.java b/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/euclid/BigIntEuclidean.java
deleted file mode 100644
index 5fb3058..0000000
--- a/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/euclid/BigIntEuclidean.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package org.bouncycastle.pqc.math.ntru.euclid;
-
-import java.math.BigInteger;
-
-/**
- * Extended Euclidean Algorithm in <code>BigInteger</code>s
- */
-public class BigIntEuclidean
-{
- public BigInteger x, y, gcd;
-
- private BigIntEuclidean()
- {
- }
-
- /**
- * Runs the EEA on two <code>BigInteger</code>s<br>
- * Implemented from pseudocode on <a href="http://en.wikipedia.org/wiki/Extended_Euclidean_algorithm">Wikipedia</a>.
- *
- * @param a
- * @param b
- * @return a <code>BigIntEuclidean</code> object that contains the result in the variables <code>x</code>, <code>y</code>, and <code>gcd</code>
- */
- public static BigIntEuclidean calculate(BigInteger a, BigInteger b)
- {
- BigInteger x = BigInteger.ZERO;
- BigInteger lastx = BigInteger.ONE;
- BigInteger y = BigInteger.ONE;
- BigInteger lasty = BigInteger.ZERO;
- while (!b.equals(BigInteger.ZERO))
- {
- BigInteger[] quotientAndRemainder = a.divideAndRemainder(b);
- BigInteger quotient = quotientAndRemainder[0];
-
- BigInteger temp = a;
- a = b;
- b = quotientAndRemainder[1];
-
- temp = x;
- x = lastx.subtract(quotient.multiply(x));
- lastx = temp;
-
- temp = y;
- y = lasty.subtract(quotient.multiply(y));
- lasty = temp;
- }
-
- BigIntEuclidean result = new BigIntEuclidean();
- result.x = lastx;
- result.y = lasty;
- result.gcd = a;
- return result;
- }
-} \ No newline at end of file
diff --git a/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/euclid/IntEuclidean.java b/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/euclid/IntEuclidean.java
deleted file mode 100644
index c959a26..0000000
--- a/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/euclid/IntEuclidean.java
+++ /dev/null
@@ -1,51 +0,0 @@
-package org.bouncycastle.pqc.math.ntru.euclid;
-
-/**
- * Extended Euclidean Algorithm in <code>int</code>s
- */
-public class IntEuclidean
-{
- public int x, y, gcd;
-
- private IntEuclidean()
- {
- }
-
- /**
- * Runs the EEA on two <code>int</code>s<br>
- * Implemented from pseudocode on <a href="http://en.wikipedia.org/wiki/Extended_Euclidean_algorithm">Wikipedia</a>.
- *
- * @param a
- * @param b
- * @return a <code>IntEuclidean</code> object that contains the result in the variables <code>x</code>, <code>y</code>, and <code>gcd</code>
- */
- public static IntEuclidean calculate(int a, int b)
- {
- int x = 0;
- int lastx = 1;
- int y = 1;
- int lasty = 0;
- while (b != 0)
- {
- int quotient = a / b;
-
- int temp = a;
- a = b;
- b = temp % b;
-
- temp = x;
- x = lastx - quotient * x;
- lastx = temp;
-
- temp = y;
- y = lasty - quotient * y;
- lasty = temp;
- }
-
- IntEuclidean result = new IntEuclidean();
- result.x = lastx;
- result.y = lasty;
- result.gcd = a;
- return result;
- }
-} \ No newline at end of file
diff --git a/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/euclid/test/AllTests.java b/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/euclid/test/AllTests.java
deleted file mode 100644
index 6302e05..0000000
--- a/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/euclid/test/AllTests.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package org.bouncycastle.pqc.math.ntru.euclid.test;
-
-import junit.framework.Test;
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
-
-public class AllTests
- extends TestCase
-{
- public static void main (String[] args)
- {
- junit.textui.TestRunner.run(suite());
- }
-
- public static Test suite()
- {
- TestSuite suite = new TestSuite("NTRU Euclid Tests");
-
- suite.addTestSuite(BigIntEuclideanTest.class);
- suite.addTestSuite(IntEuclideanTest.class);
-
- return suite;
- }
-}
diff --git a/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/euclid/test/BigIntEuclideanTest.java b/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/euclid/test/BigIntEuclideanTest.java
deleted file mode 100644
index 2cb9467..0000000
--- a/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/euclid/test/BigIntEuclideanTest.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package org.bouncycastle.pqc.math.ntru.euclid.test;
-
-import java.math.BigInteger;
-
-import junit.framework.TestCase;
-import org.bouncycastle.pqc.math.ntru.euclid.BigIntEuclidean;
-
-public class BigIntEuclideanTest
- extends TestCase
-{
- public void testCalculate()
- {
- BigIntEuclidean r = BigIntEuclidean.calculate(BigInteger.valueOf(120), BigInteger.valueOf(23));
- assertEquals(BigInteger.valueOf(-9), r.x);
- assertEquals(BigInteger.valueOf(47), r.y);
- assertEquals(BigInteger.valueOf(1), r.gcd);
-
- r = BigIntEuclidean.calculate(BigInteger.valueOf(126), BigInteger.valueOf(231));
- assertEquals(BigInteger.valueOf(2), r.x);
- assertEquals(BigInteger.valueOf(-1), r.y);
- assertEquals(BigInteger.valueOf(21), r.gcd);
- }
-} \ No newline at end of file
diff --git a/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/euclid/test/IntEuclideanTest.java b/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/euclid/test/IntEuclideanTest.java
deleted file mode 100644
index ab2ba25..0000000
--- a/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/euclid/test/IntEuclideanTest.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/**
- * Copyright (c) 2011 Tim Buktu (tbuktu@hotmail.com)
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-package org.bouncycastle.pqc.math.ntru.euclid.test;
-
-import junit.framework.TestCase;
-import org.bouncycastle.pqc.math.ntru.euclid.IntEuclidean;
-
-public class IntEuclideanTest
- extends TestCase
-{
- public void testCalculate()
- {
- IntEuclidean r = IntEuclidean.calculate(120, 23);
- assertEquals(-9, r.x);
- assertEquals(47, r.y);
- assertEquals(1, r.gcd);
-
- r = IntEuclidean.calculate(126, 231);
- assertEquals(2, r.x);
- assertEquals(-1, r.y);
- assertEquals(21, r.gcd);
- }
-} \ No newline at end of file
diff --git a/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/BigDecimalPolynomial.java b/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/BigDecimalPolynomial.java
deleted file mode 100644
index 697f51a..0000000
--- a/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/BigDecimalPolynomial.java
+++ /dev/null
@@ -1,258 +0,0 @@
-package org.bouncycastle.pqc.math.ntru.polynomial;
-
-import java.math.BigDecimal;
-
-/**
- * A polynomial with {@link BigDecimal} coefficients.
- * Some methods (like <code>add</code>) change the polynomial, others (like <code>mult</code>) do
- * not but return the result as a new polynomial.
- */
-public class BigDecimalPolynomial
-{
- private static final BigDecimal ZERO = new BigDecimal("0");
- private static final BigDecimal ONE_HALF = new BigDecimal("0.5");
-
- BigDecimal[] coeffs;
-
- /**
- * Constructs a new polynomial with <code>N</code> coefficients initialized to 0.
- *
- * @param N the number of coefficients
- */
- BigDecimalPolynomial(int N)
- {
- coeffs = new BigDecimal[N];
- for (int i = 0; i < N; i++)
- {
- coeffs[i] = ZERO;
- }
- }
-
- /**
- * Constructs a new polynomial with a given set of coefficients.
- *
- * @param coeffs the coefficients
- */
- BigDecimalPolynomial(BigDecimal[] coeffs)
- {
- this.coeffs = coeffs;
- }
-
- /**
- * Constructs a <code>BigDecimalPolynomial</code> from a <code>BigIntPolynomial</code>. The two polynomials are independent of each other.
- *
- * @param p the original polynomial
- */
- public BigDecimalPolynomial(BigIntPolynomial p)
- {
- int N = p.coeffs.length;
- coeffs = new BigDecimal[N];
- for (int i = 0; i < N; i++)
- {
- coeffs[i] = new BigDecimal(p.coeffs[i]);
- }
- }
-
- /**
- * Divides all coefficients by 2.
- */
- public void halve()
- {
- for (int i = 0; i < coeffs.length; i++)
- {
- coeffs[i] = coeffs[i].multiply(ONE_HALF);
- }
- }
-
- /**
- * Multiplies the polynomial by another. Does not change this polynomial
- * but returns the result as a new polynomial.
- *
- * @param poly2 the polynomial to multiply by
- * @return a new polynomial
- */
- public BigDecimalPolynomial mult(BigIntPolynomial poly2)
- {
- return mult(new BigDecimalPolynomial(poly2));
- }
-
- /**
- * Multiplies the polynomial by another, taking the indices mod N. Does not
- * change this polynomial but returns the result as a new polynomial.
- *
- * @param poly2 the polynomial to multiply by
- * @return a new polynomial
- */
- public BigDecimalPolynomial mult(BigDecimalPolynomial poly2)
- {
- int N = coeffs.length;
- if (poly2.coeffs.length != N)
- {
- throw new IllegalArgumentException("Number of coefficients must be the same");
- }
-
- BigDecimalPolynomial c = multRecursive(poly2);
-
- if (c.coeffs.length > N)
- {
- for (int k = N; k < c.coeffs.length; k++)
- {
- c.coeffs[k - N] = c.coeffs[k - N].add(c.coeffs[k]);
- }
- c.coeffs = copyOf(c.coeffs, N);
- }
- return c;
- }
-
- /**
- * Karazuba multiplication
- */
- private BigDecimalPolynomial multRecursive(BigDecimalPolynomial poly2)
- {
- BigDecimal[] a = coeffs;
- BigDecimal[] b = poly2.coeffs;
-
- int n = poly2.coeffs.length;
- if (n <= 1)
- {
- BigDecimal[] c = coeffs.clone();
- for (int i = 0; i < coeffs.length; i++)
- {
- c[i] = c[i].multiply(poly2.coeffs[0]);
- }
- return new BigDecimalPolynomial(c);
- }
- else
- {
- int n1 = n / 2;
-
- BigDecimalPolynomial a1 = new BigDecimalPolynomial(copyOf(a, n1));
- BigDecimalPolynomial a2 = new BigDecimalPolynomial(copyOfRange(a, n1, n));
- BigDecimalPolynomial b1 = new BigDecimalPolynomial(copyOf(b, n1));
- BigDecimalPolynomial b2 = new BigDecimalPolynomial(copyOfRange(b, n1, n));
-
- BigDecimalPolynomial A = (BigDecimalPolynomial)a1.clone();
- A.add(a2);
- BigDecimalPolynomial B = (BigDecimalPolynomial)b1.clone();
- B.add(b2);
-
- BigDecimalPolynomial c1 = a1.multRecursive(b1);
- BigDecimalPolynomial c2 = a2.multRecursive(b2);
- BigDecimalPolynomial c3 = A.multRecursive(B);
- c3.sub(c1);
- c3.sub(c2);
-
- BigDecimalPolynomial c = new BigDecimalPolynomial(2 * n - 1);
- for (int i = 0; i < c1.coeffs.length; i++)
- {
- c.coeffs[i] = c1.coeffs[i];
- }
- for (int i = 0; i < c3.coeffs.length; i++)
- {
- c.coeffs[n1 + i] = c.coeffs[n1 + i].add(c3.coeffs[i]);
- }
- for (int i = 0; i < c2.coeffs.length; i++)
- {
- c.coeffs[2 * n1 + i] = c.coeffs[2 * n1 + i].add(c2.coeffs[i]);
- }
- return c;
- }
- }
-
- /**
- * Adds another polynomial which can have a different number of coefficients.
- *
- * @param b another polynomial
- */
- public void add(BigDecimalPolynomial b)
- {
- if (b.coeffs.length > coeffs.length)
- {
- int N = coeffs.length;
- coeffs = copyOf(coeffs, b.coeffs.length);
- for (int i = N; i < coeffs.length; i++)
- {
- coeffs[i] = ZERO;
- }
- }
- for (int i = 0; i < b.coeffs.length; i++)
- {
- coeffs[i] = coeffs[i].add(b.coeffs[i]);
- }
- }
-
- /**
- * Subtracts another polynomial which can have a different number of coefficients.
- *
- * @param b
- */
- void sub(BigDecimalPolynomial b)
- {
- if (b.coeffs.length > coeffs.length)
- {
- int N = coeffs.length;
- coeffs = copyOf(coeffs, b.coeffs.length);
- for (int i = N; i < coeffs.length; i++)
- {
- coeffs[i] = ZERO;
- }
- }
- for (int i = 0; i < b.coeffs.length; i++)
- {
- coeffs[i] = coeffs[i].subtract(b.coeffs[i]);
- }
- }
-
- /**
- * Rounds all coefficients to the nearest integer.
- *
- * @return a new polynomial with <code>BigInteger</code> coefficients
- */
- public BigIntPolynomial round()
- {
- int N = coeffs.length;
- BigIntPolynomial p = new BigIntPolynomial(N);
- for (int i = 0; i < N; i++)
- {
- p.coeffs[i] = coeffs[i].setScale(0, BigDecimal.ROUND_HALF_EVEN).toBigInteger();
- }
- return p;
- }
-
- /**
- * Makes a copy of the polynomial that is independent of the original.
- */
- public Object clone()
- {
- return new BigDecimalPolynomial(coeffs.clone());
- }
-
- private BigDecimal[] copyOf(BigDecimal[] a, int length)
- {
- BigDecimal[] tmp = new BigDecimal[length];
-
- System.arraycopy(a, 0, tmp, 0, a.length < length ? a.length : length);
-
- return tmp;
- }
-
- private BigDecimal[] copyOfRange(BigDecimal[] a, int from, int to)
- {
- int newLength = to - from;
- BigDecimal[] tmp = new BigDecimal[to - from];
-
- System.arraycopy(a, from, tmp, 0, (a.length - from) < newLength ? (a.length - from) : newLength);
-
- return tmp;
- }
-
- public BigDecimal[] getCoeffs()
- {
- BigDecimal[] tmp = new BigDecimal[coeffs.length];
-
- System.arraycopy(coeffs, 0, tmp, 0, coeffs.length);
-
- return tmp;
- }
-
-}
diff --git a/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/BigIntPolynomial.java b/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/BigIntPolynomial.java
deleted file mode 100644
index 3c79b2e..0000000
--- a/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/BigIntPolynomial.java
+++ /dev/null
@@ -1,394 +0,0 @@
-package org.bouncycastle.pqc.math.ntru.polynomial;
-
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.security.SecureRandom;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-import org.bouncycastle.util.Arrays;
-
-/**
- * A polynomial with {@link BigInteger} coefficients.<br>
- * Some methods (like <code>add</code>) change the polynomial, others (like <code>mult</code>) do
- * not but return the result as a new polynomial.
- */
-public class BigIntPolynomial
-{
- private final static double LOG_10_2 = Math.log10(2);
-
- BigInteger[] coeffs;
-
- /**
- * Constructs a new polynomial with <code>N</code> coefficients initialized to 0.
- *
- * @param N the number of coefficients
- */
- BigIntPolynomial(int N)
- {
- coeffs = new BigInteger[N];
- for (int i = 0; i < N; i++)
- {
- coeffs[i] = Constants.BIGINT_ZERO;
- }
- }
-
- /**
- * Constructs a new polynomial with a given set of coefficients.
- *
- * @param coeffs the coefficients
- */
- BigIntPolynomial(BigInteger[] coeffs)
- {
- this.coeffs = coeffs;
- }
-
- /**
- * Constructs a <code>BigIntPolynomial</code> from a <code>IntegerPolynomial</code>. The two polynomials are
- * independent of each other.
- *
- * @param p the original polynomial
- */
- public BigIntPolynomial(IntegerPolynomial p)
- {
- coeffs = new BigInteger[p.coeffs.length];
- for (int i = 0; i < coeffs.length; i++)
- {
- coeffs[i] = BigInteger.valueOf(p.coeffs[i]);
- }
- }
-
- /**
- * Generates a random polynomial with <code>numOnes</code> coefficients equal to 1,
- * <code>numNegOnes</code> coefficients equal to -1, and the rest equal to 0.
- *
- * @param N number of coefficients
- * @param numOnes number of 1's
- * @param numNegOnes number of -1's
- * @return
- */
- static BigIntPolynomial generateRandomSmall(int N, int numOnes, int numNegOnes)
- {
- List coeffs = new ArrayList();
- for (int i = 0; i < numOnes; i++)
- {
- coeffs.add(Constants.BIGINT_ONE);
- }
- for (int i = 0; i < numNegOnes; i++)
- {
- coeffs.add(BigInteger.valueOf(-1));
- }
- while (coeffs.size() < N)
- {
- coeffs.add(Constants.BIGINT_ZERO);
- }
- Collections.shuffle(coeffs, new SecureRandom());
-
- BigIntPolynomial poly = new BigIntPolynomial(N);
- for (int i = 0; i < coeffs.size(); i++)
- {
- poly.coeffs[i] = (BigInteger)coeffs.get(i);
- }
- return poly;
- }
-
- /**
- * Multiplies the polynomial by another, taking the indices mod N. Does not
- * change this polynomial but returns the result as a new polynomial.<br>
- * Both polynomials must have the same number of coefficients.
- *
- * @param poly2 the polynomial to multiply by
- * @return a new polynomial
- */
- public BigIntPolynomial mult(BigIntPolynomial poly2)
- {
- int N = coeffs.length;
- if (poly2.coeffs.length != N)
- {
- throw new IllegalArgumentException("Number of coefficients must be the same");
- }
-
- BigIntPolynomial c = multRecursive(poly2);
-
- if (c.coeffs.length > N)
- {
- for (int k = N; k < c.coeffs.length; k++)
- {
- c.coeffs[k - N] = c.coeffs[k - N].add(c.coeffs[k]);
- }
- c.coeffs = Arrays.copyOf(c.coeffs, N);
- }
- return c;
- }
-
- /**
- * Karazuba multiplication
- */
- private BigIntPolynomial multRecursive(BigIntPolynomial poly2)
- {
- BigInteger[] a = coeffs;
- BigInteger[] b = poly2.coeffs;
-
- int n = poly2.coeffs.length;
- if (n <= 1)
- {
- BigInteger[] c = Arrays.clone(coeffs);
- for (int i = 0; i < coeffs.length; i++)
- {
- c[i] = c[i].multiply(poly2.coeffs[0]);
- }
- return new BigIntPolynomial(c);
- }
- else
- {
- int n1 = n / 2;
-
- BigIntPolynomial a1 = new BigIntPolynomial(Arrays.copyOf(a, n1));
- BigIntPolynomial a2 = new BigIntPolynomial(Arrays.copyOfRange(a, n1, n));
- BigIntPolynomial b1 = new BigIntPolynomial(Arrays.copyOf(b, n1));
- BigIntPolynomial b2 = new BigIntPolynomial(Arrays.copyOfRange(b, n1, n));
-
- BigIntPolynomial A = (BigIntPolynomial)a1.clone();
- A.add(a2);
- BigIntPolynomial B = (BigIntPolynomial)b1.clone();
- B.add(b2);
-
- BigIntPolynomial c1 = a1.multRecursive(b1);
- BigIntPolynomial c2 = a2.multRecursive(b2);
- BigIntPolynomial c3 = A.multRecursive(B);
- c3.sub(c1);
- c3.sub(c2);
-
- BigIntPolynomial c = new BigIntPolynomial(2 * n - 1);
- for (int i = 0; i < c1.coeffs.length; i++)
- {
- c.coeffs[i] = c1.coeffs[i];
- }
- for (int i = 0; i < c3.coeffs.length; i++)
- {
- c.coeffs[n1 + i] = c.coeffs[n1 + i].add(c3.coeffs[i]);
- }
- for (int i = 0; i < c2.coeffs.length; i++)
- {
- c.coeffs[2 * n1 + i] = c.coeffs[2 * n1 + i].add(c2.coeffs[i]);
- }
- return c;
- }
- }
-
- /**
- * Adds another polynomial which can have a different number of coefficients,
- * and takes the coefficient values mod <code>modulus</code>.
- *
- * @param b another polynomial
- */
- void add(BigIntPolynomial b, BigInteger modulus)
- {
- add(b);
- mod(modulus);
- }
-
- /**
- * Adds another polynomial which can have a different number of coefficients.
- *
- * @param b another polynomial
- */
- public void add(BigIntPolynomial b)
- {
- if (b.coeffs.length > coeffs.length)
- {
- int N = coeffs.length;
- coeffs = Arrays.copyOf(coeffs, b.coeffs.length);
- for (int i = N; i < coeffs.length; i++)
- {
- coeffs[i] = Constants.BIGINT_ZERO;
- }
- }
- for (int i = 0; i < b.coeffs.length; i++)
- {
- coeffs[i] = coeffs[i].add(b.coeffs[i]);
- }
- }
-
- /**
- * Subtracts another polynomial which can have a different number of coefficients.
- *
- * @param b another polynomial
- */
- public void sub(BigIntPolynomial b)
- {
- if (b.coeffs.length > coeffs.length)
- {
- int N = coeffs.length;
- coeffs = Arrays.copyOf(coeffs, b.coeffs.length);
- for (int i = N; i < coeffs.length; i++)
- {
- coeffs[i] = Constants.BIGINT_ZERO;
- }
- }
- for (int i = 0; i < b.coeffs.length; i++)
- {
- coeffs[i] = coeffs[i].subtract(b.coeffs[i]);
- }
- }
-
- /**
- * Multiplies each coefficient by a <code>BigInteger</code>. Does not return a new polynomial but modifies this polynomial.
- *
- * @param factor
- */
- public void mult(BigInteger factor)
- {
- for (int i = 0; i < coeffs.length; i++)
- {
- coeffs[i] = coeffs[i].multiply(factor);
- }
- }
-
- /**
- * Multiplies each coefficient by a <code>int</code>. Does not return a new polynomial but modifies this polynomial.
- *
- * @param factor
- */
- void mult(int factor)
- {
- mult(BigInteger.valueOf(factor));
- }
-
- /**
- * Divides each coefficient by a <code>BigInteger</code> and rounds the result to the nearest whole number.<br>
- * Does not return a new polynomial but modifies this polynomial.
- *
- * @param divisor the number to divide by
- */
- public void div(BigInteger divisor)
- {
- BigInteger d = divisor.add(Constants.BIGINT_ONE).divide(BigInteger.valueOf(2));
- for (int i = 0; i < coeffs.length; i++)
- {
- coeffs[i] = coeffs[i].compareTo(Constants.BIGINT_ZERO) > 0 ? coeffs[i].add(d) : coeffs[i].add(d.negate());
- coeffs[i] = coeffs[i].divide(divisor);
- }
- }
-
- /**
- * Divides each coefficient by a <code>BigDecimal</code> and rounds the result to <code>decimalPlaces</code> places.
- *
- * @param divisor the number to divide by
- * @param decimalPlaces the number of fractional digits to round the result to
- * @return a new <code>BigDecimalPolynomial</code>
- */
- public BigDecimalPolynomial div(BigDecimal divisor, int decimalPlaces)
- {
- BigInteger max = maxCoeffAbs();
- int coeffLength = (int)(max.bitLength() * LOG_10_2) + 1;
- // factor = 1/divisor
- BigDecimal factor = Constants.BIGDEC_ONE.divide(divisor, coeffLength + decimalPlaces + 1, BigDecimal.ROUND_HALF_EVEN);
-
- // multiply each coefficient by factor
- BigDecimalPolynomial p = new BigDecimalPolynomial(coeffs.length);
- for (int i = 0; i < coeffs.length; i++)
- // multiply, then truncate after decimalPlaces so subsequent operations aren't slowed down
- {
- p.coeffs[i] = new BigDecimal(coeffs[i]).multiply(factor).setScale(decimalPlaces, BigDecimal.ROUND_HALF_EVEN);
- }
-
- return p;
- }
-
- /**
- * Returns the base10 length of the largest coefficient.
- *
- * @return length of the longest coefficient
- */
- public int getMaxCoeffLength()
- {
- return (int)(maxCoeffAbs().bitLength() * LOG_10_2) + 1;
- }
-
- private BigInteger maxCoeffAbs()
- {
- BigInteger max = coeffs[0].abs();
- for (int i = 1; i < coeffs.length; i++)
- {
- BigInteger coeff = coeffs[i].abs();
- if (coeff.compareTo(max) > 0)
- {
- max = coeff;
- }
- }
- return max;
- }
-
- /**
- * Takes each coefficient modulo a number.
- *
- * @param modulus
- */
- public void mod(BigInteger modulus)
- {
- for (int i = 0; i < coeffs.length; i++)
- {
- coeffs[i] = coeffs[i].mod(modulus);
- }
- }
-
- /**
- * Returns the sum of all coefficients, i.e. evaluates the polynomial at 0.
- *
- * @return the sum of all coefficients
- */
- BigInteger sumCoeffs()
- {
- BigInteger sum = Constants.BIGINT_ZERO;
- for (int i = 0; i < coeffs.length; i++)
- {
- sum = sum.add(coeffs[i]);
- }
- return sum;
- }
-
- /**
- * Makes a copy of the polynomial that is independent of the original.
- */
- public Object clone()
- {
- return new BigIntPolynomial(coeffs.clone());
- }
-
- public int hashCode()
- {
- final int prime = 31;
- int result = 1;
- result = prime * result + Arrays.hashCode(coeffs);
- return result;
- }
-
- public boolean equals(Object obj)
- {
- if (this == obj)
- {
- return true;
- }
- if (obj == null)
- {
- return false;
- }
- if (getClass() != obj.getClass())
- {
- return false;
- }
- BigIntPolynomial other = (BigIntPolynomial)obj;
- if (!Arrays.areEqual(coeffs, other.coeffs))
- {
- return false;
- }
- return true;
- }
-
- public BigInteger[] getCoeffs()
- {
- return Arrays.clone(coeffs);
- }
-}
diff --git a/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/Constants.java b/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/Constants.java
deleted file mode 100644
index 2b41b19..0000000
--- a/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/Constants.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package org.bouncycastle.pqc.math.ntru.polynomial;
-
-import java.math.BigDecimal;
-import java.math.BigInteger;
-
-public class Constants
-{
- static final BigInteger BIGINT_ZERO = BigInteger.valueOf(0);
- static final BigInteger BIGINT_ONE = BigInteger.valueOf(1);
-
- static final BigDecimal BIGDEC_ONE = BigDecimal.valueOf(1);
-}
diff --git a/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/DenseTernaryPolynomial.java b/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/DenseTernaryPolynomial.java
deleted file mode 100644
index 85730da..0000000
--- a/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/DenseTernaryPolynomial.java
+++ /dev/null
@@ -1,142 +0,0 @@
-package org.bouncycastle.pqc.math.ntru.polynomial;
-
-import java.security.SecureRandom;
-
-import org.bouncycastle.pqc.math.ntru.util.Util;
-import org.bouncycastle.util.Arrays;
-
-/**
- * A <code>TernaryPolynomial</code> with a "high" number of nonzero coefficients.
- */
-public class DenseTernaryPolynomial
- extends IntegerPolynomial
- implements TernaryPolynomial
-{
-
- /**
- * Constructs a new <code>DenseTernaryPolynomial</code> with <code>N</code> coefficients.
- *
- * @param N the number of coefficients
- */
- DenseTernaryPolynomial(int N)
- {
- super(N);
- checkTernarity();
- }
-
- /**
- * Constructs a <code>DenseTernaryPolynomial</code> from a <code>IntegerPolynomial</code>. The two polynomials are
- * independent of each other.
- *
- * @param intPoly the original polynomial
- */
- public DenseTernaryPolynomial(IntegerPolynomial intPoly)
- {
- this(intPoly.coeffs);
- }
-
- /**
- * Constructs a new <code>DenseTernaryPolynomial</code> with a given set of coefficients.
- *
- * @param coeffs the coefficients
- */
- public DenseTernaryPolynomial(int[] coeffs)
- {
- super(coeffs);
- checkTernarity();
- }
-
- private void checkTernarity()
- {
- for (int i = 0; i != coeffs.length; i++)
- {
- int c = coeffs[i];
- if (c < -1 || c > 1)
- {
- throw new IllegalStateException("Illegal value: " + c + ", must be one of {-1, 0, 1}");
- }
- }
- }
-
- /**
- * Generates a random polynomial with <code>numOnes</code> coefficients equal to 1,
- * <code>numNegOnes</code> coefficients equal to -1, and the rest equal to 0.
- *
- * @param N number of coefficients
- * @param numOnes number of 1's
- * @param numNegOnes number of -1's
- */
- public static DenseTernaryPolynomial generateRandom(int N, int numOnes, int numNegOnes, SecureRandom random)
- {
- int[] coeffs = Util.generateRandomTernary(N, numOnes, numNegOnes, random);
- return new DenseTernaryPolynomial(coeffs);
- }
-
- /**
- * Generates a polynomial with coefficients randomly selected from <code>{-1, 0, 1}</code>.
- *
- * @param N number of coefficients
- */
- public static DenseTernaryPolynomial generateRandom(int N, SecureRandom random)
- {
- DenseTernaryPolynomial poly = new DenseTernaryPolynomial(N);
- for (int i = 0; i < N; i++)
- {
- poly.coeffs[i] = random.nextInt(3) - 1;
- }
- return poly;
- }
-
- public IntegerPolynomial mult(IntegerPolynomial poly2, int modulus)
- {
- // even on 32-bit systems, LongPolynomial5 multiplies faster than IntegerPolynomial
- if (modulus == 2048)
- {
- IntegerPolynomial poly2Pos = (IntegerPolynomial)poly2.clone();
- poly2Pos.modPositive(2048);
- LongPolynomial5 poly5 = new LongPolynomial5(poly2Pos);
- return poly5.mult(this).toIntegerPolynomial();
- }
- else
- {
- return super.mult(poly2, modulus);
- }
- }
-
- public int[] getOnes()
- {
- int N = coeffs.length;
- int[] ones = new int[N];
- int onesIdx = 0;
- for (int i = 0; i < N; i++)
- {
- int c = coeffs[i];
- if (c == 1)
- {
- ones[onesIdx++] = i;
- }
- }
- return Arrays.copyOf(ones, onesIdx);
- }
-
- public int[] getNegOnes()
- {
- int N = coeffs.length;
- int[] negOnes = new int[N];
- int negOnesIdx = 0;
- for (int i = 0; i < N; i++)
- {
- int c = coeffs[i];
- if (c == -1)
- {
- negOnes[negOnesIdx++] = i;
- }
- }
- return Arrays.copyOf(negOnes, negOnesIdx);
- }
-
- public int size()
- {
- return coeffs.length;
- }
-}
diff --git a/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/IntegerPolynomial.java b/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/IntegerPolynomial.java
deleted file mode 100644
index c6bd7fb..0000000
--- a/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/IntegerPolynomial.java
+++ /dev/null
@@ -1,1358 +0,0 @@
-package org.bouncycastle.pqc.math.ntru.polynomial;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.math.BigInteger;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-import java.util.concurrent.LinkedBlockingQueue;
-
-import org.bouncycastle.pqc.math.ntru.euclid.BigIntEuclidean;
-import org.bouncycastle.pqc.math.ntru.util.ArrayEncoder;
-import org.bouncycastle.pqc.math.ntru.util.Util;
-import org.bouncycastle.util.Arrays;
-
-/**
- * A polynomial with <code>int</code> coefficients.<br>
- * Some methods (like <code>add</code>) change the polynomial, others (like <code>mult</code>) do
- * not but return the result as a new polynomial.
- */
-public class IntegerPolynomial
- implements Polynomial
-{
- private static final int NUM_EQUAL_RESULTANTS = 3;
- /**
- * Prime numbers &gt; 4500 for resultant computation. Starting them below ~4400 causes incorrect results occasionally.
- * Fortunately, 4500 is about the optimum number for performance.<br/>
- * This array contains enough prime numbers so primes never have to be computed on-line for any standard {@link org.bouncycastle.pqc.crypto.ntru.NTRUSigningParameters}.
- */
- private static final int[] PRIMES = new int[]{
- 4507, 4513, 4517, 4519, 4523, 4547, 4549, 4561, 4567, 4583,
- 4591, 4597, 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657,
- 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751,
- 4759, 4783, 4787, 4789, 4793, 4799, 4801, 4813, 4817, 4831,
- 4861, 4871, 4877, 4889, 4903, 4909, 4919, 4931, 4933, 4937,
- 4943, 4951, 4957, 4967, 4969, 4973, 4987, 4993, 4999, 5003,
- 5009, 5011, 5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087,
- 5099, 5101, 5107, 5113, 5119, 5147, 5153, 5167, 5171, 5179,
- 5189, 5197, 5209, 5227, 5231, 5233, 5237, 5261, 5273, 5279,
- 5281, 5297, 5303, 5309, 5323, 5333, 5347, 5351, 5381, 5387,
- 5393, 5399, 5407, 5413, 5417, 5419, 5431, 5437, 5441, 5443,
- 5449, 5471, 5477, 5479, 5483, 5501, 5503, 5507, 5519, 5521,
- 5527, 5531, 5557, 5563, 5569, 5573, 5581, 5591, 5623, 5639,
- 5641, 5647, 5651, 5653, 5657, 5659, 5669, 5683, 5689, 5693,
- 5701, 5711, 5717, 5737, 5741, 5743, 5749, 5779, 5783, 5791,
- 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, 5851, 5857,
- 5861, 5867, 5869, 5879, 5881, 5897, 5903, 5923, 5927, 5939,
- 5953, 5981, 5987, 6007, 6011, 6029, 6037, 6043, 6047, 6053,
- 6067, 6073, 6079, 6089, 6091, 6101, 6113, 6121, 6131, 6133,
- 6143, 6151, 6163, 6173, 6197, 6199, 6203, 6211, 6217, 6221,
- 6229, 6247, 6257, 6263, 6269, 6271, 6277, 6287, 6299, 6301,
- 6311, 6317, 6323, 6329, 6337, 6343, 6353, 6359, 6361, 6367,
- 6373, 6379, 6389, 6397, 6421, 6427, 6449, 6451, 6469, 6473,
- 6481, 6491, 6521, 6529, 6547, 6551, 6553, 6563, 6569, 6571,
- 6577, 6581, 6599, 6607, 6619, 6637, 6653, 6659, 6661, 6673,
- 6679, 6689, 6691, 6701, 6703, 6709, 6719, 6733, 6737, 6761,
- 6763, 6779, 6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833,
- 6841, 6857, 6863, 6869, 6871, 6883, 6899, 6907, 6911, 6917,
- 6947, 6949, 6959, 6961, 6967, 6971, 6977, 6983, 6991, 6997,
- 7001, 7013, 7019, 7027, 7039, 7043, 7057, 7069, 7079, 7103,
- 7109, 7121, 7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207,
- 7211, 7213, 7219, 7229, 7237, 7243, 7247, 7253, 7283, 7297,
- 7307, 7309, 7321, 7331, 7333, 7349, 7351, 7369, 7393, 7411,
- 7417, 7433, 7451, 7457, 7459, 7477, 7481, 7487, 7489, 7499,
- 7507, 7517, 7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561,
- 7573, 7577, 7583, 7589, 7591, 7603, 7607, 7621, 7639, 7643,
- 7649, 7669, 7673, 7681, 7687, 7691, 7699, 7703, 7717, 7723,
- 7727, 7741, 7753, 7757, 7759, 7789, 7793, 7817, 7823, 7829,
- 7841, 7853, 7867, 7873, 7877, 7879, 7883, 7901, 7907, 7919,
- 7927, 7933, 7937, 7949, 7951, 7963, 7993, 8009, 8011, 8017,
- 8039, 8053, 8059, 8069, 8081, 8087, 8089, 8093, 8101, 8111,
- 8117, 8123, 8147, 8161, 8167, 8171, 8179, 8191, 8209, 8219,
- 8221, 8231, 8233, 8237, 8243, 8263, 8269, 8273, 8287, 8291,
- 8293, 8297, 8311, 8317, 8329, 8353, 8363, 8369, 8377, 8387,
- 8389, 8419, 8423, 8429, 8431, 8443, 8447, 8461, 8467, 8501,
- 8513, 8521, 8527, 8537, 8539, 8543, 8563, 8573, 8581, 8597,
- 8599, 8609, 8623, 8627, 8629, 8641, 8647, 8663, 8669, 8677,
- 8681, 8689, 8693, 8699, 8707, 8713, 8719, 8731, 8737, 8741,
- 8747, 8753, 8761, 8779, 8783, 8803, 8807, 8819, 8821, 8831,
- 8837, 8839, 8849, 8861, 8863, 8867, 8887, 8893, 8923, 8929,
- 8933, 8941, 8951, 8963, 8969, 8971, 8999, 9001, 9007, 9011,
- 9013, 9029, 9041, 9043, 9049, 9059, 9067, 9091, 9103, 9109,
- 9127, 9133, 9137, 9151, 9157, 9161, 9173, 9181, 9187, 9199,
- 9203, 9209, 9221, 9227, 9239, 9241, 9257, 9277, 9281, 9283,
- 9293, 9311, 9319, 9323, 9337, 9341, 9343, 9349, 9371, 9377,
- 9391, 9397, 9403, 9413, 9419, 9421, 9431, 9433, 9437, 9439,
- 9461, 9463, 9467, 9473, 9479, 9491, 9497, 9511, 9521, 9533,
- 9539, 9547, 9551, 9587, 9601, 9613, 9619, 9623, 9629, 9631,
- 9643, 9649, 9661, 9677, 9679, 9689, 9697, 9719, 9721, 9733,
- 9739, 9743, 9749, 9767, 9769, 9781, 9787, 9791, 9803, 9811,
- 9817, 9829, 9833, 9839, 9851, 9857, 9859, 9871, 9883, 9887,
- 9901, 9907, 9923, 9929, 9931, 9941, 9949, 9967, 9973};
- private static final List BIGINT_PRIMES;
-
- static
- {
- BIGINT_PRIMES = new ArrayList();
- for (int i = 0; i != PRIMES.length; i++)
- {
- BIGINT_PRIMES.add(BigInteger.valueOf(PRIMES[i]));
- }
- }
-
- public int[] coeffs;
-
- /**
- * Constructs a new polynomial with <code>N</code> coefficients initialized to 0.
- *
- * @param N the number of coefficients
- */
- public IntegerPolynomial(int N)
- {
- coeffs = new int[N];
- }
-
- /**
- * Constructs a new polynomial with a given set of coefficients.
- *
- * @param coeffs the coefficients
- */
- public IntegerPolynomial(int[] coeffs)
- {
- this.coeffs = coeffs;
- }
-
- /**
- * Constructs a <code>IntegerPolynomial</code> from a <code>BigIntPolynomial</code>. The two polynomials are independent of each other.
- *
- * @param p the original polynomial
- */
- public IntegerPolynomial(BigIntPolynomial p)
- {
- coeffs = new int[p.coeffs.length];
- for (int i = 0; i < p.coeffs.length; i++)
- {
- coeffs[i] = p.coeffs[i].intValue();
- }
- }
-
- /**
- * Decodes a byte array to a polynomial with <code>N</code> ternary coefficients<br>
- * Ignores any excess bytes.
- *
- * @param data an encoded ternary polynomial
- * @param N number of coefficients
- * @return the decoded polynomial
- */
- public static IntegerPolynomial fromBinary3Sves(byte[] data, int N)
- {
- return new IntegerPolynomial(ArrayEncoder.decodeMod3Sves(data, N));
- }
-
- /**
- * Converts a byte array produced by {@link #toBinary3Tight()} to a polynomial.
- *
- * @param b a byte array
- * @param N number of coefficients
- * @return the decoded polynomial
- */
- public static IntegerPolynomial fromBinary3Tight(byte[] b, int N)
- {
- return new IntegerPolynomial(ArrayEncoder.decodeMod3Tight(b, N));
- }
-
- /**
- * Reads data produced by {@link #toBinary3Tight()} from an input stream and converts it to a polynomial.
- *
- * @param is an input stream
- * @param N number of coefficients
- * @return the decoded polynomial
- */
- public static IntegerPolynomial fromBinary3Tight(InputStream is, int N)
- throws IOException
- {
- return new IntegerPolynomial(ArrayEncoder.decodeMod3Tight(is, N));
- }
-
- /**
- * Returns a polynomial with N coefficients between <code>0</code> and <code>q-1</code>.<br>
- * <code>q</code> must be a power of 2.<br>
- * Ignores any excess bytes.
- *
- * @param data an encoded ternary polynomial
- * @param N number of coefficients
- * @param q
- * @return the decoded polynomial
- */
- public static IntegerPolynomial fromBinary(byte[] data, int N, int q)
- {
- return new IntegerPolynomial(ArrayEncoder.decodeModQ(data, N, q));
- }
-
- /**
- * Returns a polynomial with N coefficients between <code>0</code> and <code>q-1</code>.<br>
- * <code>q</code> must be a power of 2.<br>
- * Ignores any excess bytes.
- *
- * @param is an encoded ternary polynomial
- * @param N number of coefficients
- * @param q
- * @return the decoded polynomial
- */
- public static IntegerPolynomial fromBinary(InputStream is, int N, int q)
- throws IOException
- {
- return new IntegerPolynomial(ArrayEncoder.decodeModQ(is, N, q));
- }
-
- /**
- * Encodes a polynomial with ternary coefficients to binary.
- * <code>coeffs[2*i]</code> and <code>coeffs[2*i+1]</code> must not both equal -1 for any integer <code>i</code>,
- * so this method is only safe to use with polynomials produced by <code>fromBinary3Sves()</code>.
- *
- * @return the encoded polynomial
- */
- public byte[] toBinary3Sves()
- {
- return ArrayEncoder.encodeMod3Sves(coeffs);
- }
-
- /**
- * Converts a polynomial with ternary coefficients to binary.
- *
- * @return the encoded polynomial
- */
- public byte[] toBinary3Tight()
- {
- BigInteger sum = Constants.BIGINT_ZERO;
- for (int i = coeffs.length - 1; i >= 0; i--)
- {
- sum = sum.multiply(BigInteger.valueOf(3));
- sum = sum.add(BigInteger.valueOf(coeffs[i] + 1));
- }
-
- int size = (BigInteger.valueOf(3).pow(coeffs.length).bitLength() + 7) / 8;
- byte[] arr = sum.toByteArray();
-
- if (arr.length < size)
- {
- // pad with leading zeros so arr.length==size
- byte[] arr2 = new byte[size];
- System.arraycopy(arr, 0, arr2, size - arr.length, arr.length);
- return arr2;
- }
-
- if (arr.length > size)
- // drop sign bit
- {
- arr = Arrays.copyOfRange(arr, 1, arr.length);
- }
- return arr;
- }
-
- /**
- * Encodes a polynomial whose coefficients are between 0 and q, to binary. q must be a power of 2.
- *
- * @param q
- * @return the encoded polynomial
- */
- public byte[] toBinary(int q)
- {
- return ArrayEncoder.encodeModQ(coeffs, q);
- }
-
- /**
- * Multiplies the polynomial with another, taking the values mod modulus and the indices mod N
- */
- public IntegerPolynomial mult(IntegerPolynomial poly2, int modulus)
- {
- IntegerPolynomial c = mult(poly2);
- c.mod(modulus);
- return c;
- }
-
- /**
- * Multiplies the polynomial with another, taking the indices mod N
- */
- public IntegerPolynomial mult(IntegerPolynomial poly2)
- {
- int N = coeffs.length;
- if (poly2.coeffs.length != N)
- {
- throw new IllegalArgumentException("Number of coefficients must be the same");
- }
-
- IntegerPolynomial c = multRecursive(poly2);
-
- if (c.coeffs.length > N)
- {
- for (int k = N; k < c.coeffs.length; k++)
- {
- c.coeffs[k - N] += c.coeffs[k];
- }
- c.coeffs = Arrays.copyOf(c.coeffs, N);
- }
- return c;
- }
-
- public BigIntPolynomial mult(BigIntPolynomial poly2)
- {
- return new BigIntPolynomial(this).mult(poly2);
- }
-
- /**
- * Karazuba multiplication
- */
- private IntegerPolynomial multRecursive(IntegerPolynomial poly2)
- {
- int[] a = coeffs;
- int[] b = poly2.coeffs;
-
- int n = poly2.coeffs.length;
- if (n <= 32)
- {
- int cn = 2 * n - 1;
- IntegerPolynomial c = new IntegerPolynomial(new int[cn]);
- for (int k = 0; k < cn; k++)
- {
- for (int i = Math.max(0, k - n + 1); i <= Math.min(k, n - 1); i++)
- {
- c.coeffs[k] += b[i] * a[k - i];
- }
- }
- return c;
- }
- else
- {
- int n1 = n / 2;
-
- IntegerPolynomial a1 = new IntegerPolynomial(Arrays.copyOf(a, n1));
- IntegerPolynomial a2 = new IntegerPolynomial(Arrays.copyOfRange(a, n1, n));
- IntegerPolynomial b1 = new IntegerPolynomial(Arrays.copyOf(b, n1));
- IntegerPolynomial b2 = new IntegerPolynomial(Arrays.copyOfRange(b, n1, n));
-
- IntegerPolynomial A = (IntegerPolynomial)a1.clone();
- A.add(a2);
- IntegerPolynomial B = (IntegerPolynomial)b1.clone();
- B.add(b2);
-
- IntegerPolynomial c1 = a1.multRecursive(b1);
- IntegerPolynomial c2 = a2.multRecursive(b2);
- IntegerPolynomial c3 = A.multRecursive(B);
- c3.sub(c1);
- c3.sub(c2);
-
- IntegerPolynomial c = new IntegerPolynomial(2 * n - 1);
- for (int i = 0; i < c1.coeffs.length; i++)
- {
- c.coeffs[i] = c1.coeffs[i];
- }
- for (int i = 0; i < c3.coeffs.length; i++)
- {
- c.coeffs[n1 + i] += c3.coeffs[i];
- }
- for (int i = 0; i < c2.coeffs.length; i++)
- {
- c.coeffs[2 * n1 + i] += c2.coeffs[i];
- }
- return c;
- }
- }
-
- /**
- * Computes the inverse mod <code>q; q</code> must be a power of 2.<br>
- * Returns <code>null</code> if the polynomial is not invertible.
- *
- * @param q the modulus
- * @return a new polynomial
- */
- public IntegerPolynomial invertFq(int q)
- {
- int N = coeffs.length;
- int k = 0;
- IntegerPolynomial b = new IntegerPolynomial(N + 1);
- b.coeffs[0] = 1;
- IntegerPolynomial c = new IntegerPolynomial(N + 1);
- IntegerPolynomial f = new IntegerPolynomial(N + 1);
- f.coeffs = Arrays.copyOf(coeffs, N + 1);
- f.modPositive(2);
- // set g(x) = x^N − 1
- IntegerPolynomial g = new IntegerPolynomial(N + 1);
- g.coeffs[0] = 1;
- g.coeffs[N] = 1;
- while (true)
- {
- while (f.coeffs[0] == 0)
- {
- for (int i = 1; i <= N; i++)
- {
- f.coeffs[i - 1] = f.coeffs[i]; // f(x) = f(x) / x
- c.coeffs[N + 1 - i] = c.coeffs[N - i]; // c(x) = c(x) * x
- }
- f.coeffs[N] = 0;
- c.coeffs[0] = 0;
- k++;
- if (f.equalsZero())
- {
- return null; // not invertible
- }
- }
- if (f.equalsOne())
- {
- break;
- }
- if (f.degree() < g.degree())
- {
- // exchange f and g
- IntegerPolynomial temp = f;
- f = g;
- g = temp;
- // exchange b and c
- temp = b;
- b = c;
- c = temp;
- }
- f.add(g, 2);
- b.add(c, 2);
- }
-
- if (b.coeffs[N] != 0)
- {
- return null;
- }
- // Fq(x) = x^(N-k) * b(x)
- IntegerPolynomial Fq = new IntegerPolynomial(N);
- int j = 0;
- k %= N;
- for (int i = N - 1; i >= 0; i--)
- {
- j = i - k;
- if (j < 0)
- {
- j += N;
- }
- Fq.coeffs[j] = b.coeffs[i];
- }
-
- return mod2ToModq(Fq, q);
- }
-
- /**
- * Computes the inverse mod q from the inverse mod 2
- *
- * @param Fq
- * @param q
- * @return The inverse of this polynomial mod q
- */
- private IntegerPolynomial mod2ToModq(IntegerPolynomial Fq, int q)
- {
- if (Util.is64BitJVM() && q == 2048)
- {
- LongPolynomial2 thisLong = new LongPolynomial2(this);
- LongPolynomial2 FqLong = new LongPolynomial2(Fq);
- int v = 2;
- while (v < q)
- {
- v *= 2;
- LongPolynomial2 temp = (LongPolynomial2)FqLong.clone();
- temp.mult2And(v - 1);
- FqLong = thisLong.mult(FqLong).mult(FqLong);
- temp.subAnd(FqLong, v - 1);
- FqLong = temp;
- }
- return FqLong.toIntegerPolynomial();
- }
- else
- {
- int v = 2;
- while (v < q)
- {
- v *= 2;
- IntegerPolynomial temp = new IntegerPolynomial(Arrays.copyOf(Fq.coeffs, Fq.coeffs.length));
- temp.mult2(v);
- Fq = mult(Fq, v).mult(Fq, v);
- temp.sub(Fq, v);
- Fq = temp;
- }
- return Fq;
- }
- }
-
- /**
- * Computes the inverse mod 3.
- * Returns <code>null</code> if the polynomial is not invertible.
- *
- * @return a new polynomial
- */
- public IntegerPolynomial invertF3()
- {
- int N = coeffs.length;
- int k = 0;
- IntegerPolynomial b = new IntegerPolynomial(N + 1);
- b.coeffs[0] = 1;
- IntegerPolynomial c = new IntegerPolynomial(N + 1);
- IntegerPolynomial f = new IntegerPolynomial(N + 1);
- f.coeffs = Arrays.copyOf(coeffs, N + 1);
- f.modPositive(3);
- // set g(x) = x^N − 1
- IntegerPolynomial g = new IntegerPolynomial(N + 1);
- g.coeffs[0] = -1;
- g.coeffs[N] = 1;
- while (true)
- {
- while (f.coeffs[0] == 0)
- {
- for (int i = 1; i <= N; i++)
- {
- f.coeffs[i - 1] = f.coeffs[i]; // f(x) = f(x) / x
- c.coeffs[N + 1 - i] = c.coeffs[N - i]; // c(x) = c(x) * x
- }
- f.coeffs[N] = 0;
- c.coeffs[0] = 0;
- k++;
- if (f.equalsZero())
- {
- return null; // not invertible
- }
- }
- if (f.equalsAbsOne())
- {
- break;
- }
- if (f.degree() < g.degree())
- {
- // exchange f and g
- IntegerPolynomial temp = f;
- f = g;
- g = temp;
- // exchange b and c
- temp = b;
- b = c;
- c = temp;
- }
- if (f.coeffs[0] == g.coeffs[0])
- {
- f.sub(g, 3);
- b.sub(c, 3);
- }
- else
- {
- f.add(g, 3);
- b.add(c, 3);
- }
- }
-
- if (b.coeffs[N] != 0)
- {
- return null;
- }
- // Fp(x) = [+-] x^(N-k) * b(x)
- IntegerPolynomial Fp = new IntegerPolynomial(N);
- int j = 0;
- k %= N;
- for (int i = N - 1; i >= 0; i--)
- {
- j = i - k;
- if (j < 0)
- {
- j += N;
- }
- Fp.coeffs[j] = f.coeffs[0] * b.coeffs[i];
- }
-
- Fp.ensurePositive(3);
- return Fp;
- }
-
- /**
- * Resultant of this polynomial with <code>x^n-1</code> using a probabilistic algorithm.
- * <p>
- * Unlike EESS, this implementation does not compute all resultants modulo primes
- * such that their product exceeds the maximum possible resultant, but rather stops
- * when <code>NUM_EQUAL_RESULTANTS</code> consecutive modular resultants are equal.<br>
- * This means the return value may be incorrect. Experiments show this happens in
- * about 1 out of 100 cases when <code>N=439</code> and <code>NUM_EQUAL_RESULTANTS=2</code>,
- * so the likelyhood of leaving the loop too early is <code>(1/100)^(NUM_EQUAL_RESULTANTS-1)</code>.
- * <p>
- * Because of the above, callers must verify the output and try a different polynomial if necessary.
- *
- * @return <code>(rho, res)</code> satisfying <code>res = rho*this + t*(x^n-1)</code> for some integer <code>t</code>.
- */
- public Resultant resultant()
- {
- int N = coeffs.length;
-
- // Compute resultants modulo prime numbers. Continue until NUM_EQUAL_RESULTANTS consecutive modular resultants are equal.
- LinkedList<ModularResultant> modResultants = new LinkedList<ModularResultant>();
- BigInteger prime = null;
- BigInteger pProd = Constants.BIGINT_ONE;
- BigInteger res = Constants.BIGINT_ONE;
- int numEqual = 1; // number of consecutive modular resultants equal to each other
- Iterator<BigInteger> primes = BIGINT_PRIMES.iterator();
- while (true)
- {
- prime = primes.hasNext() ? primes.next() : prime.nextProbablePrime();
- ModularResultant crr = resultant(prime.intValue());
- modResultants.add(crr);
-
- BigInteger temp = pProd.multiply(prime);
- BigIntEuclidean er = BigIntEuclidean.calculate(prime, pProd);
- BigInteger resPrev = res;
- res = res.multiply(er.x.multiply(prime));
- BigInteger res2 = crr.res.multiply(er.y.multiply(pProd));
- res = res.add(res2).mod(temp);
- pProd = temp;
-
- BigInteger pProd2 = pProd.divide(BigInteger.valueOf(2));
- BigInteger pProd2n = pProd2.negate();
- if (res.compareTo(pProd2) > 0)
- {
- res = res.subtract(pProd);
- }
- else if (res.compareTo(pProd2n) < 0)
- {
- res = res.add(pProd);
- }
-
- if (res.equals(resPrev))
- {
- numEqual++;
- if (numEqual >= NUM_EQUAL_RESULTANTS)
- {
- break;
- }
- }
- else
- {
- numEqual = 1;
- }
- }
-
- // Combine modular rho's to obtain the final rho.
- // For efficiency, first combine all pairs of small resultants to bigger resultants,
- // then combine pairs of those, etc. until only one is left.
- while (modResultants.size() > 1)
- {
- ModularResultant modRes1 = modResultants.removeFirst();
- ModularResultant modRes2 = modResultants.removeFirst();
- ModularResultant modRes3 = ModularResultant.combineRho(modRes1, modRes2);
- modResultants.addLast(modRes3);
- }
- BigIntPolynomial rhoP = modResultants.getFirst().rho;
-
- BigInteger pProd2 = pProd.divide(BigInteger.valueOf(2));
- BigInteger pProd2n = pProd2.negate();
- if (res.compareTo(pProd2) > 0)
- {
- res = res.subtract(pProd);
- }
- if (res.compareTo(pProd2n) < 0)
- {
- res = res.add(pProd);
- }
-
- for (int i = 0; i < N; i++)
- {
- BigInteger c = rhoP.coeffs[i];
- if (c.compareTo(pProd2) > 0)
- {
- rhoP.coeffs[i] = c.subtract(pProd);
- }
- if (c.compareTo(pProd2n) < 0)
- {
- rhoP.coeffs[i] = c.add(pProd);
- }
- }
-
- return new Resultant(rhoP, res);
- }
-
- /**
- * Multithreaded version of {@link #resultant()}.
- *
- * @return <code>(rho, res)</code> satisfying <code>res = rho*this + t*(x^n-1)</code> for some integer <code>t</code>.
- */
- public Resultant resultantMultiThread()
- {
- int N = coeffs.length;
-
- // upper bound for resultant(f, g) = ||f, 2||^deg(g) * ||g, 2||^deg(f) = squaresum(f)^(N/2) * 2^(deg(f)/2) because g(x)=x^N-1
- // see http://jondalon.mathematik.uni-osnabrueck.de/staff/phpages/brunsw/CompAlg.pdf chapter 3
- BigInteger max = squareSum().pow((N + 1) / 2);
- max = max.multiply(BigInteger.valueOf(2).pow((degree() + 1) / 2));
- BigInteger max2 = max.multiply(BigInteger.valueOf(2));
-
- // compute resultants modulo prime numbers
- BigInteger prime = BigInteger.valueOf(10000);
- BigInteger pProd = Constants.BIGINT_ONE;
- LinkedBlockingQueue<Future<ModularResultant>> resultantTasks = new LinkedBlockingQueue<Future<ModularResultant>>();
- Iterator<BigInteger> primes = BIGINT_PRIMES.iterator();
- ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
- while (pProd.compareTo(max2) < 0)
- {
- if (primes.hasNext())
- {
- prime = primes.next();
- }
- else
- {
- prime = prime.nextProbablePrime();
- }
- Future<ModularResultant> task = executor.submit(new ModResultantTask(prime.intValue()));
- resultantTasks.add(task);
- pProd = pProd.multiply(prime);
- }
-
- // Combine modular resultants to obtain the resultant.
- // For efficiency, first combine all pairs of small resultants to bigger resultants,
- // then combine pairs of those, etc. until only one is left.
- ModularResultant overallResultant = null;
- while (!resultantTasks.isEmpty())
- {
- try
- {
- Future<ModularResultant> modRes1 = resultantTasks.take();
- Future<ModularResultant> modRes2 = resultantTasks.poll();
- if (modRes2 == null)
- {
- // modRes1 is the only one left
- overallResultant = modRes1.get();
- break;
- }
- Future<ModularResultant> newTask = executor.submit(new CombineTask(modRes1.get(), modRes2.get()));
- resultantTasks.add(newTask);
- }
- catch (Exception e)
- {
- throw new IllegalStateException(e.toString());
- }
- }
- executor.shutdown();
- BigInteger res = overallResultant.res;
- BigIntPolynomial rhoP = overallResultant.rho;
-
- BigInteger pProd2 = pProd.divide(BigInteger.valueOf(2));
- BigInteger pProd2n = pProd2.negate();
-
- if (res.compareTo(pProd2) > 0)
- {
- res = res.subtract(pProd);
- }
- if (res.compareTo(pProd2n) < 0)
- {
- res = res.add(pProd);
- }
-
- for (int i = 0; i < N; i++)
- {
- BigInteger c = rhoP.coeffs[i];
- if (c.compareTo(pProd2) > 0)
- {
- rhoP.coeffs[i] = c.subtract(pProd);
- }
- if (c.compareTo(pProd2n) < 0)
- {
- rhoP.coeffs[i] = c.add(pProd);
- }
- }
-
- return new Resultant(rhoP, res);
- }
-
- /**
- * Resultant of this polynomial with <code>x^n-1 mod p</code>.
- *
- * @return <code>(rho, res)</code> satisfying <code>res = rho*this + t*(x^n-1) mod p</code> for some integer <code>t</code>.
- */
- public ModularResultant resultant(int p)
- {
- // Add a coefficient as the following operations involve polynomials of degree deg(f)+1
- int[] fcoeffs = Arrays.copyOf(coeffs, coeffs.length + 1);
- IntegerPolynomial f = new IntegerPolynomial(fcoeffs);
- int N = fcoeffs.length;
-
- IntegerPolynomial a = new IntegerPolynomial(N);
- a.coeffs[0] = -1;
- a.coeffs[N - 1] = 1;
- IntegerPolynomial b = new IntegerPolynomial(f.coeffs);
- IntegerPolynomial v1 = new IntegerPolynomial(N);
- IntegerPolynomial v2 = new IntegerPolynomial(N);
- v2.coeffs[0] = 1;
- int da = N - 1;
- int db = b.degree();
- int ta = da;
- int c = 0;
- int r = 1;
- while (db > 0)
- {
- c = Util.invert(b.coeffs[db], p);
- c = (c * a.coeffs[da]) % p;
- a.multShiftSub(b, c, da - db, p);
- v1.multShiftSub(v2, c, da - db, p);
-
- da = a.degree();
- if (da < db)
- {
- r *= Util.pow(b.coeffs[db], ta - da, p);
- r %= p;
- if (ta % 2 == 1 && db % 2 == 1)
- {
- r = (-r) % p;
- }
- IntegerPolynomial temp = a;
- a = b;
- b = temp;
- int tempdeg = da;
- da = db;
- temp = v1;
- v1 = v2;
- v2 = temp;
- ta = db;
- db = tempdeg;
- }
- }
- r *= Util.pow(b.coeffs[0], da, p);
- r %= p;
- c = Util.invert(b.coeffs[0], p);
- v2.mult(c);
- v2.mod(p);
- v2.mult(r);
- v2.mod(p);
-
- // drop the highest coefficient so #coeffs matches the original input
- v2.coeffs = Arrays.copyOf(v2.coeffs, v2.coeffs.length - 1);
- return new ModularResultant(new BigIntPolynomial(v2), BigInteger.valueOf(r), BigInteger.valueOf(p));
- }
-
- /**
- * Computes <code>this-b*c*(x^k) mod p</code> and stores the result in this polynomial.<br/>
- * See steps 4a,4b in EESS algorithm 2.2.7.1.
- *
- * @param b
- * @param c
- * @param k
- * @param p
- */
- private void multShiftSub(IntegerPolynomial b, int c, int k, int p)
- {
- int N = coeffs.length;
- for (int i = k; i < N; i++)
- {
- coeffs[i] = (coeffs[i] - b.coeffs[i - k] * c) % p;
- }
- }
-
- /**
- * Adds the squares of all coefficients.
- *
- * @return the sum of squares
- */
- private BigInteger squareSum()
- {
- BigInteger sum = Constants.BIGINT_ZERO;
- for (int i = 0; i < coeffs.length; i++)
- {
- sum = sum.add(BigInteger.valueOf(coeffs[i] * coeffs[i]));
- }
- return sum;
- }
-
- /**
- * Returns the degree of the polynomial
- *
- * @return the degree
- */
- int degree()
- {
- int degree = coeffs.length - 1;
- while (degree > 0 && coeffs[degree] == 0)
- {
- degree--;
- }
- return degree;
- }
-
- /**
- * Adds another polynomial which can have a different number of coefficients,
- * and takes the coefficient values mod <code>modulus</code>.
- *
- * @param b another polynomial
- */
- public void add(IntegerPolynomial b, int modulus)
- {
- add(b);
- mod(modulus);
- }
-
- /**
- * Adds another polynomial which can have a different number of coefficients.
- *
- * @param b another polynomial
- */
- public void add(IntegerPolynomial b)
- {
- if (b.coeffs.length > coeffs.length)
- {
- coeffs = Arrays.copyOf(coeffs, b.coeffs.length);
- }
- for (int i = 0; i < b.coeffs.length; i++)
- {
- coeffs[i] += b.coeffs[i];
- }
- }
-
- /**
- * Subtracts another polynomial which can have a different number of coefficients,
- * and takes the coefficient values mod <code>modulus</code>.
- *
- * @param b another polynomial
- */
- public void sub(IntegerPolynomial b, int modulus)
- {
- sub(b);
- mod(modulus);
- }
-
- /**
- * Subtracts another polynomial which can have a different number of coefficients.
- *
- * @param b another polynomial
- */
- public void sub(IntegerPolynomial b)
- {
- if (b.coeffs.length > coeffs.length)
- {
- coeffs = Arrays.copyOf(coeffs, b.coeffs.length);
- }
- for (int i = 0; i < b.coeffs.length; i++)
- {
- coeffs[i] -= b.coeffs[i];
- }
- }
-
- /**
- * Subtracts a <code>int</code> from each coefficient. Does not return a new polynomial but modifies this polynomial.
- *
- * @param b
- */
- void sub(int b)
- {
- for (int i = 0; i < coeffs.length; i++)
- {
- coeffs[i] -= b;
- }
- }
-
- /**
- * Multiplies each coefficient by a <code>int</code>. Does not return a new polynomial but modifies this polynomial.
- *
- * @param factor
- */
- public void mult(int factor)
- {
- for (int i = 0; i < coeffs.length; i++)
- {
- coeffs[i] *= factor;
- }
- }
-
- /**
- * Multiplies each coefficient by a 2 and applies a modulus. Does not return a new polynomial but modifies this polynomial.
- *
- * @param modulus a modulus
- */
- private void mult2(int modulus)
- {
- for (int i = 0; i < coeffs.length; i++)
- {
- coeffs[i] *= 2;
- coeffs[i] %= modulus;
- }
- }
-
- /**
- * Multiplies each coefficient by a 2 and applies a modulus. Does not return a new polynomial but modifies this polynomial.
- *
- * @param modulus a modulus
- */
- public void mult3(int modulus)
- {
- for (int i = 0; i < coeffs.length; i++)
- {
- coeffs[i] *= 3;
- coeffs[i] %= modulus;
- }
- }
-
- /**
- * Divides each coefficient by <code>k</code> and rounds to the nearest integer. Does not return a new polynomial but modifies this polynomial.
- *
- * @param k the divisor
- */
- public void div(int k)
- {
- int k2 = (k + 1) / 2;
- for (int i = 0; i < coeffs.length; i++)
- {
- coeffs[i] += coeffs[i] > 0 ? k2 : -k2;
- coeffs[i] /= k;
- }
- }
-
- /**
- * Takes each coefficient modulo 3 such that all coefficients are ternary.
- */
- public void mod3()
- {
- for (int i = 0; i < coeffs.length; i++)
- {
- coeffs[i] %= 3;
- if (coeffs[i] > 1)
- {
- coeffs[i] -= 3;
- }
- if (coeffs[i] < -1)
- {
- coeffs[i] += 3;
- }
- }
- }
-
- /**
- * Ensures all coefficients are between 0 and <code>modulus-1</code>
- *
- * @param modulus a modulus
- */
- public void modPositive(int modulus)
- {
- mod(modulus);
- ensurePositive(modulus);
- }
-
- /**
- * Reduces all coefficients to the interval [-modulus/2, modulus/2)
- */
- void modCenter(int modulus)
- {
- mod(modulus);
- for (int j = 0; j < coeffs.length; j++)
- {
- while (coeffs[j] < modulus / 2)
- {
- coeffs[j] += modulus;
- }
- while (coeffs[j] >= modulus / 2)
- {
- coeffs[j] -= modulus;
- }
- }
- }
-
- /**
- * Takes each coefficient modulo <code>modulus</code>.
- */
- public void mod(int modulus)
- {
- for (int i = 0; i < coeffs.length; i++)
- {
- coeffs[i] %= modulus;
- }
- }
-
- /**
- * Adds <code>modulus</code> until all coefficients are above 0.
- *
- * @param modulus a modulus
- */
- public void ensurePositive(int modulus)
- {
- for (int i = 0; i < coeffs.length; i++)
- {
- while (coeffs[i] < 0)
- {
- coeffs[i] += modulus;
- }
- }
- }
-
- /**
- * Computes the centered euclidean norm of the polynomial.
- *
- * @param q a modulus
- * @return the centered norm
- */
- public long centeredNormSq(int q)
- {
- int N = coeffs.length;
- IntegerPolynomial p = (IntegerPolynomial)clone();
- p.shiftGap(q);
-
- long sum = 0;
- long sqSum = 0;
- for (int i = 0; i != p.coeffs.length; i++)
- {
- int c = p.coeffs[i];
- sum += c;
- sqSum += c * c;
- }
-
- long centeredNormSq = sqSum - sum * sum / N;
- return centeredNormSq;
- }
-
- /**
- * Shifts all coefficients so the largest gap is centered around <code>-q/2</code>.
- *
- * @param q a modulus
- */
- void shiftGap(int q)
- {
- modCenter(q);
-
- int[] sorted = Arrays.clone(coeffs);
-
- sort(sorted);
-
- int maxrange = 0;
- int maxrangeStart = 0;
- for (int i = 0; i < sorted.length - 1; i++)
- {
- int range = sorted[i + 1] - sorted[i];
- if (range > maxrange)
- {
- maxrange = range;
- maxrangeStart = sorted[i];
- }
- }
-
- int pmin = sorted[0];
- int pmax = sorted[sorted.length - 1];
-
- int j = q - pmax + pmin;
- int shift;
- if (j > maxrange)
- {
- shift = (pmax + pmin) / 2;
- }
- else
- {
- shift = maxrangeStart + maxrange / 2 + q / 2;
- }
-
- sub(shift);
- }
-
- private void sort(int[] ints)
- {
- boolean swap = true;
-
- while (swap)
- {
- swap = false;
- for (int i = 0; i != ints.length - 1; i++)
- {
- if (ints[i] > ints[i+1])
- {
- int tmp = ints[i];
- ints[i] = ints[i+1];
- ints[i+1] = tmp;
- swap = true;
- }
- }
- }
- }
-
- /**
- * Shifts the values of all coefficients to the interval <code>[-q/2, q/2]</code>.
- *
- * @param q a modulus
- */
- public void center0(int q)
- {
- for (int i = 0; i < coeffs.length; i++)
- {
- while (coeffs[i] < -q / 2)
- {
- coeffs[i] += q;
- }
- while (coeffs[i] > q / 2)
- {
- coeffs[i] -= q;
- }
- }
- }
-
- /**
- * Returns the sum of all coefficients, i.e. evaluates the polynomial at 0.
- *
- * @return the sum of all coefficients
- */
- public int sumCoeffs()
- {
- int sum = 0;
- for (int i = 0; i < coeffs.length; i++)
- {
- sum += coeffs[i];
- }
- return sum;
- }
-
- /**
- * Tests if <code>p(x) = 0</code>.
- *
- * @return true iff all coefficients are zeros
- */
- private boolean equalsZero()
- {
- for (int i = 0; i < coeffs.length; i++)
- {
- if (coeffs[i] != 0)
- {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Tests if <code>p(x) = 1</code>.
- *
- * @return true iff all coefficients are equal to zero, except for the lowest coefficient which must equal 1
- */
- public boolean equalsOne()
- {
- for (int i = 1; i < coeffs.length; i++)
- {
- if (coeffs[i] != 0)
- {
- return false;
- }
- }
- return coeffs[0] == 1;
- }
-
- /**
- * Tests if <code>|p(x)| = 1</code>.
- *
- * @return true iff all coefficients are equal to zero, except for the lowest coefficient which must equal 1 or -1
- */
- private boolean equalsAbsOne()
- {
- for (int i = 1; i < coeffs.length; i++)
- {
- if (coeffs[i] != 0)
- {
- return false;
- }
- }
- return Math.abs(coeffs[0]) == 1;
- }
-
- /**
- * Counts the number of coefficients equal to an integer
- *
- * @param value an integer
- * @return the number of coefficients equal to <code>value</code>
- */
- public int count(int value)
- {
- int count = 0;
- for (int i = 0; i != coeffs.length; i++)
- {
- if (coeffs[i] == value)
- {
- count++;
- }
- }
- return count;
- }
-
- /**
- * Multiplication by <code>X</code> in <code>Z[X]/Z[X^n-1]</code>.
- */
- public void rotate1()
- {
- int clast = coeffs[coeffs.length - 1];
- for (int i = coeffs.length - 1; i > 0; i--)
- {
- coeffs[i] = coeffs[i - 1];
- }
- coeffs[0] = clast;
- }
-
- public void clear()
- {
- for (int i = 0; i < coeffs.length; i++)
- {
- coeffs[i] = 0;
- }
- }
-
- public IntegerPolynomial toIntegerPolynomial()
- {
- return (IntegerPolynomial)clone();
- }
-
- public Object clone()
- {
- return new IntegerPolynomial(coeffs.clone());
- }
-
- public boolean equals(Object obj)
- {
- if (obj instanceof IntegerPolynomial)
- {
- return Arrays.areEqual(coeffs, ((IntegerPolynomial)obj).coeffs);
- }
- else
- {
- return false;
- }
- }
-
- /**
- * Calls {@link IntegerPolynomial#resultant(int)
- */
- private class ModResultantTask
- implements Callable<ModularResultant>
- {
- private int modulus;
-
- private ModResultantTask(int modulus)
- {
- this.modulus = modulus;
- }
-
- public ModularResultant call()
- {
- return resultant(modulus);
- }
- }
-
- /**
- * Calls {@link ModularResultant#combineRho(ModularResultant, ModularResultant)
- */
- private class CombineTask
- implements Callable<ModularResultant>
- {
- private ModularResultant modRes1;
- private ModularResultant modRes2;
-
- private CombineTask(ModularResultant modRes1, ModularResultant modRes2)
- {
- this.modRes1 = modRes1;
- this.modRes2 = modRes2;
- }
-
- public ModularResultant call()
- {
- return ModularResultant.combineRho(modRes1, modRes2);
- }
- }
-}
diff --git a/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/LongPolynomial2.java b/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/LongPolynomial2.java
deleted file mode 100644
index d71615a..0000000
--- a/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/LongPolynomial2.java
+++ /dev/null
@@ -1,255 +0,0 @@
-package org.bouncycastle.pqc.math.ntru.polynomial;
-
-import org.bouncycastle.util.Arrays;
-
-/**
- * A polynomial class that combines two coefficients into one <code>long</code> value for
- * faster multiplication in 64 bit environments.<br>
- * Coefficients can be between 0 and 2047 and are stored in pairs in the bits 0..10 and 24..34 of a <code>long</code> number.
- */
-public class LongPolynomial2
-{
- private long[] coeffs; // each representing two coefficients in the original IntegerPolynomial
- private int numCoeffs;
-
- /**
- * Constructs a <code>LongPolynomial2</code> from a <code>IntegerPolynomial</code>. The two polynomials are independent of each other.
- *
- * @param p the original polynomial. Coefficients must be between 0 and 2047.
- */
- public LongPolynomial2(IntegerPolynomial p)
- {
- numCoeffs = p.coeffs.length;
- coeffs = new long[(numCoeffs + 1) / 2];
- int idx = 0;
- for (int pIdx = 0; pIdx < numCoeffs; )
- {
- int c0 = p.coeffs[pIdx++];
- while (c0 < 0)
- {
- c0 += 2048;
- }
- long c1 = pIdx < numCoeffs ? p.coeffs[pIdx++] : 0;
- while (c1 < 0)
- {
- c1 += 2048;
- }
- coeffs[idx] = c0 + (c1 << 24);
- idx++;
- }
- }
-
- private LongPolynomial2(long[] coeffs)
- {
- this.coeffs = coeffs;
- }
-
- private LongPolynomial2(int N)
- {
- coeffs = new long[N];
- }
-
- /**
- * Multiplies the polynomial with another, taking the indices mod N and the values mod 2048.
- */
- public LongPolynomial2 mult(LongPolynomial2 poly2)
- {
- int N = coeffs.length;
- if (poly2.coeffs.length != N || numCoeffs != poly2.numCoeffs)
- {
- throw new IllegalArgumentException("Number of coefficients must be the same");
- }
-
- LongPolynomial2 c = multRecursive(poly2);
-
- if (c.coeffs.length > N)
- {
- if (numCoeffs % 2 == 0)
- {
- for (int k = N; k < c.coeffs.length; k++)
- {
- c.coeffs[k - N] = (c.coeffs[k - N] + c.coeffs[k]) & 0x7FF0007FFL;
- }
- c.coeffs = Arrays.copyOf(c.coeffs, N);
- }
- else
- {
- for (int k = N; k < c.coeffs.length; k++)
- {
- c.coeffs[k - N] = c.coeffs[k - N] + (c.coeffs[k - 1] >> 24);
- c.coeffs[k - N] = c.coeffs[k - N] + ((c.coeffs[k] & 2047) << 24);
- c.coeffs[k - N] &= 0x7FF0007FFL;
- }
- c.coeffs = Arrays.copyOf(c.coeffs, N);
- c.coeffs[c.coeffs.length - 1] &= 2047;
- }
- }
-
- c = new LongPolynomial2(c.coeffs);
- c.numCoeffs = numCoeffs;
- return c;
- }
-
- public IntegerPolynomial toIntegerPolynomial()
- {
- int[] intCoeffs = new int[numCoeffs];
- int uIdx = 0;
- for (int i = 0; i < coeffs.length; i++)
- {
- intCoeffs[uIdx++] = (int)(coeffs[i] & 2047);
- if (uIdx < numCoeffs)
- {
- intCoeffs[uIdx++] = (int)((coeffs[i] >> 24) & 2047);
- }
- }
- return new IntegerPolynomial(intCoeffs);
- }
-
- /**
- * Karazuba multiplication
- */
- private LongPolynomial2 multRecursive(LongPolynomial2 poly2)
- {
- long[] a = coeffs;
- long[] b = poly2.coeffs;
-
- int n = poly2.coeffs.length;
- if (n <= 32)
- {
- int cn = 2 * n;
- LongPolynomial2 c = new LongPolynomial2(new long[cn]);
- for (int k = 0; k < cn; k++)
- {
- for (int i = Math.max(0, k - n + 1); i <= Math.min(k, n - 1); i++)
- {
- long c0 = a[k - i] * b[i];
- long cu = c0 & 0x7FF000000L + (c0 & 2047);
- long co = (c0 >>> 48) & 2047;
-
- c.coeffs[k] = (c.coeffs[k] + cu) & 0x7FF0007FFL;
- c.coeffs[k + 1] = (c.coeffs[k + 1] + co) & 0x7FF0007FFL;
- }
- }
- return c;
- }
- else
- {
- int n1 = n / 2;
-
- LongPolynomial2 a1 = new LongPolynomial2(Arrays.copyOf(a, n1));
- LongPolynomial2 a2 = new LongPolynomial2(Arrays.copyOfRange(a, n1, n));
- LongPolynomial2 b1 = new LongPolynomial2(Arrays.copyOf(b, n1));
- LongPolynomial2 b2 = new LongPolynomial2(Arrays.copyOfRange(b, n1, n));
-
- LongPolynomial2 A = (LongPolynomial2)a1.clone();
- A.add(a2);
- LongPolynomial2 B = (LongPolynomial2)b1.clone();
- B.add(b2);
-
- LongPolynomial2 c1 = a1.multRecursive(b1);
- LongPolynomial2 c2 = a2.multRecursive(b2);
- LongPolynomial2 c3 = A.multRecursive(B);
- c3.sub(c1);
- c3.sub(c2);
-
- LongPolynomial2 c = new LongPolynomial2(2 * n);
- for (int i = 0; i < c1.coeffs.length; i++)
- {
- c.coeffs[i] = c1.coeffs[i] & 0x7FF0007FFL;
- }
- for (int i = 0; i < c3.coeffs.length; i++)
- {
- c.coeffs[n1 + i] = (c.coeffs[n1 + i] + c3.coeffs[i]) & 0x7FF0007FFL;
- }
- for (int i = 0; i < c2.coeffs.length; i++)
- {
- c.coeffs[2 * n1 + i] = (c.coeffs[2 * n1 + i] + c2.coeffs[i]) & 0x7FF0007FFL;
- }
- return c;
- }
- }
-
- /**
- * Adds another polynomial which can have a different number of coefficients.
- *
- * @param b another polynomial
- */
- private void add(LongPolynomial2 b)
- {
- if (b.coeffs.length > coeffs.length)
- {
- coeffs = Arrays.copyOf(coeffs, b.coeffs.length);
- }
- for (int i = 0; i < b.coeffs.length; i++)
- {
- coeffs[i] = (coeffs[i] + b.coeffs[i]) & 0x7FF0007FFL;
- }
- }
-
- /**
- * Subtracts another polynomial which can have a different number of coefficients.
- *
- * @param b another polynomial
- */
- private void sub(LongPolynomial2 b)
- {
- if (b.coeffs.length > coeffs.length)
- {
- coeffs = Arrays.copyOf(coeffs, b.coeffs.length);
- }
- for (int i = 0; i < b.coeffs.length; i++)
- {
- coeffs[i] = (0x0800000800000L + coeffs[i] - b.coeffs[i]) & 0x7FF0007FFL;
- }
- }
-
- /**
- * Subtracts another polynomial which must have the same number of coefficients,
- * and applies an AND mask to the upper and lower halves of each coefficients.
- *
- * @param b another polynomial
- * @param mask a bit mask less than 2048 to apply to each 11-bit coefficient
- */
- public void subAnd(LongPolynomial2 b, int mask)
- {
- long longMask = (((long)mask) << 24) + mask;
- for (int i = 0; i < b.coeffs.length; i++)
- {
- coeffs[i] = (0x0800000800000L + coeffs[i] - b.coeffs[i]) & longMask;
- }
- }
-
- /**
- * Multiplies this polynomial by 2 and applies an AND mask to the upper and
- * lower halves of each coefficients.
- *
- * @param mask a bit mask less than 2048 to apply to each 11-bit coefficient
- */
- public void mult2And(int mask)
- {
- long longMask = (((long)mask) << 24) + mask;
- for (int i = 0; i < coeffs.length; i++)
- {
- coeffs[i] = (coeffs[i] << 1) & longMask;
- }
- }
-
- public Object clone()
- {
- LongPolynomial2 p = new LongPolynomial2(coeffs.clone());
- p.numCoeffs = numCoeffs;
- return p;
- }
-
- public boolean equals(Object obj)
- {
- if (obj instanceof LongPolynomial2)
- {
- return Arrays.areEqual(coeffs, ((LongPolynomial2)obj).coeffs);
- }
- else
- {
- return false;
- }
- }
-}
diff --git a/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/LongPolynomial5.java b/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/LongPolynomial5.java
deleted file mode 100644
index c804cc8..0000000
--- a/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/LongPolynomial5.java
+++ /dev/null
@@ -1,149 +0,0 @@
-package org.bouncycastle.pqc.math.ntru.polynomial;
-
-import org.bouncycastle.util.Arrays;
-
-/**
- * A polynomial class that combines five coefficients into one <code>long</code> value for
- * faster multiplication by a ternary polynomial.<br>
- * Coefficients can be between 0 and 2047 and are stored in bits 0..11, 12..23, ..., 48..59 of a <code>long</code> number.
- */
-public class LongPolynomial5
-{
- private long[] coeffs; // groups of 5 coefficients
- private int numCoeffs;
-
- /**
- * Constructs a <code>LongPolynomial5</code> from a <code>IntegerPolynomial</code>. The two polynomials are independent of each other.
- *
- * @param p the original polynomial. Coefficients must be between 0 and 2047.
- */
- public LongPolynomial5(IntegerPolynomial p)
- {
- numCoeffs = p.coeffs.length;
-
- coeffs = new long[(numCoeffs + 4) / 5];
- int cIdx = 0;
- int shift = 0;
- for (int i = 0; i < numCoeffs; i++)
- {
- coeffs[cIdx] |= ((long)p.coeffs[i]) << shift;
- shift += 12;
- if (shift >= 60)
- {
- shift = 0;
- cIdx++;
- }
- }
- }
-
- private LongPolynomial5(long[] coeffs, int numCoeffs)
- {
- this.coeffs = coeffs;
- this.numCoeffs = numCoeffs;
- }
-
- /**
- * Multiplies the polynomial with a <code>TernaryPolynomial</code>, taking the indices mod N and the values mod 2048.
- */
- public LongPolynomial5 mult(TernaryPolynomial poly2)
- {
- long[][] prod = new long[5][coeffs.length + (poly2.size() + 4) / 5 - 1]; // intermediate results, the subarrays are shifted by 0,...,4 coefficients
-
- // multiply ones
- int[] ones = poly2.getOnes();
- for (int idx = 0; idx != ones.length; idx++)
- {
- int pIdx = ones[idx];
- int cIdx = pIdx / 5;
- int m = pIdx - cIdx * 5; // m = pIdx % 5
- for (int i = 0; i < coeffs.length; i++)
- {
- prod[m][cIdx] = (prod[m][cIdx] + coeffs[i]) & 0x7FF7FF7FF7FF7FFL;
- cIdx++;
- }
- }
-
- // multiply negative ones
- int[] negOnes = poly2.getNegOnes();
- for (int idx = 0; idx != negOnes.length; idx++)
- {
- int pIdx = negOnes[idx];
- int cIdx = pIdx / 5;
- int m = pIdx - cIdx * 5; // m = pIdx % 5
- for (int i = 0; i < coeffs.length; i++)
- {
- prod[m][cIdx] = (0x800800800800800L + prod[m][cIdx] - coeffs[i]) & 0x7FF7FF7FF7FF7FFL;
- cIdx++;
- }
- }
-
- // combine shifted coefficients (5 arrays) into a single array of length prod[*].length+1
- long[] cCoeffs = Arrays.copyOf(prod[0], prod[0].length + 1);
- for (int m = 1; m <= 4; m++)
- {
- int shift = m * 12;
- int shift60 = 60 - shift;
- long mask = (1L << shift60) - 1;
- int pLen = prod[m].length;
- for (int i = 0; i < pLen; i++)
- {
- long upper, lower;
- upper = prod[m][i] >> shift60;
- lower = prod[m][i] & mask;
-
- cCoeffs[i] = (cCoeffs[i] + (lower << shift)) & 0x7FF7FF7FF7FF7FFL;
- int nextIdx = i + 1;
- cCoeffs[nextIdx] = (cCoeffs[nextIdx] + upper) & 0x7FF7FF7FF7FF7FFL;
- }
- }
-
- // reduce indices of cCoeffs modulo numCoeffs
- int shift = 12 * (numCoeffs % 5);
- for (int cIdx = coeffs.length - 1; cIdx < cCoeffs.length; cIdx++)
- {
- long iCoeff; // coefficient to shift into the [0..numCoeffs-1] range
- int newIdx;
- if (cIdx == coeffs.length - 1)
- {
- iCoeff = numCoeffs == 5 ? 0 : cCoeffs[cIdx] >> shift;
- newIdx = 0;
- }
- else
- {
- iCoeff = cCoeffs[cIdx];
- newIdx = cIdx * 5 - numCoeffs;
- }
-
- int base = newIdx / 5;
- int m = newIdx - base * 5; // m = newIdx % 5
- long lower = iCoeff << (12 * m);
- long upper = iCoeff >> (12 * (5 - m));
- cCoeffs[base] = (cCoeffs[base] + lower) & 0x7FF7FF7FF7FF7FFL;
- int base1 = base + 1;
- if (base1 < coeffs.length)
- {
- cCoeffs[base1] = (cCoeffs[base1] + upper) & 0x7FF7FF7FF7FF7FFL;
- }
- }
-
- return new LongPolynomial5(cCoeffs, numCoeffs);
- }
-
- public IntegerPolynomial toIntegerPolynomial()
- {
- int[] intCoeffs = new int[numCoeffs];
- int cIdx = 0;
- int shift = 0;
- for (int i = 0; i < numCoeffs; i++)
- {
- intCoeffs[i] = (int)((coeffs[cIdx] >> shift) & 2047);
- shift += 12;
- if (shift >= 60)
- {
- shift = 0;
- cIdx++;
- }
- }
- return new IntegerPolynomial(intCoeffs);
- }
-}
diff --git a/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/ModularResultant.java b/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/ModularResultant.java
deleted file mode 100644
index 5f77192..0000000
--- a/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/ModularResultant.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package org.bouncycastle.pqc.math.ntru.polynomial;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.pqc.math.ntru.euclid.BigIntEuclidean;
-
-/**
- * A resultant modulo a <code>BigInteger</code>
- */
-public class ModularResultant
- extends Resultant
-{
- BigInteger modulus;
-
- ModularResultant(BigIntPolynomial rho, BigInteger res, BigInteger modulus)
- {
- super(rho, res);
- this.modulus = modulus;
- }
-
- /**
- * Calculates a <code>rho</code> modulo <code>m1*m2</code> from
- * two resultants whose <code>rho</code>s are modulo <code>m1</code> and <code>m2</code>.<br/>
- * </code>res</code> is set to <code>null</code>.
- *
- * @param modRes1
- * @param modRes2
- * @return <code>rho</code> modulo <code>modRes1.modulus * modRes2.modulus</code>, and <code>null</code> for </code>res</code>.
- */
- static ModularResultant combineRho(ModularResultant modRes1, ModularResultant modRes2)
- {
- BigInteger mod1 = modRes1.modulus;
- BigInteger mod2 = modRes2.modulus;
- BigInteger prod = mod1.multiply(mod2);
- BigIntEuclidean er = BigIntEuclidean.calculate(mod2, mod1);
-
- BigIntPolynomial rho1 = (BigIntPolynomial)modRes1.rho.clone();
- rho1.mult(er.x.multiply(mod2));
- BigIntPolynomial rho2 = (BigIntPolynomial)modRes2.rho.clone();
- rho2.mult(er.y.multiply(mod1));
- rho1.add(rho2);
- rho1.mod(prod);
-
- return new ModularResultant(rho1, null, prod);
- }
-}
diff --git a/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/Polynomial.java b/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/Polynomial.java
deleted file mode 100644
index 69193e3..0000000
--- a/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/Polynomial.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package org.bouncycastle.pqc.math.ntru.polynomial;
-
-public interface Polynomial
-{
-
- /**
- * Multiplies the polynomial by an <code>IntegerPolynomial</code>,
- * taking the indices mod <code>N</code>.
- *
- * @param poly2 a polynomial
- * @return the product of the two polynomials
- */
- IntegerPolynomial mult(IntegerPolynomial poly2);
-
- /**
- * Multiplies the polynomial by an <code>IntegerPolynomial</code>,
- * taking the coefficient values mod <code>modulus</code> and the indices mod <code>N</code>.
- *
- * @param poly2 a polynomial
- * @param modulus a modulus to apply
- * @return the product of the two polynomials
- */
- IntegerPolynomial mult(IntegerPolynomial poly2, int modulus);
-
- /**
- * Returns a polynomial that is equal to this polynomial (in the sense that {@link #mult(IntegerPolynomial, int)}
- * returns equal <code>IntegerPolynomial</code>s). The new polynomial is guaranteed to be independent of the original.
- *
- * @return a new <code>IntegerPolynomial</code>.
- */
- IntegerPolynomial toIntegerPolynomial();
-
- /**
- * Multiplies the polynomial by a <code>BigIntPolynomial</code>, taking the indices mod N. Does not
- * change this polynomial but returns the result as a new polynomial.<br>
- * Both polynomials must have the same number of coefficients.
- *
- * @param poly2 the polynomial to multiply by
- * @return a new polynomial
- */
- BigIntPolynomial mult(BigIntPolynomial poly2);
-}
diff --git a/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/ProductFormPolynomial.java b/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/ProductFormPolynomial.java
deleted file mode 100644
index dd18902..0000000
--- a/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/ProductFormPolynomial.java
+++ /dev/null
@@ -1,153 +0,0 @@
-package org.bouncycastle.pqc.math.ntru.polynomial;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.security.SecureRandom;
-
-import org.bouncycastle.util.Arrays;
-
-/**
- * A polynomial of the form <code>f1*f2+f3</code>, where
- * <code>f1,f2,f3</code> are very sparsely populated ternary polynomials.
- */
-public class ProductFormPolynomial
- implements Polynomial
-{
- private SparseTernaryPolynomial f1, f2, f3;
-
- public ProductFormPolynomial(SparseTernaryPolynomial f1, SparseTernaryPolynomial f2, SparseTernaryPolynomial f3)
- {
- this.f1 = f1;
- this.f2 = f2;
- this.f3 = f3;
- }
-
- public static ProductFormPolynomial generateRandom(int N, int df1, int df2, int df3Ones, int df3NegOnes, SecureRandom random)
- {
- SparseTernaryPolynomial f1 = SparseTernaryPolynomial.generateRandom(N, df1, df1, random);
- SparseTernaryPolynomial f2 = SparseTernaryPolynomial.generateRandom(N, df2, df2, random);
- SparseTernaryPolynomial f3 = SparseTernaryPolynomial.generateRandom(N, df3Ones, df3NegOnes, random);
- return new ProductFormPolynomial(f1, f2, f3);
- }
-
- public static ProductFormPolynomial fromBinary(byte[] data, int N, int df1, int df2, int df3Ones, int df3NegOnes)
- throws IOException
- {
- return fromBinary(new ByteArrayInputStream(data), N, df1, df2, df3Ones, df3NegOnes);
- }
-
- public static ProductFormPolynomial fromBinary(InputStream is, int N, int df1, int df2, int df3Ones, int df3NegOnes)
- throws IOException
- {
- SparseTernaryPolynomial f1;
-
- f1 = SparseTernaryPolynomial.fromBinary(is, N, df1, df1);
- SparseTernaryPolynomial f2 = SparseTernaryPolynomial.fromBinary(is, N, df2, df2);
- SparseTernaryPolynomial f3 = SparseTernaryPolynomial.fromBinary(is, N, df3Ones, df3NegOnes);
- return new ProductFormPolynomial(f1, f2, f3);
- }
-
- public byte[] toBinary()
- {
- byte[] f1Bin = f1.toBinary();
- byte[] f2Bin = f2.toBinary();
- byte[] f3Bin = f3.toBinary();
-
- byte[] all = Arrays.copyOf(f1Bin, f1Bin.length + f2Bin.length + f3Bin.length);
- System.arraycopy(f2Bin, 0, all, f1Bin.length, f2Bin.length);
- System.arraycopy(f3Bin, 0, all, f1Bin.length + f2Bin.length, f3Bin.length);
- return all;
- }
-
- public IntegerPolynomial mult(IntegerPolynomial b)
- {
- IntegerPolynomial c = f1.mult(b);
- c = f2.mult(c);
- c.add(f3.mult(b));
- return c;
- }
-
- public BigIntPolynomial mult(BigIntPolynomial b)
- {
- BigIntPolynomial c = f1.mult(b);
- c = f2.mult(c);
- c.add(f3.mult(b));
- return c;
- }
-
- public IntegerPolynomial toIntegerPolynomial()
- {
- IntegerPolynomial i = f1.mult(f2.toIntegerPolynomial());
- i.add(f3.toIntegerPolynomial());
- return i;
- }
-
- public IntegerPolynomial mult(IntegerPolynomial poly2, int modulus)
- {
- IntegerPolynomial c = mult(poly2);
- c.mod(modulus);
- return c;
- }
-
- public int hashCode()
- {
- final int prime = 31;
- int result = 1;
- result = prime * result + ((f1 == null) ? 0 : f1.hashCode());
- result = prime * result + ((f2 == null) ? 0 : f2.hashCode());
- result = prime * result + ((f3 == null) ? 0 : f3.hashCode());
- return result;
- }
-
- public boolean equals(Object obj)
- {
- if (this == obj)
- {
- return true;
- }
- if (obj == null)
- {
- return false;
- }
- if (getClass() != obj.getClass())
- {
- return false;
- }
- ProductFormPolynomial other = (ProductFormPolynomial)obj;
- if (f1 == null)
- {
- if (other.f1 != null)
- {
- return false;
- }
- }
- else if (!f1.equals(other.f1))
- {
- return false;
- }
- if (f2 == null)
- {
- if (other.f2 != null)
- {
- return false;
- }
- }
- else if (!f2.equals(other.f2))
- {
- return false;
- }
- if (f3 == null)
- {
- if (other.f3 != null)
- {
- return false;
- }
- }
- else if (!f3.equals(other.f3))
- {
- return false;
- }
- return true;
- }
-}
diff --git a/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/Resultant.java b/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/Resultant.java
deleted file mode 100644
index ec58577..0000000
--- a/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/Resultant.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package org.bouncycastle.pqc.math.ntru.polynomial;
-
-import java.math.BigInteger;
-
-/**
- * Contains a resultant and a polynomial <code>rho</code> such that
- * <code>res = rho*this + t*(x^n-1) for some integer t</code>.
- *
- * @see IntegerPolynomial#resultant()
- * @see IntegerPolynomial#resultant(int)
- */
-public class Resultant
-{
- /**
- * A polynomial such that <code>res = rho*this + t*(x^n-1) for some integer t</code>
- */
- public BigIntPolynomial rho;
- /**
- * Resultant of a polynomial with <code>x^n-1</code>
- */
- public BigInteger res;
-
- Resultant(BigIntPolynomial rho, BigInteger res)
- {
- this.rho = rho;
- this.res = res;
- }
-}
diff --git a/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/SparseTernaryPolynomial.java b/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/SparseTernaryPolynomial.java
deleted file mode 100644
index 3c91339..0000000
--- a/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/SparseTernaryPolynomial.java
+++ /dev/null
@@ -1,320 +0,0 @@
-package org.bouncycastle.pqc.math.ntru.polynomial;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-import org.bouncycastle.pqc.math.ntru.util.ArrayEncoder;
-import org.bouncycastle.pqc.math.ntru.util.Util;
-import org.bouncycastle.util.Arrays;
-
-/**
- * A <code>TernaryPolynomial</code> with a "low" number of nonzero coefficients.
- */
-public class SparseTernaryPolynomial
- implements TernaryPolynomial
-{
- /**
- * Number of bits to use for each coefficient. Determines the upper bound for <code>N</code>.
- */
- private static final int BITS_PER_INDEX = 11;
-
- private int N;
- private int[] ones;
- private int[] negOnes;
-
- /**
- * Constructs a new polynomial.
- *
- * @param N total number of coefficients including zeros
- * @param ones indices of coefficients equal to 1
- * @param negOnes indices of coefficients equal to -1
- */
- SparseTernaryPolynomial(int N, int[] ones, int[] negOnes)
- {
- this.N = N;
- this.ones = ones;
- this.negOnes = negOnes;
- }
-
- /**
- * Constructs a <code>DenseTernaryPolynomial</code> from a <code>IntegerPolynomial</code>. The two polynomials are
- * independent of each other.
- *
- * @param intPoly the original polynomial
- */
- public SparseTernaryPolynomial(IntegerPolynomial intPoly)
- {
- this(intPoly.coeffs);
- }
-
- /**
- * Constructs a new <code>SparseTernaryPolynomial</code> with a given set of coefficients.
- *
- * @param coeffs the coefficients
- */
- public SparseTernaryPolynomial(int[] coeffs)
- {
- N = coeffs.length;
- ones = new int[N];
- negOnes = new int[N];
- int onesIdx = 0;
- int negOnesIdx = 0;
- for (int i = 0; i < N; i++)
- {
- int c = coeffs[i];
- switch (c)
- {
- case 1:
- ones[onesIdx++] = i;
- break;
- case -1:
- negOnes[negOnesIdx++] = i;
- break;
- case 0:
- break;
- default:
- throw new IllegalArgumentException("Illegal value: " + c + ", must be one of {-1, 0, 1}");
- }
- }
- ones = Arrays.copyOf(ones, onesIdx);
- negOnes = Arrays.copyOf(negOnes, negOnesIdx);
- }
-
- /**
- * 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(InputStream is, int N, int numOnes, int numNegOnes)
- throws IOException
- {
- int maxIndex = 1 << BITS_PER_INDEX;
- int bitsPerIndex = 32 - Integer.numberOfLeadingZeros(maxIndex - 1);
-
- int data1Len = (numOnes * bitsPerIndex + 7) / 8;
- byte[] data1 = Util.readFullLength(is, data1Len);
- int[] ones = ArrayEncoder.decodeModQ(data1, numOnes, maxIndex);
-
- int data2Len = (numNegOnes * bitsPerIndex + 7) / 8;
- byte[] data2 = Util.readFullLength(is, data2Len);
- int[] negOnes = ArrayEncoder.decodeModQ(data2, numNegOnes, maxIndex);
-
- return new SparseTernaryPolynomial(N, ones, negOnes);
- }
-
- /**
- * Generates a random polynomial with <code>numOnes</code> coefficients equal to 1,
- * <code>numNegOnes</code> coefficients equal to -1, and the rest equal to 0.
- *
- * @param N number of coefficients
- * @param numOnes number of 1's
- * @param numNegOnes number of -1's
- */
- public static SparseTernaryPolynomial generateRandom(int N, int numOnes, int numNegOnes, SecureRandom random)
- {
- int[] coeffs = Util.generateRandomTernary(N, numOnes, numNegOnes, random);
- return new SparseTernaryPolynomial(coeffs);
- }
-
- public IntegerPolynomial mult(IntegerPolynomial poly2)
- {
- int[] b = poly2.coeffs;
- if (b.length != N)
- {
- throw new IllegalArgumentException("Number of coefficients must be the same");
- }
-
- int[] c = new int[N];
- for (int idx = 0; idx != ones.length; idx++)
- {
- int i = ones[idx];
- int j = N - 1 - i;
- for (int k = N - 1; k >= 0; k--)
- {
- c[k] += b[j];
- j--;
- if (j < 0)
- {
- j = N - 1;
- }
- }
- }
-
- for (int idx = 0; idx != negOnes.length; idx++)
- {
- int i = negOnes[idx];
- int j = N - 1 - i;
- for (int k = N - 1; k >= 0; k--)
- {
- c[k] -= b[j];
- j--;
- if (j < 0)
- {
- j = N - 1;
- }
- }
- }
-
- return new IntegerPolynomial(c);
- }
-
- public IntegerPolynomial mult(IntegerPolynomial poly2, int modulus)
- {
- IntegerPolynomial c = mult(poly2);
- c.mod(modulus);
- return c;
- }
-
- public BigIntPolynomial mult(BigIntPolynomial poly2)
- {
- BigInteger[] b = poly2.coeffs;
- if (b.length != N)
- {
- throw new IllegalArgumentException("Number of coefficients must be the same");
- }
-
- BigInteger[] c = new BigInteger[N];
- for (int i = 0; i < N; i++)
- {
- c[i] = BigInteger.ZERO;
- }
-
- for (int idx = 0; idx != ones.length; idx++)
- {
- int i = ones[idx];
- int j = N - 1 - i;
- for (int k = N - 1; k >= 0; k--)
- {
- c[k] = c[k].add(b[j]);
- j--;
- if (j < 0)
- {
- j = N - 1;
- }
- }
- }
-
- for (int idx = 0; idx != negOnes.length; idx++)
- {
- int i = negOnes[idx];
- int j = N - 1 - i;
- for (int k = N - 1; k >= 0; k--)
- {
- c[k] = c[k].subtract(b[j]);
- j--;
- if (j < 0)
- {
- j = N - 1;
- }
- }
- }
-
- return new BigIntPolynomial(c);
- }
-
- public int[] getOnes()
- {
- return ones;
- }
-
- public int[] getNegOnes()
- {
- return negOnes;
- }
-
- /**
- * Encodes the polynomial to a byte array writing <code>BITS_PER_INDEX</code> bits for each coefficient.
- *
- * @return the encoded polynomial
- */
- public byte[] toBinary()
- {
- int maxIndex = 1 << BITS_PER_INDEX;
- byte[] bin1 = ArrayEncoder.encodeModQ(ones, maxIndex);
- byte[] bin2 = ArrayEncoder.encodeModQ(negOnes, maxIndex);
-
- byte[] bin = Arrays.copyOf(bin1, bin1.length + bin2.length);
- System.arraycopy(bin2, 0, bin, bin1.length, bin2.length);
- return bin;
- }
-
- public IntegerPolynomial toIntegerPolynomial()
- {
- int[] coeffs = new int[N];
- for (int idx = 0; idx != ones.length; idx++)
- {
- int i = ones[idx];
- coeffs[i] = 1;
- }
- for (int idx = 0; idx != negOnes.length; idx++)
- {
- int i = negOnes[idx];
- coeffs[i] = -1;
- }
- return new IntegerPolynomial(coeffs);
- }
-
- public int size()
- {
- return N;
- }
-
- public void clear()
- {
- for (int i = 0; i < ones.length; i++)
- {
- ones[i] = 0;
- }
- for (int i = 0; i < negOnes.length; i++)
- {
- negOnes[i] = 0;
- }
- }
-
- public int hashCode()
- {
- final int prime = 31;
- int result = 1;
- result = prime * result + N;
- result = prime * result + Arrays.hashCode(negOnes);
- result = prime * result + Arrays.hashCode(ones);
- return result;
- }
-
- public boolean equals(Object obj)
- {
- if (this == obj)
- {
- return true;
- }
- if (obj == null)
- {
- return false;
- }
- if (getClass() != obj.getClass())
- {
- return false;
- }
- SparseTernaryPolynomial other = (SparseTernaryPolynomial)obj;
- if (N != other.N)
- {
- return false;
- }
- if (!Arrays.areEqual(negOnes, other.negOnes))
- {
- return false;
- }
- if (!Arrays.areEqual(ones, other.ones))
- {
- return false;
- }
- return true;
- }
-}
diff --git a/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/TernaryPolynomial.java b/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/TernaryPolynomial.java
deleted file mode 100644
index 822b64b..0000000
--- a/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/TernaryPolynomial.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package org.bouncycastle.pqc.math.ntru.polynomial;
-
-/**
- * A polynomial whose coefficients are all equal to -1, 0, or 1
- */
-public interface TernaryPolynomial
- extends Polynomial
-{
-
- /**
- * Multiplies the polynomial by an <code>IntegerPolynomial</code>, taking the indices mod N
- */
- IntegerPolynomial mult(IntegerPolynomial poly2);
-
- int[] getOnes();
-
- int[] getNegOnes();
-
- /**
- * Returns the maximum number of coefficients the polynomial can have
- */
- int size();
-
- void clear();
-}
diff --git a/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/test/AllTests.java b/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/test/AllTests.java
deleted file mode 100644
index 296a66e..0000000
--- a/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/test/AllTests.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package org.bouncycastle.pqc.math.ntru.polynomial.test;
-
-import junit.framework.Test;
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
-
-public class AllTests
- extends TestCase
-{
- public static void main (String[] args)
- {
- junit.textui.TestRunner.run(suite());
- }
-
- public static Test suite()
- {
- TestSuite suite = new TestSuite("NTRU Polynomial Tests");
-
- suite.addTestSuite(BigDecimalPolynomialTest.class);
- suite.addTestSuite(BigIntPolynomialTest.class);
- suite.addTestSuite(IntegerPolynomialTest.class);
- suite.addTestSuite(LongPolynomial2Test.class);
- suite.addTestSuite(LongPolynomial5Test.class);
- suite.addTestSuite(ProductFormPolynomialTest.class);
- suite.addTestSuite(SparseTernaryPolynomialTest.class);
-
- return suite;
- }
-}
diff --git a/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/test/BigDecimalPolynomialTest.java b/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/test/BigDecimalPolynomialTest.java
deleted file mode 100644
index 06e9e04..0000000
--- a/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/test/BigDecimalPolynomialTest.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package org.bouncycastle.pqc.math.ntru.polynomial.test;
-
-import java.math.BigDecimal;
-import java.security.SecureRandom;
-
-import junit.framework.TestCase;
-import org.bouncycastle.pqc.math.ntru.polynomial.BigDecimalPolynomial;
-import org.bouncycastle.pqc.math.ntru.polynomial.BigIntPolynomial;
-import org.bouncycastle.pqc.math.ntru.polynomial.DenseTernaryPolynomial;
-import org.bouncycastle.pqc.math.ntru.polynomial.IntegerPolynomial;
-
-public class BigDecimalPolynomialTest
- extends TestCase
-{
- public void testMult()
- {
- BigDecimalPolynomial a = new BigDecimalPolynomial(new BigIntPolynomial(new IntegerPolynomial(new int[]{4, -1, 9, 2, 1, -5, 12, -7, 0, -9, 5})));
- BigDecimalPolynomial b = new BigDecimalPolynomial(new BigIntPolynomial(new IntegerPolynomial(new int[]{-6, 0, 0, 13, 3, -2, -4, 10, 11, 2, -1})));
- BigDecimalPolynomial c = a.mult(b);
- BigDecimal[] expectedCoeffs = new BigDecimalPolynomial(new BigIntPolynomial(new IntegerPolynomial(new int[]{2, -189, 77, 124, -29, 0, -75, 124, -49, 267, 34}))).getCoeffs();
-
- BigDecimal[] cCoeffs = c.getCoeffs();
-
- assertEquals(expectedCoeffs.length, cCoeffs.length);
- for (int i = 0; i != cCoeffs.length; i++)
- {
- assertEquals(expectedCoeffs[i], cCoeffs[i]);
- }
-
- // multiply a polynomial by its inverse modulo 2048 and check that the result is 1
- SecureRandom random = new SecureRandom();
- IntegerPolynomial d, dInv;
- do
- {
- d = DenseTernaryPolynomial.generateRandom(1001, 333, 334, random);
- dInv = d.invertFq(2048);
- }
- while (dInv == null);
-
- d.mod(2048);
- BigDecimalPolynomial e = new BigDecimalPolynomial(new BigIntPolynomial(d));
- BigIntPolynomial f = new BigIntPolynomial(dInv);
- IntegerPolynomial g = new IntegerPolynomial(e.mult(f).round());
- g.modPositive(2048);
- assertTrue(g.equalsOne());
- }
-} \ No newline at end of file
diff --git a/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/test/BigIntPolynomialTest.java b/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/test/BigIntPolynomialTest.java
deleted file mode 100644
index a6ad36e..0000000
--- a/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/test/BigIntPolynomialTest.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package org.bouncycastle.pqc.math.ntru.polynomial.test;
-
-import java.math.BigInteger;
-
-import junit.framework.TestCase;
-import org.bouncycastle.pqc.math.ntru.polynomial.BigIntPolynomial;
-import org.bouncycastle.pqc.math.ntru.polynomial.IntegerPolynomial;
-
-public class BigIntPolynomialTest
- extends TestCase
-{
- public void testMult()
- {
- BigIntPolynomial a = new BigIntPolynomial(new IntegerPolynomial(new int[]{4, -1, 9, 2, 1, -5, 12, -7, 0, -9, 5}));
- BigIntPolynomial b = new BigIntPolynomial(new IntegerPolynomial(new int[]{-6, 0, 0, 13, 3, -2, -4, 10, 11, 2, -1}));
- BigIntPolynomial c = a.mult(b);
- BigInteger[] expectedCoeffs = new BigIntPolynomial(new IntegerPolynomial(new int[]{2, -189, 77, 124, -29, 0, -75, 124, -49, 267, 34})).getCoeffs();
- BigInteger[] cCoeffs = c.getCoeffs();
-
- assertEquals(expectedCoeffs.length, cCoeffs.length);
- for (int i = 0; i != cCoeffs.length; i++)
- {
- assertEquals(expectedCoeffs[i], cCoeffs[i]);
- }
- }
-} \ No newline at end of file
diff --git a/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/test/IntegerPolynomialTest.java b/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/test/IntegerPolynomialTest.java
deleted file mode 100644
index 8f6e489..0000000
--- a/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/test/IntegerPolynomialTest.java
+++ /dev/null
@@ -1,230 +0,0 @@
-package org.bouncycastle.pqc.math.ntru.polynomial.test;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-import junit.framework.TestCase;
-import org.bouncycastle.pqc.crypto.ntru.NTRUSigningKeyGenerationParameters;
-import org.bouncycastle.pqc.math.ntru.polynomial.BigIntPolynomial;
-import org.bouncycastle.pqc.math.ntru.polynomial.DenseTernaryPolynomial;
-import org.bouncycastle.pqc.math.ntru.polynomial.IntegerPolynomial;
-import org.bouncycastle.pqc.math.ntru.polynomial.Resultant;
-import org.bouncycastle.util.Arrays;
-
-
-public class IntegerPolynomialTest
- extends TestCase
-{
- public void testMult()
- {
- // multiplication modulo q
- IntegerPolynomial a = new IntegerPolynomial(new int[]{-1, 1, 1, 0, -1, 0, 1, 0, 0, 1, -1});
- IntegerPolynomial b = new IntegerPolynomial(new int[]{14, 11, 26, 24, 14, 16, 30, 7, 25, 6, 19});
- IntegerPolynomial c = a.mult(b, 32);
- assertEqualsMod(new int[]{3, -7, -10, -11, 10, 7, 6, 7, 5, -3, -7}, c.coeffs, 32);
-
- a = new IntegerPolynomial(new int[]{15, 27, 18, 16, 12, 13, 16, 2, 28, 22, 26});
- b = new IntegerPolynomial(new int[]{-1, 0, 1, 1, 0, 1, 0, 0, -1, 0, -1});
- c = a.mult(b, 32);
- assertEqualsMod(new int[]{8, 25, 22, 20, 12, 24, 15, 19, 12, 19, 16}, c.coeffs, 32);
-
- // multiplication without a modulus
- a = new IntegerPolynomial(new int[]{1, 1, 0, 0, -1, -1, 0, 0, -1, 0, 1});
- b = new IntegerPolynomial(new int[]{704, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0});
- c = a.mult(b);
-
- // mult(p, modulus) should give the same result as mult(p) followed by modulus
- a = new IntegerPolynomial(new int[]{1, 0, -1, 1, 0, 1, 1, 1, -1, 1, -1});
- b = new IntegerPolynomial(new int[]{0, 1, 1, 0, 0, -1, -1, 1, 1, -1, 1});
- c = a.mult(b);
- c.modPositive(20);
- IntegerPolynomial d = a.mult(b, 20);
- d.modPositive(20);
- assertTrue(Arrays.areEqual(c.coeffs, d.coeffs));
- }
-
- void assertEqualsMod(int[] arr1, int[] arr2, int m)
- {
- assertEquals(arr1.length, arr2.length);
- for (int i = 0; i < arr1.length; i++)
- {
- assertEquals((arr1[i] + m) % m, (arr2[i] + m) % m);
- }
- }
-
- public void testInvertFq()
- {
- SecureRandom random = new SecureRandom();
- // Verify an example from the NTRU tutorial
- IntegerPolynomial a = new IntegerPolynomial(new int[]{-1, 1, 1, 0, -1, 0, 1, 0, 0, 1, -1});
- IntegerPolynomial b = a.invertFq(32);
- assertEqualsMod(new int[]{5, 9, 6, 16, 4, 15, 16, 22, 20, 18, 30}, b.coeffs, 32);
- verifyInverse(a, b, 32);
-
- // test 3 random polynomials
- int numInvertible = 0;
- while (numInvertible < 3)
- {
- a = DenseTernaryPolynomial.generateRandom(853, random);
- b = a.invertFq(2048);
- if (b != null)
- {
- numInvertible++;
- verifyInverse(a, b, 2048);
- }
- }
-
- // test a non-invertible polynomial
- a = new IntegerPolynomial(new int[]{-1, 0, 1, 1, 0, 0, -1, 0, -1, 0, 1});
- b = a.invertFq(32);
- assertNull(b);
- }
-
- public void testInvertF3()
- {
- IntegerPolynomial a = new IntegerPolynomial(new int[]{-1, 1, 1, 0, -1, 0, 1, 0, 0, 1, -1});
- IntegerPolynomial b = a.invertF3();
- assertEqualsMod(new int[]{1, 2, 0, 2, 2, 1, 0, 2, 1, 2, 0}, b.coeffs, 3);
- verifyInverse(a, b, 3);
-
- // test a non-invertible polynomial
- a = new IntegerPolynomial(new int[]{0, 1, -1, 1, 0, 0, 0, 0, -1, 0, 0});
- b = a.invertF3();
- assertNull(b);
- }
-
- // tests if a*b=1 (mod modulus)
- private void verifyInverse(IntegerPolynomial a, IntegerPolynomial b, int modulus)
- {
- IntegerPolynomial c = a.mult(b, modulus);
- for (int i = 1; i < c.coeffs.length; i++)
- {
- c.coeffs[i] %= modulus;
- }
- c.ensurePositive(modulus);
- assertTrue(c.equalsOne());
- }
-
- public void testFromToBinary()
- {
- byte[] a = new byte[]{-44, -33, 30, -109, 101, -28, -6, -105, -45, 113, -72, 99, 101, 15, 9, 49, -80, -76, 58, 42, -57, -113, -89, -14, -125, 24, 125, -16, 37, -58, 10, -49, -77, -31, 120, 103, -29, 105, -56, -126, -92, 36, 125, 127, -90, 38, 9, 4, 104, 10, -78, -106, -88, -1, -1, -43, -19, 90, 41, 0, -43, 102, 118, -72, -122, 19, -76, 57, -59, -2, 35, 47, 83, 114, 86, -115, -125, 58, 75, 115, -29, -6, 108, 6, -77, -51, 127, -8, -8, -58, -30, -126, 110, -5, -35, -41, -37, 69, 22, -48, 26, 4, -120, -19, -32, -81, -77, 124, -7, -2, -46, -96, 38, -35, 88, 4, -5, 16, 101, 29, 7, 2, 88, 35, -64, 31, -66, -70, 120, -97, 76, -74, -97, -61, 52, -56, 87, -35, 5, 95, -93, -30, 10, 38, 17, -102, -25, 86, 7, -43, 44, -52, -108, 33, -18, -110, -9, -115, 66, -71, 66, 1, -90, -72, 90, -88, -38, 75, 47, -124, -120, -15, -49, -8, 85, 5, 17, -88, 76, 99, -4, 83, 16, -91, 82, 116, 112, -83, 56, -45, -26, 125, 13, -75, -115, 92, -12, -59, 3, -12, 14, -6, 43, -17, 121, 122, 22, 92, -74, 99, -59, -103, 113, 8, -103, 114, 99, -48, 92, -88, 77, 81, 5, 31, -4, -69, -24, 23, 94, 126, 71, 93, 20, 77, 82, -54, -14, 86, 45, -81, 0, 52, -63, -66, 48, 104, -54, 15, -73, -2, -52, 115, 76, 28, -5, -94, -63, 117, -69, 0, 61, 22, -1, 71, -115, 9, -73, -100, -128, -31, 106, -74, -61, -37, 98, -6, 11, -5, 6, -18, -53, -6, 11, -49, 62, 23, 6, -128, 38, -91, 89, -34, 18, -38, -110, -101, 43, 36, 62, 101, 112, 59, -91, 78, -81, 61, 126, -21, -42, -110, -38, -27, 69, 57, 9, 24, -50, -118, 31, -17, 42, 87, -54, 122, -16, 42, -47, -19, -80, 16, 54, -97, -89, 81, -22, -35, 45, 54, -46, 22, -122, -95, -17, 7, -127, 105, -100, -56, -98, -105, 101, -81, 104, 121, -7, 33, 126, 110, -125, -85, 111, -52, 123, -98, 41, -42, 88, -68, -17, 39, -19, -96, -10, -117, 13, -88, -75, -101, -16, -7, 73, 23, -12, 41, -116, -105, -64, -4, 103, 49, -15, -49, 60, 88, -25, -21, 42, 26, 95, -90, -83, -69, 64, -2, 50, -116, -64, 26, -29, -93, -120, -70, 32, -38, 39, -126, -19, 103, 127, 65, 54, 110, 94, 126, -82, -80, -18, 43, 45, 56, -118, 109, 36, -8, 10, 113, 69, 53, -122, -127, 92, -127, -73, 70, -19, -105, -80, -15, -5, 99, -109, -27, 119, -76, -57, -48, 42, -35, 23, 39, -126, 44, -107, -100, -125, 117, -50, 115, -79, -16, 104, 8, -102, 83, -73, 21, -85, 113, -87, -54, 93, 63, -108, -64, 109, -74, 15, 14, -119, -6, -68, 45, 37, -15, -97, -95, -55, 89, 25, -63, -92, -80, -27, -8, 55, 50, 96, -91, 40, -74, 110, -96, 94, 6, 85, 92, 0, 34, -122, 5, -126, 123, 37, -90, -94, 60, 14, 36, 49, -98, -23, 57, 75, 63, 106, -7, -36, -89, 84, 71, 60, -21, 104, -47, 90, -52, -66, 88, -91, -81, -3, 116, 23, 62, -47, -84, -118, 65, 31, 7, -103, 37, -29, 115, -114, 73, 12, -121, 96, -91, -7, 56, 10, -72, 27, -45, 122, -27, -38, 74, 64, 30, -60, 64, -21, 48, 101, 113, 126, -60, -103, 71, 100, -117, 124, -125, 116, 78, 114, -74, 42, -81, -54, 34, 33, -10, 19, 23, 24, 40, 0, -8, 78, 100, 73, -88, -95, -62, -115, -18, 47, 10, -14, -39, 82, 27, -9, -115, -70, 92, -6, 39, 45, -71, -109, -41, 94, -88, -63, 19, -58, -37, -31, 1, 127, -42, 125, -120, -57, 120, -86, -6, 17, -27, -37, 47, 55, -22, -11, -31, 38, -1, 29, 56, -34, -104, -66, -62, 72, -11, -30, -30, 61, -31, 10, -63, 116, -84, 118, -127, 6, 17, -36, 91, 123, 77, 35, 22, 110, 114, 107, -3, 52, 11, 86, 68, -56, 0, 119, -43, -73, 112, 89, -4, -122, -71, -26, 103, -118, -61, -112, -108, -44, -25, -22, 4, 24, 53, -5, -71, 9, -41, 84, -28, 22, 99, 39, -26, -2, -51, 68, 63, -15, 99, 66, -78, 46, -89, 21, -38, -114, -51, 100, -59, 84, -76, -105, 51, 28, 19, 74, 42, 91, -73, 12, -89, -128, 34, 38, -100, 121, -78, 114, -28, 127, -29, 50, 105, -6, 36, 98, -35, 79, -58, 5, -13, -86, -101, -108, -99, -70, 25, 103, 63, 57, 79, -12, -63, 125, -54, 61, 15, 6, -79, 90, 76, 103, -45, 7, 39, 93, 107, 58, 76, 80, 56, -108, 55, -22, 36, 125, -91, -65, 11, 69, 10, -19, -14, -4, -26, -36, 114, 124, 63, -31, 88, 92, 108, 33, -52, -22, 80, -65, 57, 126, 43, -13, 122, -8, 68, 72, 92, -50, 100, -91, 1, -81, 75, 95, -11, -99, 38, 121, -20, -70, 82, -125, -94, -18, 16, 59, 89, 18, -96, 91, -97, 62, -96, 127, 45, 70, 16, 84, -43, -75, -118, 81, 58, 84, -115, -120, -3, 41, -103, -70, 123, 26, 101, 33, 58, 13, -11, -73, -84, -47, -7, 81, -63, 60, -45, 30, 100, -51, -15, 73, 58, -119, -3, 62, -63, -17, -69, -44, 60, -54, -115, -59, 23, -59, 98, -89, -72, 20, -96, 27, 53, -89, 59, -85, -29, 120, 23, 62, 8, -86, 113, 87, -15, 102, 106, -104, 57, -57, 37, 110, 118, 109, 25, 64, 26, -20, -86, -2, 60, -70, -33, 67, 13, -28, -29, -63, -37, 67, 99, 84, 121, -126, -38, 45, 24, 122, 51, 11, -19, -80, 26, -106, -95, 82, 69, -2, -75, 62, 106, -120, 87, -107, 87, 17, 102, -52, -16, 22, 12, -86, -48, -95, -61, 109, 64, -29, 111, 40, -90, -35, 49, 88, -15, 122, 127, 87, 113, 116, 93, 100, 28, -70, -87, -40, -1, -126, -114, 7, 79, 16, 2, -47, -98, -102, 49, 58, 61, -32, 44, 18, -26, 37, 27, -123, -76, 56, 91, 51, -21, -48, -122, -33, 40, -8, -62, -56, -126, 91, -51, 76, -29, 127, -22, -18, -110, 27, 13, -111, 81, 51, -104, 70, 98, 12, 120, -7, 15, 104, -43, -104, 124, 46, 116, 7, -26, 21, 33, 105, 17, -99, -42, -106, 8, -85, 39, 8, 79, -54, -81, 109, 40, 25, 29, -18, -90, 22, 85, -12, -16, 61, 49, -31, 127, 64, 5, 25, 39, -65, -42, 13, -97, -92, 36, -126, -18, -4, -22, -14, 109, -93, -76, -5, 13, 74, 44, 103, 79, 110, 85, 58, 39, -24, 119, 120, 122, 120, 43, 110, 67, 21, 47, 39, -48, 7, 91, -51, 126, 100, -38, -124, 0, -97, 99, -123, 118, -27, 8, 102, -106, -23, -53, -4, -56, -9, -126, -85, 93, -4, -5, 4, 49, 29, 2, 63, 78, -32, -106, 118, 111, 52, 54, 74, 53, 106, 39, -95, -38, -18, 118, -5, 94, -83, -97, -27, 62, -56, -90, -36, 43, 43, -113, 119, -89, 44, -108, -46, 66, 28, 66, -38, 3, -62, -83, -35, -127, -2, 51, 104, 105, 40, 76, -10, -124, -95, 52, 11, 101, -32, -122, -73, -17, 37, -126, 68, -126, 55, 112, -126, 38, 99, -63, 123, -74, -31, 58, 8, 93, -68, 111, -22, -24, -23, 9, -87, -25, -115, 81, -116, -91, 60, 96, -102, -1, -7, 73, 99, 46, -78, 62, 48, -116, -52, -44, -5, 82, -45, 5, -55, -101, 101, 65, -109, -108, 26, 98, -55, 11, -86, 57, 30, 92, -58, 20, 82, 65, 103, 27, -64, 76, 123, -56, -16, -111, -83, 125, 65, 111, 9, 123, 14, 119, 126, -80, 79, 94, -19, 66, -25, 35, 112, -64, 10, -66, -86, 51, 56, -78, 103, 92, -116, 8, 75, 41, -49, -79, -53, 125, -32, -76, -27, 59, -8, -4, -94, -104, -15, 79, -7, -124, 32, -87, -104, 85, -118, -36, 125, 65, 111, -105, 5, -105, 40, -50, 2, 118, 123, -54, 59, -22, 94, 20, 99, -87, -27, 28, -30, -109, 72, -19, 92, 60, 19, 115, 47, 96, -96, 10, -74, 60, 96, -86, 101, 101, 68, -44, -72, 9, -36, 126, 96, -45, -12, 9, 14, -15, 79, -79, -48, 8, -107, -81, 47, 35, -36, -107, -120, -36, -124, 37, 103, -60, -35, -74, 100, -38, -88, -99, -99, -94, -107, 79, 115, 108, 54, 119, 73, 84, 110, -74, 92, 57, 108, 80, 47, -36, -119, -115, 58, -62, -4, -97, 43, -98, 5, 112, 47, 59, -89, 82, -69, -103, 39, -29, 75, -9, -94, -72, 99, -64, 22, -10, 21, 89, 101, 21, 94, -30, -17, 73, -36, -68, -89, -91, -94, 99, -106, 119, -116, 123, -19, 54, -99, 64, -119, 82, 120, -106, -99, 80, 69, 29, -48, 77, 28, 13, 92, -107, -77, 94, -116, 108, 89, -115, 96, -41, 25, 99, -65, 118, -5, -16, 48, -122, 5, 50, -123, -115, 13, 24, 7, 15, -103, -62, -71, 92, -82, -5, -70, 49, -6, -51, -17, -47, 12, 46, -86, 30, 93, 84, -101, 43, -92, -87, -118, -110, -32, 52, 115, -4, 36, -2, -79, -69, -46, -110, 70, -82, 6, 21, -27, -11, 94, 42, -81, -96, 116, -102, -38, 36, 32, 91, 28, 80, -45, 116, -94, -33, -5, -102, 64, -96, 27, -2, 100, -126, 59, -71, 33, -36, -124, 123, 99, -76, 108, 127, -11, -24, -19, 84, -6, 19, 105, -19, -18, 120, -14, 23, 39, 54, 87, 105, 58, -95, -15, 127, -65, 114, 49, 4, -66, 32, -7, 84, 43, -103, 76, 11, 36, -68, -3, -98, -5, -43, 35, -48, 20, -40, -33, -123, 1, -54, -44, 99, -68, 8, -100, 97, -49, -10, 110, 49, 84, 46, -85, 98, -103, -58, -4, 104, -100, -40, -79, 67, -20, -95, 85, 51, 73, 10, -25, 102, 68, -97, -83, -39, 35, 2, -111, 71, 62, -89, 20, 25, -126, 17, -81, -29, 39, -27, -55, 55, -122, 97, 23, -99, 55, 86, 33, -9, 8, 55, -40, -84, 39, 38, 37, -29, 87, 113, -118, -26, 123, -95, 24, -126, 119, -94, 17, 83, -43, 10, 63, -98, 72, 8, 16, -95, -96, 119, -91, 6, 71, -60, 1, -77, 4, 53, -121, 55, 7, 36, -86, -49, -118, -121, 56, 84, -49, -57, -99, 3, -68, 37, -108, -72, 114, -74, 120, 3, 121, -28, -106, 54, -20, 63, -121, -85, -59, -111, 32, 13, -69, 122, 90, 5, 40, 88, 15, -90, 125, -28, 89, 95, 73, 96, 60, -60, -51, 102, 7, 57, 91, 59, 15, 92, -76, -34, -23, -77, 90, 45, 91, 77, -63, 94, -127, 74, -97, -44, 50, -87, -94, -25, -71, 112, 127, -117, 6, 32, -113, 54, 83, -31, 111, -73, 53, 34, -32, -98, 125, -39, 63, 15, 72, -69, 87, -118, 108, 17, 84, 15, 61, -47, 54, -24, -79, 91, 28, -28, 66, 53, 22, 9, -28, -12, 38, 64, 75, -122, 96, -59, -45, 4, -19, 47, -30, 75, -94, 62, -64, 76, -49, 19, -66, -34, 3, 84, -2, -54, 13, -84, 86, -117, 94, -27, 89, 16, 96, 52, -77, -36, -116, 27, -52, -33, -50, 14, -59, 77, 93, -109, 8, -89, 81, -114, -29, -94, 73, -119, -56, -19, 88, -17, -33, 125, -18, -68, 113, 40, -128, -112, -119, -106, -106, -30, 23, -77, 49, 3, 98, -101, 99, -107, -121, -12, -112, 24, -74, -74, 79, -17, 96, 65, -52, 86, -63, 45, 84, 119, -42, 61, -91, 29, -87, 65, -85, 99, -14, 71, 33, -41, -48, -2, -121, 78, -38, 41, -7, -37, 48, 122, 61, -124, 42, -22, 24, 2, -49, 74, -81, -88, -89, -107, 109, 53, -68, 90, -117, 123, -109, -28, 12, 80, 120, 26, -104, 73, 70, -36, 34, -80, -104, 23, 16, 14, -96, -5, 27, 71, 25, -8, -125, 58, 88, -52, -97, -97, -93, 11, -44, 116, 42, -102, -100, -31, -86, 71, 84, 70, 27, 117, -67, 92, -84, -13, 54, -102, 34, 5, 19, -76, 71, 89, 22, -49, -34, -29};
- IntegerPolynomial poly = IntegerPolynomial.fromBinary(a, 1499, 2048);
- byte[] b = poly.toBinary(2048);
- // verify that bytes 0..2047 match, ignore non-relevant bits of byte 2048
- assertTrue(Arrays.areEqual(copyOf(a, 2047), copyOf(b, 2047)));
- assertEquals((a[a.length - 1] & 1) >> (7 - (1499 * 11) % 8), (b[b.length - 1] & 1) >> (7 - (1499 * 11) % 8));
- }
-
- public void testFromToBinary3Sves()
- {
- byte[] a = new byte[]{-112, -78, 19, 15, 99, -65, -56, -90, 44, -93, -109, 104, 40, 90, -84, -21, -124, 51, -33, 4, -51, -106, 33, 86, -76, 42, 41, -17, 47, 79, 81, -29, 15, 116, 101, 120, 116, 32, 116, 111, 32, 101, 110, 99, 114, 121, 112, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
- IntegerPolynomial poly = IntegerPolynomial.fromBinary3Sves(a, 1499);
- byte[] b = poly.toBinary3Sves();
- assertTrue(Arrays.areEqual(a, b));
- }
-
- public void testFromToBinary3Tight()
- {
- int[] c = new int[]{0, 0, 0, 0, 0, 0, 0, 1, 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0, 0, 0, -1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0, 1, 0, 1, 0, -1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, -1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, -1, -1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, -1, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0};
- IntegerPolynomial poly1 = new IntegerPolynomial(c);
- IntegerPolynomial poly2 = IntegerPolynomial.fromBinary3Tight(poly1.toBinary3Tight(), c.length);
- assertTrue(Arrays.areEqual(poly1.coeffs, poly2.coeffs));
-
- IntegerPolynomial poly3 = new IntegerPolynomial(new int[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, -1, -1, 0, 0, 0, 1, 0, -1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, -1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, -1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, -1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, -1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, -1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0});
- byte[] arr = poly3.toBinary3Tight();
- IntegerPolynomial poly4 = IntegerPolynomial.fromBinary3Tight(arr, 1499);
- assertTrue(Arrays.areEqual(poly3.coeffs, poly4.coeffs));
-
- IntegerPolynomial poly5 = new IntegerPolynomial(new int[]{0, 0, 0, 1, -1, -1, -1});
- arr = poly5.toBinary3Tight();
- IntegerPolynomial poly6 = IntegerPolynomial.fromBinary3Tight(arr, 7);
- assertTrue(Arrays.areEqual(poly5.coeffs, poly6.coeffs));
-
- SecureRandom random = new SecureRandom();
-
- for (int i = 0; i < 100; i++)
- {
- IntegerPolynomial poly7 = DenseTernaryPolynomial.generateRandom(157, random);
- arr = poly7.toBinary3Tight();
- IntegerPolynomial poly8 = IntegerPolynomial.fromBinary3Tight(arr, 157);
- assertTrue(Arrays.areEqual(poly7.coeffs, poly8.coeffs));
- }
- }
-
- public void testResultant()
- {
- SecureRandom random = new SecureRandom();
- NTRUSigningKeyGenerationParameters params = NTRUSigningKeyGenerationParameters.APR2011_439;
- IntegerPolynomial a = DenseTernaryPolynomial.generateRandom(params.N, params.d, params.d, random);
- verifyResultant(a, a.resultant());
-
- a = new IntegerPolynomial(new int[]{0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0, 0, 0, 0, 0, 1, -1, 0, 0, -1, 0, 0, 0, 1, 0, 0, 0, -1, -1, 0, -1, 1, -1, 0, -1, 0, -1, -1, -1, 0, 0, 0, 1, 1, -1, -1, -1, 0, -1, -1, 0, 0, 1, 0, 0, 0, 0, 0, -1, 0, 0, 1, 0, 0, 1, 1, -1, 0, 1, -1, 0, 1, 0, 1, 0, -1, -1, 0, 1, 0, -1, 1, 1, 1, 1, 0, 0, -1, -1, 1, 0, 0, -1, -1, 0, -1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, -1, 0, 0, 0, 0, -1, 0, 0, 0, 1, 0, 1, 0, 1, -1, 0, 0, 1, 1, 1, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 1, 0, -1, -1, 0, -1, -1, -1, 0, -1, -1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, -1, 0, 1, 0, -1, 0, 0, 0, 0, 0, 0, -1, -1, 0, -1, -1, 1, 1, 0, 0, -1, 1, 0, 0, 0, -1, 1, -1, 0, -1, 0, 0, 0, -1, 0, 0, 0, 0, 0, -1, 1, 1, 0, 0, -1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, -1, 0, 1, 0, -1, -1, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, 1, -1, 1, -1, -1, 1, -1, 0, 1, 0, 0, 0, 1, 0, 0, 1, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0, -1, 0, 1, -1, 0, 0, 1, 1, 0, 0, 1, 1, 0, -1, 0, -1, 1, -1, -1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, -1, 0, 0, 1, -1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, -1, -1, 0, 0, -1, 0, 1, 1, -1, 1, -1, 0, 0, 0, 1});
- verifyResultant(a, a.resultant());
- }
-
- // verifies that res=rho*a mod x^n-1
- private void verifyResultant(IntegerPolynomial a, Resultant r)
- {
- BigIntPolynomial b = new BigIntPolynomial(a).mult(r.rho);
- BigInteger[] bCoeffs = b.getCoeffs();
-
- for (int j = 1; j < bCoeffs.length - 1; j++)
- {
- assertEquals(BigInteger.ZERO, bCoeffs[j]);
- }
- if (r.res.equals(BigInteger.ZERO))
- {
- assertEquals(BigInteger.ZERO, bCoeffs[0].subtract(bCoeffs[bCoeffs.length - 1]));
- }
- else
- {
- assertEquals(BigInteger.ZERO, (bCoeffs[0].subtract(bCoeffs[bCoeffs.length - 1]).mod(r.res)));
- }
- assertEquals(bCoeffs[0].subtract(r.res), bCoeffs[bCoeffs.length - 1].negate());
- }
-
- public void testResultantMod()
- {
- int p = 46337; // prime; must be less than sqrt(2^31) or integer overflows will occur
-
- IntegerPolynomial a = new IntegerPolynomial(new int[]{0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0, 0, 0, 0, 0, 1, -1, 0, 0, -1, 0, 0, 0, 1, 0, 0, 0, -1, -1, 0, -1, 1, -1, 0, -1, 0, -1, -1, -1, 0, 0, 0, 1, 1, -1, -1, -1, 0, -1, -1, 0, 0, 1, 0, 0, 0, 0, 0, -1, 0, 0, 1, 0, 0, 1, 1, -1, 0, 1, -1, 0, 1, 0, 1, 0, -1, -1, 0, 1, 0, -1, 1, 1, 1, 1, 0, 0, -1, -1, 1, 0, 0, -1, -1, 0, -1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, -1, 0, 0, 0, 0, -1, 0, 0, 0, 1, 0, 1, 0, 1, -1, 0, 0, 1, 1, 1, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 1, 0, -1, -1, 0, -1, -1, -1, 0, -1, -1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, -1, 0, 1, 0, -1, 0, 0, 0, 0, 0, 0, -1, -1, 0, -1, -1, 1, 1, 0, 0, -1, 1, 0, 0, 0, -1, 1, -1, 0, -1, 0, 0, 0, -1, 0, 0, 0, 0, 0, -1, 1, 1, 0, 0, -1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, -1, 0, 1, 0, -1, -1, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, 1, -1, 1, -1, -1, 1, -1, 0, 1, 0, 0, 0, 1, 0, 0, 1, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0, -1, 0, 1, -1, 0, 0, 1, 1, 0, 0, 1, 1, 0, -1, 0, -1, 1, -1, -1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, -1, 0, 0, 1, -1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, -1, -1, 0, 0, -1, 0, 1, 1, -1, 1, -1, 0, 0, 0, 1});
- verifyResultant(a, a.resultant(p), p);
-
- SecureRandom random = new SecureRandom();
-
- for (int i = 0; i < 10; i++)
- {
- a = DenseTernaryPolynomial.generateRandom(853, random);
- verifyResultant(a, a.resultant(p), p);
- }
- }
-
- // verifies that res=rho*a mod x^n-1 mod p
- private void verifyResultant(IntegerPolynomial a, Resultant r, int p)
- {
- BigIntPolynomial b = new BigIntPolynomial(a).mult(r.rho);
- b.mod(BigInteger.valueOf(p));
- BigInteger[] bCoeffs = b.getCoeffs();
-
- for (int j = 1; j < bCoeffs.length - 1; j++)
- {
- assertEquals(BigInteger.ZERO, bCoeffs[j]);
- }
- if (r.res.equals(BigInteger.ZERO))
- {
- assertEquals(BigInteger.ZERO, bCoeffs[0].subtract(bCoeffs[bCoeffs.length - 1]));
- }
- else
- {
- assertEquals(BigInteger.ZERO, (bCoeffs[0].subtract(bCoeffs[bCoeffs.length - 1]).subtract(r.res).mod(BigInteger.valueOf(p))));
- }
- assertEquals(BigInteger.ZERO, bCoeffs[0].subtract(r.res).subtract(bCoeffs[bCoeffs.length - 1].negate()).mod(BigInteger.valueOf(p)));
- }
-
- private byte[] copyOf(byte[] src, int length)
- {
- byte[] tmp = new byte[length];
- System.arraycopy(src, 0, tmp, 0, tmp.length);
- return tmp;
- }
-} \ No newline at end of file
diff --git a/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/test/LongPolynomial2Test.java b/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/test/LongPolynomial2Test.java
deleted file mode 100644
index c842064..0000000
--- a/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/test/LongPolynomial2Test.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package org.bouncycastle.pqc.math.ntru.polynomial.test;
-
-import java.util.Random;
-
-import junit.framework.TestCase;
-import org.bouncycastle.pqc.math.ntru.polynomial.IntegerPolynomial;
-import org.bouncycastle.pqc.math.ntru.polynomial.LongPolynomial2;
-import org.bouncycastle.util.Arrays;
-
-public class LongPolynomial2Test
- extends TestCase
-{
- public void testMult()
- {
- IntegerPolynomial i1 = new IntegerPolynomial(new int[]{1368, 2047, 672, 871, 1662, 1352, 1099, 1608});
- IntegerPolynomial i2 = new IntegerPolynomial(new int[]{1729, 1924, 806, 179, 1530, 1381, 1695, 60});
- LongPolynomial2 a = new LongPolynomial2(i1);
- LongPolynomial2 b = new LongPolynomial2(i2);
- IntegerPolynomial c1 = i1.mult(i2, 2048);
- IntegerPolynomial c2 = a.mult(b).toIntegerPolynomial();
- assertTrue(Arrays.areEqual(c1.coeffs, c2.coeffs));
-
- // test 10 random polynomials
- Random rng = new Random();
- for (int i = 0; i < 10; i++)
- {
- int N = 2 + rng.nextInt(2000);
- i1 = PolynomialGenerator.generateRandom(N, 2048);
- i2 = PolynomialGenerator.generateRandom(N, 2048);
- a = new LongPolynomial2(i1);
- b = new LongPolynomial2(i2);
- c1 = i1.mult(i2);
- c1.modPositive(2048);
- c2 = a.mult(b).toIntegerPolynomial();
- assertTrue(Arrays.areEqual(c1.coeffs, c2.coeffs));
- }
- }
-
- public void testSubAnd()
- {
- IntegerPolynomial i1 = new IntegerPolynomial(new int[]{1368, 2047, 672, 871, 1662, 1352, 1099, 1608});
- IntegerPolynomial i2 = new IntegerPolynomial(new int[]{1729, 1924, 806, 179, 1530, 1381, 1695, 60});
- LongPolynomial2 a = new LongPolynomial2(i1);
- LongPolynomial2 b = new LongPolynomial2(i2);
- a.subAnd(b, 2047);
- i1.sub(i2);
- i1.modPositive(2048);
- assertTrue(Arrays.areEqual(a.toIntegerPolynomial().coeffs, i1.coeffs));
- }
-
- public void testMult2And()
- {
- IntegerPolynomial i1 = new IntegerPolynomial(new int[]{1368, 2047, 672, 871, 1662, 1352, 1099, 1608});
- LongPolynomial2 i2 = new LongPolynomial2(i1);
- i2.mult2And(2047);
- i1.mult(2);
- i1.modPositive(2048);
- assertTrue(Arrays.areEqual(i1.coeffs, i2.toIntegerPolynomial().coeffs));
- }
-} \ No newline at end of file
diff --git a/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/test/LongPolynomial5Test.java b/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/test/LongPolynomial5Test.java
deleted file mode 100644
index cf91ac2..0000000
--- a/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/test/LongPolynomial5Test.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package org.bouncycastle.pqc.math.ntru.polynomial.test;
-
-import java.security.SecureRandom;
-
-import junit.framework.TestCase;
-import org.bouncycastle.pqc.math.ntru.polynomial.DenseTernaryPolynomial;
-import org.bouncycastle.pqc.math.ntru.polynomial.IntegerPolynomial;
-import org.bouncycastle.pqc.math.ntru.polynomial.LongPolynomial5;
-import org.bouncycastle.util.Arrays;
-
-public class LongPolynomial5Test
- extends TestCase
-{
- public void testMult()
- {
- testMult(new int[]{2}, new int[]{-1});
- testMult(new int[]{2, 0}, new int[]{-1, 0});
- testMult(new int[]{2, 0, 3}, new int[]{-1, 0, 1});
- testMult(new int[]{2, 0, 3, 1}, new int[]{-1, 0, 1, 1});
- testMult(new int[]{2, 0, 3, 1, 2}, new int[]{-1, 0, 1, 1, 0});
- testMult(new int[]{2, 0, 3, 1, 1, 5}, new int[]{1, -1, 1, 1, 0, 1});
- testMult(new int[]{2, 0, 3, 1, 1, 5, 1, 4}, new int[]{1, 0, 1, 1, -1, 1, 0, -1});
- testMult(new int[]{1368, 2047, 672, 871, 1662, 1352, 1099, 1608}, new int[]{1, 0, 1, 1, -1, 1, 0, -1});
-
- // test random polynomials
- SecureRandom rng = new SecureRandom();
- for (int i = 0; i < 10; i++)
- {
- int[] coeffs1 = new int[rng.nextInt(2000) + 1];
- int[] coeffs2 = DenseTernaryPolynomial.generateRandom(coeffs1.length, rng).coeffs;
- testMult(coeffs1, coeffs2);
- }
- }
-
- private void testMult(int[] coeffs1, int[] coeffs2)
- {
- IntegerPolynomial i1 = new IntegerPolynomial(coeffs1);
- IntegerPolynomial i2 = new IntegerPolynomial(coeffs2);
-
- LongPolynomial5 a = new LongPolynomial5(i1);
- DenseTernaryPolynomial b = new DenseTernaryPolynomial(i2);
- IntegerPolynomial c1 = i1.mult(i2, 2048);
- IntegerPolynomial c2 = a.mult(b).toIntegerPolynomial();
- assertEqualsMod(c1.coeffs, c2.coeffs, 2048);
- }
-
- private void assertEqualsMod(int[] arr1, int[] arr2, int m)
- {
- assertEquals(arr1.length, arr2.length);
- for (int i = 0; i < arr1.length; i++)
- {
- assertEquals((arr1[i] + m) % m, (arr2[i] + m) % m);
- }
- }
-
- public void testToIntegerPolynomial()
- {
- int[] coeffs = new int[]{2, 0, 3, 1, 1, 5, 1, 4};
- LongPolynomial5 p = new LongPolynomial5(new IntegerPolynomial(coeffs));
- assertTrue(Arrays.areEqual(coeffs, p.toIntegerPolynomial().coeffs));
- }
-} \ No newline at end of file
diff --git a/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/test/PolynomialGenerator.java b/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/test/PolynomialGenerator.java
deleted file mode 100644
index 8f931d7..0000000
--- a/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/test/PolynomialGenerator.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package org.bouncycastle.pqc.math.ntru.polynomial.test;
-
-import java.util.Random;
-
-import org.bouncycastle.pqc.math.ntru.polynomial.IntegerPolynomial;
-
-public class PolynomialGenerator
-{
- /**
- * Creates a random polynomial with <code>N</code> coefficients
- * between <code>0</code> and <code>q-1</code>.
- *
- * @param N length of the polynomial
- * @param q coefficients will all be below this number
- * @return a random polynomial
- */
- public static IntegerPolynomial generateRandom(int N, int q)
- {
- Random rng = new Random();
- int[] coeffs = new int[N];
- for (int i = 0; i < N; i++)
- {
- coeffs[i] = rng.nextInt(q);
- }
- return new IntegerPolynomial(coeffs);
- }
-} \ No newline at end of file
diff --git a/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/test/ProductFormPolynomialTest.java b/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/test/ProductFormPolynomialTest.java
deleted file mode 100644
index 9fbbb98..0000000
--- a/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/test/ProductFormPolynomialTest.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package org.bouncycastle.pqc.math.ntru.polynomial.test;
-
-import java.security.SecureRandom;
-
-import junit.framework.TestCase;
-import org.bouncycastle.pqc.crypto.ntru.NTRUEncryptionKeyGenerationParameters;
-import org.bouncycastle.pqc.math.ntru.polynomial.IntegerPolynomial;
-import org.bouncycastle.pqc.math.ntru.polynomial.ProductFormPolynomial;
-
-public class ProductFormPolynomialTest
- extends TestCase
-{
- private NTRUEncryptionKeyGenerationParameters params;
- private int N;
- private int df1;
- private int df2;
- private int df3;
- private int q;
-
- public void setUp()
- {
- params = NTRUEncryptionKeyGenerationParameters.APR2011_439_FAST;
- N = params.N;
- df1 = params.df1;
- df2 = params.df2;
- df3 = params.df3;
- q = params.q;
- }
-
- public void testFromToBinary()
- throws Exception
- {
- ProductFormPolynomial p1 = ProductFormPolynomial.generateRandom(N, df1, df2, df3, df3 - 1, new SecureRandom());
- byte[] bin1 = p1.toBinary();
- ProductFormPolynomial p2 = ProductFormPolynomial.fromBinary(bin1, N, df1, df2, df3, df3 - 1);
- assertEquals(p1, p2);
- }
-
- public void testMult()
- {
- ProductFormPolynomial p1 = ProductFormPolynomial.generateRandom(N, df1, df2, df3, df3 - 1, new SecureRandom());
- IntegerPolynomial p2 = PolynomialGenerator.generateRandom(N, q);
- IntegerPolynomial p3 = p1.mult(p2);
- IntegerPolynomial p4 = p1.toIntegerPolynomial().mult(p2);
- assertEquals(p3, p4);
- }
-} \ No newline at end of file
diff --git a/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/test/SparseTernaryPolynomialTest.java b/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/test/SparseTernaryPolynomialTest.java
deleted file mode 100644
index 3d434c6..0000000
--- a/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/polynomial/test/SparseTernaryPolynomialTest.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package org.bouncycastle.pqc.math.ntru.polynomial.test;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.security.SecureRandom;
-
-import junit.framework.TestCase;
-import org.bouncycastle.pqc.math.ntru.polynomial.BigIntPolynomial;
-import org.bouncycastle.pqc.math.ntru.polynomial.DenseTernaryPolynomial;
-import org.bouncycastle.pqc.math.ntru.polynomial.IntegerPolynomial;
-import org.bouncycastle.pqc.math.ntru.polynomial.SparseTernaryPolynomial;
-
-public class SparseTernaryPolynomialTest
- extends TestCase
-{
-
- /**
- * tests mult(IntegerPolynomial) and mult(BigIntPolynomial)
- */
- public void testMult()
- {
- SecureRandom random = new SecureRandom();
- SparseTernaryPolynomial p1 = SparseTernaryPolynomial.generateRandom(1000, 500, 500, random);
- IntegerPolynomial p2 = DenseTernaryPolynomial.generateRandom(1000, random);
-
- IntegerPolynomial prod1 = p1.mult(p2);
- IntegerPolynomial prod2 = p1.mult(p2);
- assertEquals(prod1, prod2);
-
- BigIntPolynomial p3 = new BigIntPolynomial(p2);
- BigIntPolynomial prod3 = p1.mult(p3);
-
- assertEquals(new BigIntPolynomial(prod1), prod3);
- }
-
- public void testFromToBinary()
- throws IOException
- {
- SecureRandom random = new SecureRandom();
- SparseTernaryPolynomial poly1 = SparseTernaryPolynomial.generateRandom(1000, 100, 101, random);
- ByteArrayInputStream poly1Stream = new ByteArrayInputStream(poly1.toBinary());
- SparseTernaryPolynomial poly2 = SparseTernaryPolynomial.fromBinary(poly1Stream, 1000, 100, 101);
- assertEquals(poly1, poly2);
- }
-} \ No newline at end of file
diff --git a/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/util/ArrayEncoder.java b/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/util/ArrayEncoder.java
deleted file mode 100644
index 017e104..0000000
--- a/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/util/ArrayEncoder.java
+++ /dev/null
@@ -1,294 +0,0 @@
-package org.bouncycastle.pqc.math.ntru.util;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.math.BigInteger;
-
-import org.bouncycastle.util.Arrays;
-
-/**
- * Converts a coefficient array to a compact byte array and vice versa.
- */
-public class ArrayEncoder
-{
- /**
- * Bit string to coefficient conversion table from P1363.1. Also found at
- * {@link http://stackoverflow.com/questions/1562548/how-to-make-a-message-into-a-polynomial}
- * <p>
- * Convert each three-bit quantity to two ternary coefficients as follows, and concatenate the resulting
- * ternary quantities to obtain [the output].
- * </p><p>
- * <code>
- * {0, 0, 0} -> {0, 0}<br/>
- * {0, 0, 1} -> {0, 1}<br/>
- * {0, 1, 0} -> {0, -1}<br/>
- * {0, 1, 1} -> {1, 0}<br/>
- * {1, 0, 0} -> {1, 1}<br/>
- * {1, 0, 1} -> {1, -1}<br/>
- * {1, 1, 0} -> {-1, 0}<br/>
- * {1, 1, 1} -> {-1, 1}<br/>
- * </code>
- * </p>
- */
- private static final int[] COEFF1_TABLE = {0, 0, 0, 1, 1, 1, -1, -1};
- private static final int[] COEFF2_TABLE = {0, 1, -1, 0, 1, -1, 0, 1};
- /**
- * Coefficient to bit string conversion table from P1363.1. Also found at
- * {@link http://stackoverflow.com/questions/1562548/how-to-make-a-message-into-a-polynomial}
- * <p>
- * Convert each set of two ternary coefficients to three bits as follows, and concatenate the resulting bit
- * quantities to obtain [the output]:
- * </p><p>
- * <code>
- * {-1, -1} -> set "fail" to 1 and set bit string to {1, 1, 1}
- * {-1, 0} -> {1, 1, 0}<br/>
- * {-1, 1} -> {1, 1, 1}<br/>
- * {0, -1} -> {0, 1, 0}<br/>
- * {0, 0} -> {0, 0, 0}<br/>
- * {0, 1} -> {0, 0, 1}<br/>
- * {1, -1} -> {1, 0, 1}<br/>
- * {1, 0} -> {0, 1, 1}<br/>
- * {1, 1} -> {1, 0, 0}<br/>
- * </code> \
- * </p>
- */
- private static final int[] BIT1_TABLE = {1, 1, 1, 0, 0, 0, 1, 0, 1};
- private static final int[] BIT2_TABLE = {1, 1, 1, 1, 0, 0, 0, 1, 0};
- private static final int[] BIT3_TABLE = {1, 0, 1, 0, 0, 1, 1, 1, 0};
-
- /**
- * 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 - Integer.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] |= currentBit << bitIndex;
- if (bitIndex == 7)
- {
- bitIndex = 0;
- byteIndex++;
- }
- else
- {
- bitIndex++;
- }
- }
- }
- return data;
- }
-
- /**
- * 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 - Integer.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;
- }
-
- /**
- * 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(InputStream is, int N, int q)
- throws IOException
- {
- int qBits = 31 - Integer.numberOfLeadingZeros(q);
- int size = (N * qBits + 7) / 8;
- byte[] arr = Util.readFullLength(is, size);
- return decodeModQ(arr, N, q);
- }
-
- /**
- * Decodes a <code>byte</code> array encoded with {@link #encodeMod3Sves(int[])} back to an <code>int</code> array
- * with <code>N</code> coefficients between <code>-1</code> and <code>1</code>.<br>
- * Ignores any excess bytes.<br>
- * See P1363.1 section 9.2.2.
- *
- * @param data an encoded ternary polynomial
- * @param N number of coefficients
- * @return the decoded coefficients
- */
- public static int[] decodeMod3Sves(byte[] data, int N)
- {
- int[] coeffs = new int[N];
- int coeffIndex = 0;
- for (int bitIndex = 0; bitIndex < data.length * 8; )
- {
- int bit1 = getBit(data, bitIndex++);
- int bit2 = getBit(data, bitIndex++);
- int bit3 = getBit(data, bitIndex++);
- int coeffTableIndex = bit1 * 4 + bit2 * 2 + bit3;
- coeffs[coeffIndex++] = COEFF1_TABLE[coeffTableIndex];
- coeffs[coeffIndex++] = COEFF2_TABLE[coeffTableIndex];
- // ignore bytes that can't fit
- if (coeffIndex > N - 2)
- {
- break;
- }
- }
- return coeffs;
- }
-
- /**
- * Encodes an <code>int</code> array whose elements are between <code>-1</code> and <code>1</code>, to a byte array.
- * <code>coeffs[2*i]</code> and <code>coeffs[2*i+1]</code> must not both equal -1 for any integer <code>i</code>,
- * so this method is only safe to use with arrays produced by {@link #decodeMod3Sves(byte[], int)}.<br>
- * See P1363.1 section 9.2.3.
- *
- * @param arr
- * @return the encoded array
- */
- public static byte[] encodeMod3Sves(int[] arr)
- {
- int numBits = (arr.length * 3 + 1) / 2;
- int numBytes = (numBits + 7) / 8;
- byte[] data = new byte[numBytes];
- int bitIndex = 0;
- int byteIndex = 0;
- for (int i = 0; i < arr.length / 2 * 2; )
- { // if length is an odd number, throw away the highest coeff
- int coeff1 = arr[i++] + 1;
- int coeff2 = arr[i++] + 1;
- if (coeff1 == 0 && coeff2 == 0)
- {
- throw new IllegalStateException("Illegal encoding!");
- }
- int bitTableIndex = coeff1 * 3 + coeff2;
- int[] bits = new int[]{BIT1_TABLE[bitTableIndex], BIT2_TABLE[bitTableIndex], BIT3_TABLE[bitTableIndex]};
- for (int j = 0; j < 3; j++)
- {
- data[byteIndex] |= bits[j] << bitIndex;
- if (bitIndex == 7)
- {
- bitIndex = 0;
- byteIndex++;
- }
- else
- {
- bitIndex++;
- }
- }
- }
- return data;
- }
-
- /**
- * Encodes an <code>int</code> array whose elements are between <code>-1</code> and <code>1</code>, to a byte array.
- *
- * @return the encoded array
- */
- public static byte[] encodeMod3Tight(int[] intArray)
- {
- BigInteger sum = BigInteger.ZERO;
- for (int i = intArray.length - 1; i >= 0; i--)
- {
- sum = sum.multiply(BigInteger.valueOf(3));
- sum = sum.add(BigInteger.valueOf(intArray[i] + 1));
- }
-
- int size = (BigInteger.valueOf(3).pow(intArray.length).bitLength() + 7) / 8;
- byte[] arr = sum.toByteArray();
-
- if (arr.length < size)
- {
- // pad with leading zeros so arr.length==size
- byte[] arr2 = new byte[size];
- System.arraycopy(arr, 0, arr2, size - arr.length, arr.length);
- return arr2;
- }
-
- if (arr.length > size)
- // drop sign bit
- {
- arr = Arrays.copyOfRange(arr, 1, arr.length);
- }
- return arr;
- }
-
- /**
- * Converts a byte array produced by {@link #encodeMod3Tight(int[])} back to an <code>int</code> array.
- *
- * @param b a byte array
- * @param N number of coefficients
- * @return the decoded array
- */
- public static int[] decodeMod3Tight(byte[] b, int N)
- {
- BigInteger sum = new BigInteger(1, b);
- int[] coeffs = new int[N];
- for (int i = 0; i < N; i++)
- {
- coeffs[i] = sum.mod(BigInteger.valueOf(3)).intValue() - 1;
- if (coeffs[i] > 1)
- {
- coeffs[i] -= 3;
- }
- sum = sum.divide(BigInteger.valueOf(3));
- }
- return coeffs;
- }
-
- /**
- * Converts data produced by {@link #encodeMod3Tight(int[])} back to an <code>int</code> array.
- *
- * @param is an input stream containing the data to decode
- * @param N number of coefficients
- * @return the decoded array
- */
- public static int[] decodeMod3Tight(InputStream is, int N)
- throws IOException
- {
- int size = (int)Math.ceil(N * Math.log(3) / Math.log(2) / 8);
- byte[] arr = Util.readFullLength(is, size);
- return decodeMod3Tight(arr, N);
- }
-
- private static int getBit(byte[] arr, int bitIndex)
- {
- int byteIndex = bitIndex / 8;
- int arrElem = arr[byteIndex] & 0xFF;
- return (arrElem >> (bitIndex % 8)) & 1;
- }
-} \ No newline at end of file
diff --git a/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/util/Util.java b/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/util/Util.java
deleted file mode 100644
index 92c2ed4..0000000
--- a/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/util/Util.java
+++ /dev/null
@@ -1,158 +0,0 @@
-package org.bouncycastle.pqc.math.ntru.util;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.security.SecureRandom;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-import org.bouncycastle.pqc.math.ntru.euclid.IntEuclidean;
-import org.bouncycastle.pqc.math.ntru.polynomial.DenseTernaryPolynomial;
-import org.bouncycastle.pqc.math.ntru.polynomial.SparseTernaryPolynomial;
-import org.bouncycastle.pqc.math.ntru.polynomial.TernaryPolynomial;
-import org.bouncycastle.util.Integers;
-
-public class Util
-{
- private static volatile boolean IS_64_BITNESS_KNOWN;
- private static volatile boolean IS_64_BIT_JVM;
-
- /**
- * Calculates the inverse of n mod modulus
- */
- public static int invert(int n, int modulus)
- {
- n %= modulus;
- if (n < 0)
- {
- n += modulus;
- }
- return IntEuclidean.calculate(n, modulus).x;
- }
-
- /**
- * Calculates a^b mod modulus
- */
- public static int pow(int a, int b, int modulus)
- {
- int p = 1;
- for (int i = 0; i < b; i++)
- {
- p = (p * a) % modulus;
- }
- return p;
- }
-
- /**
- * Calculates a^b mod modulus
- */
- public static long pow(long a, int b, long modulus)
- {
- long p = 1;
- for (int i = 0; i < b; i++)
- {
- p = (p * a) % modulus;
- }
- return p;
- }
-
- /**
- * Generates a "sparse" or "dense" polynomial containing numOnes ints equal to 1,
- * numNegOnes int equal to -1, and the rest equal to 0.
- *
- * @param N
- * @param numOnes
- * @param numNegOnes
- * @param sparse whether to create a {@link SparseTernaryPolynomial} or {@link DenseTernaryPolynomial}
- * @return a ternary polynomial
- */
- public static TernaryPolynomial generateRandomTernary(int N, int numOnes, int numNegOnes, boolean sparse, SecureRandom random)
- {
- if (sparse)
- {
- return SparseTernaryPolynomial.generateRandom(N, numOnes, numNegOnes, random);
- }
- else
- {
- return DenseTernaryPolynomial.generateRandom(N, numOnes, numNegOnes, random);
- }
- }
-
- /**
- * Generates an array containing numOnes ints equal to 1,
- * numNegOnes int equal to -1, and the rest equal to 0.
- *
- * @param N
- * @param numOnes
- * @param numNegOnes
- * @return an array of integers
- */
- public static int[] generateRandomTernary(int N, int numOnes, int numNegOnes, SecureRandom random)
- {
- Integer one = Integers.valueOf(1);
- Integer minusOne = Integers.valueOf(-1);
- Integer zero = Integers.valueOf(0);
-
- List list = new ArrayList();
- for (int i = 0; i < numOnes; i++)
- {
- list.add(one);
- }
- for (int i = 0; i < numNegOnes; i++)
- {
- list.add(minusOne);
- }
- while (list.size() < N)
- {
- list.add(zero);
- }
-
- Collections.shuffle(list, random);
-
- int[] arr = new int[N];
- for (int i = 0; i < N; i++)
- {
- arr[i] = ((Integer)list.get(i)).intValue();
- }
- return arr;
- }
-
- /**
- * Takes an educated guess as to whether 64 bits are supported by the JVM.
- *
- * @return <code>true</code> if 64-bit support detected, <code>false</code> otherwise
- */
- public static boolean is64BitJVM()
- {
- if (!IS_64_BITNESS_KNOWN)
- {
- String arch = System.getProperty("os.arch");
- String sunModel = System.getProperty("sun.arch.data.model");
- IS_64_BIT_JVM = "amd64".equals(arch) || "x86_64".equals(arch) || "ppc64".equals(arch) || "64".equals(sunModel);
- IS_64_BITNESS_KNOWN = true;
- }
- return IS_64_BIT_JVM;
- }
-
- /**
- * Reads a given number of bytes from an <code>InputStream</code>.
- * If there are not enough bytes in the stream, an <code>IOException</code>
- * is thrown.
- *
- * @param is
- * @param length
- * @return an array of length <code>length</code>
- * @throws IOException
- */
- public static byte[] readFullLength(InputStream is, int length)
- throws IOException
- {
- byte[] arr = new byte[length];
- if (is.read(arr) != arr.length)
- {
- throw new IOException("Not enough bytes to read.");
- }
- return arr;
- }
-} \ No newline at end of file
diff --git a/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/util/test/AllTests.java b/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/util/test/AllTests.java
deleted file mode 100644
index 55fc973..0000000
--- a/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/util/test/AllTests.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package org.bouncycastle.pqc.math.ntru.util.test;
-
-import junit.framework.Test;
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
-
-public class AllTests
- extends TestCase
-{
- public static void main (String[] args)
- {
- junit.textui.TestRunner.run(suite());
- }
-
- public static Test suite()
- {
- TestSuite suite = new TestSuite("NTRU ArrayEncoder Tests");
-
- suite.addTestSuite(ArrayEncoderTest.class);
-
- return suite;
- }
-}
diff --git a/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/util/test/ArrayEncoderTest.java b/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/util/test/ArrayEncoderTest.java
deleted file mode 100644
index 6dbdea3..0000000
--- a/bcprov/src/main/java/org/bouncycastle/pqc/math/ntru/util/test/ArrayEncoderTest.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package org.bouncycastle.pqc.math.ntru.util.test;
-
-import java.security.SecureRandom;
-import java.util.Random;
-
-import junit.framework.TestCase;
-import org.bouncycastle.pqc.math.ntru.polynomial.DenseTernaryPolynomial;
-import org.bouncycastle.pqc.math.ntru.polynomial.test.PolynomialGenerator;
-import org.bouncycastle.pqc.math.ntru.util.ArrayEncoder;
-import org.bouncycastle.util.Arrays;
-
-public class ArrayEncoderTest
- extends TestCase
-{
- public void testEncodeDecodeModQ()
- {
- int[] coeffs = PolynomialGenerator.generateRandom(1000, 2048).coeffs;
- byte[] data = ArrayEncoder.encodeModQ(coeffs, 2048);
- int[] coeffs2 = ArrayEncoder.decodeModQ(data, 1000, 2048);
- assertTrue(Arrays.areEqual(coeffs, coeffs2));
- }
-
- public void testEncodeDecodeMod3Sves()
- {
- Random rng = new Random();
- byte[] data = new byte[180];
- rng.nextBytes(data);
- int[] coeffs = ArrayEncoder.decodeMod3Sves(data, 960);
- byte[] data2 = ArrayEncoder.encodeMod3Sves(coeffs);
- assertTrue(Arrays.areEqual(data, data2));
- }
-
- public void testEncodeDecodeMod3Tight()
- {
- SecureRandom random = new SecureRandom();
-
- int[] coeffs = DenseTernaryPolynomial.generateRandom(1000, random).coeffs;
- byte[] data = ArrayEncoder.encodeMod3Tight(coeffs);
- int[] coeffs2 = ArrayEncoder.decodeMod3Tight(data, 1000);
- assertTrue(Arrays.areEqual(coeffs, coeffs2));
- }
-} \ No newline at end of file