diff options
Diffstat (limited to 'bcprov/src/main/java/org/bouncycastle/pqc/math')
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->true, 0->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> < 0) || (<i>i</i> > (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> < 0) || (<i>i</i> > (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> < 0) || (<i>i</i> > (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> < 0) || (<i>i</i> > (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 << 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 << <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 << 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< m <32. For the - * representation of field elements the map f: F->Z, poly(A)->poly(2) is used, - * where integers have the binary representation. For example: A^7+A^3+A+1 -> - * (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< m <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<m<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) > 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 < g < p. This algorithm - * is only efficient for small p (see X9.62-1998, p. 68). - * - * @param g an integer with 1 < g < 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 >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 <= 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 > 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 >=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 - * > 0, i.e., ordered sequences containing each number <tt>m</tt> (<tt>0 <= - * m < n</tt>) - * once and only once. - */ -public class Permutation -{ - - /** - * perm holds the elements of the permutation vector, i.e. <tt>[perm(0), - * perm(1), ..., perm(n-1)]</tt> - */ - private int[] perm; - - /** - * Create the identity permutation of the given size. - * - * @param n the size of the permutation - */ - public Permutation(int n) - { - if (n <= 0) - { - throw new 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 <= m <=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) < - * deg(f); - */ - public PolynomialGF2mSmallM[] div(PolynomialGF2mSmallM f) - { - int[][] resultCoeffs = div(coefficients, f.coefficients); - return new PolynomialGF2mSmallM[]{ - new PolynomialGF2mSmallM(field, resultCoeffs[0]), - new PolynomialGF2mSmallM(field, resultCoeffs[1])}; - } - - /** - * Compute the result of the division of two polynomials over the field - * <tt>GF(2^m)</tt>. - * - * @param a the first polynomial - * @param f the second polynomial - * @return int[][] {q,r}, where a = q*f+r and deg(r) < deg(f); - */ - private int[][] div(int[] a, int[] f) - { - int df = computeDegree(f); - int da = computeDegree(a) + 1; - if (df == -1) - { - throw new ArithmeticException("Division by zero."); - } - int[][] result = new int[2][]; - result[0] = new int[1]; - result[1] = new int[da]; - int hc = headCoefficient(f); - hc = field.inverse(hc); - result[0][0] = 0; - 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)<=deg(g)/2. - * - * @param g the reduction polynomial - * @return PolynomialGF2mSmallM[] {a,b} with b*this = a mod g and deg(a)<= - * deg(g)/2 - */ - public PolynomialGF2mSmallM[] modPolynomialToFracton(PolynomialGF2mSmallM g) - { - int dg = g.degree >> 1; - int[] a0 = normalForm(g.coefficients); - int[] a1 = mod(coefficients, g.coefficients); - int[] b0 = {0}; - int[] b1 = {1}; - while (computeDegree(a1) > dg) - { - int[][] q = div(a0, a1); - a0 = a1; - a1 = q[1]; - int[] b2 = add(b0, modMultiply(q[0], b1, g.coefficients)); - b0 = b1; - b1 = b2; - } - - return new PolynomialGF2mSmallM[]{ - new PolynomialGF2mSmallM(field, a1), - new PolynomialGF2mSmallM(field, b1)}; - } - - /** - * checks if given object is equal to this polynomial. - * <p> - * The method returns false whenever the given object is not polynomial over - * GF(2^m). - * - * @param other object - * @return true or false - */ - public 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 <=32. For the polynomial representation the map f: R->Z, - * poly(X)->poly(2) is used, where integers have the binary representation. For - * example: X^7+X^3+X+1 -> (00...0010001011)=139 Also for polynomials type - * Integer is used. - * - * @see GF2mField - */ -public 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<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 > 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 |