what-the-bank/sources/org/bouncycastle/pqc/math/linearalgebra/PolynomialGF2mSmallM.java

579 lines
21 KiB
Java
Raw Normal View History

2024-07-27 18:17:47 +07:00
package org.bouncycastle.pqc.math.linearalgebra;
import com.google.common.primitives.UnsignedBytes;
import java.security.SecureRandom;
/* loaded from: classes6.dex */
public class PolynomialGF2mSmallM {
public static final char RANDOM_IRREDUCIBLE_POLYNOMIAL = 'I';
private int[] coefficients;
private int degree;
private GF2mField field;
public String toString() {
StringBuilder sb = new StringBuilder(" Polynomial over ");
sb.append(this.field.toString());
sb.append(": \n");
String obj = sb.toString();
for (int i = 0; i < this.coefficients.length; i++) {
StringBuilder sb2 = new StringBuilder();
sb2.append(obj);
sb2.append(this.field.elementToStr(this.coefficients[i]));
sb2.append("Y^");
sb2.append(i);
sb2.append("+");
obj = sb2.toString();
}
StringBuilder sb3 = new StringBuilder();
sb3.append(obj);
sb3.append(";");
return sb3.toString();
}
public PolynomialGF2mSmallM multiply(PolynomialGF2mSmallM polynomialGF2mSmallM) {
return new PolynomialGF2mSmallM(this.field, multiply(this.coefficients, polynomialGF2mSmallM.coefficients));
}
public PolynomialGF2mSmallM multWithMonomial(int i) {
return new PolynomialGF2mSmallM(this.field, multWithMonomial(this.coefficients, i));
}
public PolynomialGF2mSmallM multWithElement(int i) {
if (!this.field.isElementOfThisField(i)) {
throw new ArithmeticException("Not an element of the finite field this polynomial is defined over.");
}
return new PolynomialGF2mSmallM(this.field, multWithElement(this.coefficients, i));
}
public void multThisWithElement(int i) {
if (!this.field.isElementOfThisField(i)) {
throw new ArithmeticException("Not an element of the finite field this polynomial is defined over.");
}
this.coefficients = multWithElement(this.coefficients, i);
computeDegree();
}
public PolynomialGF2mSmallM modSquareRootMatrix(PolynomialGF2mSmallM[] polynomialGF2mSmallMArr) {
int length = polynomialGF2mSmallMArr.length;
int[] iArr = new int[length];
for (int i = 0; i < length; i++) {
for (int i2 = 0; i2 < length; i2++) {
int[] iArr2 = polynomialGF2mSmallMArr[i2].coefficients;
if (i < iArr2.length) {
int[] iArr3 = this.coefficients;
if (i2 < iArr3.length) {
iArr[i] = this.field.add(iArr[i], this.field.mult(iArr2[i], iArr3[i2]));
}
}
}
}
for (int i3 = 0; i3 < length; i3++) {
iArr[i3] = this.field.sqRoot(iArr[i3]);
}
return new PolynomialGF2mSmallM(this.field, iArr);
}
public PolynomialGF2mSmallM modSquareRoot(PolynomialGF2mSmallM polynomialGF2mSmallM) {
int[] clone = IntUtils.clone(this.coefficients);
int[] modMultiply = modMultiply(clone, clone, polynomialGF2mSmallM.coefficients);
while (!isEqual(modMultiply, this.coefficients)) {
clone = normalForm(modMultiply);
modMultiply = modMultiply(clone, clone, polynomialGF2mSmallM.coefficients);
}
return new PolynomialGF2mSmallM(this.field, clone);
}
public PolynomialGF2mSmallM modSquareMatrix(PolynomialGF2mSmallM[] polynomialGF2mSmallMArr) {
int length = polynomialGF2mSmallMArr.length;
int[] iArr = new int[length];
int[] iArr2 = new int[length];
int i = 0;
while (true) {
int[] iArr3 = this.coefficients;
if (i >= iArr3.length) {
break;
}
GF2mField gF2mField = this.field;
int i2 = iArr3[i];
iArr2[i] = gF2mField.mult(i2, i2);
i++;
}
for (int i3 = 0; i3 < length; i3++) {
for (int i4 = 0; i4 < length; i4++) {
int[] iArr4 = polynomialGF2mSmallMArr[i4].coefficients;
if (i3 < iArr4.length) {
iArr[i3] = this.field.add(iArr[i3], this.field.mult(iArr4[i3], iArr2[i4]));
}
}
}
return new PolynomialGF2mSmallM(this.field, iArr);
}
public PolynomialGF2mSmallM[] modPolynomialToFracton(PolynomialGF2mSmallM polynomialGF2mSmallM) {
int i = polynomialGF2mSmallM.degree;
int[] normalForm = normalForm(polynomialGF2mSmallM.coefficients);
int[] iArr = normalForm;
int[] mod = mod(this.coefficients, polynomialGF2mSmallM.coefficients);
int[] iArr2 = {0};
int[] iArr3 = {1};
while (computeDegree(mod) > (i >> 1)) {
int[][] div = div(iArr, mod);
int[] iArr4 = div[1];
int[] add = add(iArr2, modMultiply(div[0], iArr3, polynomialGF2mSmallM.coefficients));
iArr2 = iArr3;
iArr3 = add;
iArr = mod;
mod = iArr4;
}
return new PolynomialGF2mSmallM[]{new PolynomialGF2mSmallM(this.field, mod), new PolynomialGF2mSmallM(this.field, iArr3)};
}
public PolynomialGF2mSmallM modMultiply(PolynomialGF2mSmallM polynomialGF2mSmallM, PolynomialGF2mSmallM polynomialGF2mSmallM2) {
return new PolynomialGF2mSmallM(this.field, modMultiply(this.coefficients, polynomialGF2mSmallM.coefficients, polynomialGF2mSmallM2.coefficients));
}
public PolynomialGF2mSmallM modInverse(PolynomialGF2mSmallM polynomialGF2mSmallM) {
return new PolynomialGF2mSmallM(this.field, modDiv(new int[]{1}, this.coefficients, polynomialGF2mSmallM.coefficients));
}
public PolynomialGF2mSmallM modDiv(PolynomialGF2mSmallM polynomialGF2mSmallM, PolynomialGF2mSmallM polynomialGF2mSmallM2) {
return new PolynomialGF2mSmallM(this.field, modDiv(this.coefficients, polynomialGF2mSmallM.coefficients, polynomialGF2mSmallM2.coefficients));
}
public PolynomialGF2mSmallM mod(PolynomialGF2mSmallM polynomialGF2mSmallM) {
return new PolynomialGF2mSmallM(this.field, mod(this.coefficients, polynomialGF2mSmallM.coefficients));
}
public int hashCode() {
int hashCode = this.field.hashCode();
int i = 0;
while (true) {
int[] iArr = this.coefficients;
if (i >= iArr.length) {
return hashCode;
}
hashCode = (hashCode * 31) + iArr[i];
i++;
}
}
public int getHeadCoefficient() {
int i = this.degree;
if (i == -1) {
return 0;
}
return this.coefficients[i];
}
public byte[] getEncoded() {
int i = 8;
int i2 = 1;
while (this.field.getDegree() > i) {
i2++;
i += 8;
}
byte[] bArr = new byte[this.coefficients.length * i2];
int i3 = 0;
for (int i4 = 0; i4 < this.coefficients.length; i4++) {
int i5 = 0;
while (i5 < i) {
bArr[i3] = (byte) (this.coefficients[i4] >>> i5);
i5 += 8;
i3++;
}
}
return bArr;
}
public int getDegree() {
int[] iArr = this.coefficients;
int length = iArr.length - 1;
if (iArr[length] == 0) {
return -1;
}
return length;
}
public int getCoefficient(int i) {
if (i < 0 || i > this.degree) {
return 0;
}
return this.coefficients[i];
}
public PolynomialGF2mSmallM gcd(PolynomialGF2mSmallM polynomialGF2mSmallM) {
return new PolynomialGF2mSmallM(this.field, gcd(this.coefficients, polynomialGF2mSmallM.coefficients));
}
public int evaluateAt(int i) {
int[] iArr = this.coefficients;
int i2 = this.degree;
int i3 = iArr[i2];
while (true) {
i2--;
if (i2 < 0) {
return i3;
}
i3 = this.field.mult(i3, i) ^ this.coefficients[i2];
}
}
public boolean equals(Object obj) {
if (obj == null || !(obj instanceof PolynomialGF2mSmallM)) {
return false;
}
PolynomialGF2mSmallM polynomialGF2mSmallM = (PolynomialGF2mSmallM) obj;
return this.field.equals(polynomialGF2mSmallM.field) && this.degree == polynomialGF2mSmallM.degree && isEqual(this.coefficients, polynomialGF2mSmallM.coefficients);
}
public PolynomialGF2mSmallM[] div(PolynomialGF2mSmallM polynomialGF2mSmallM) {
int[][] div = div(this.coefficients, polynomialGF2mSmallM.coefficients);
return new PolynomialGF2mSmallM[]{new PolynomialGF2mSmallM(this.field, div[0]), new PolynomialGF2mSmallM(this.field, div[1])};
}
public void addToThis(PolynomialGF2mSmallM polynomialGF2mSmallM) {
this.coefficients = add(this.coefficients, polynomialGF2mSmallM.coefficients);
computeDegree();
}
public PolynomialGF2mSmallM addMonomial(int i) {
int[] iArr = new int[i + 1];
iArr[i] = 1;
return new PolynomialGF2mSmallM(this.field, add(this.coefficients, iArr));
}
public PolynomialGF2mSmallM add(PolynomialGF2mSmallM polynomialGF2mSmallM) {
return new PolynomialGF2mSmallM(this.field, add(this.coefficients, polynomialGF2mSmallM.coefficients));
}
private static int[] normalForm(int[] iArr) {
int computeDegree = computeDegree(iArr);
if (computeDegree == -1) {
return new int[1];
}
int i = computeDegree + 1;
if (iArr.length == i) {
return IntUtils.clone(iArr);
}
int[] iArr2 = new int[i];
System.arraycopy(iArr, 0, iArr2, 0, i);
return iArr2;
}
private int[] multiply(int[] iArr, int[] iArr2) {
if (computeDegree(iArr) < computeDegree(iArr2)) {
iArr2 = iArr;
iArr = iArr2;
}
int[] normalForm = normalForm(iArr);
int[] normalForm2 = normalForm(iArr2);
if (normalForm2.length == 1) {
return multWithElement(normalForm, normalForm2[0]);
}
int length = normalForm.length;
int length2 = normalForm2.length;
int[] iArr3 = new int[(length + length2) - 1];
if (length2 != length) {
int[] iArr4 = new int[length2];
int i = length - length2;
int[] iArr5 = new int[i];
System.arraycopy(normalForm, 0, iArr4, 0, length2);
System.arraycopy(normalForm, length2, iArr5, 0, i);
return add(multiply(iArr4, normalForm2), multWithMonomial(multiply(iArr5, normalForm2), length2));
}
int i2 = (length + 1) >>> 1;
int i3 = length - i2;
int[] iArr6 = new int[i2];
int[] iArr7 = new int[i2];
int[] iArr8 = new int[i3];
int[] iArr9 = new int[i3];
System.arraycopy(normalForm, 0, iArr6, 0, i2);
System.arraycopy(normalForm, i2, iArr8, 0, i3);
System.arraycopy(normalForm2, 0, iArr7, 0, i2);
System.arraycopy(normalForm2, i2, iArr9, 0, i3);
int[] add = add(iArr6, iArr8);
int[] add2 = add(iArr7, iArr9);
int[] multiply = multiply(iArr6, iArr7);
int[] multiply2 = multiply(add, add2);
int[] multiply3 = multiply(iArr8, iArr9);
return add(multWithMonomial(add(add(add(multiply2, multiply), multiply3), multWithMonomial(multiply3, i2)), i2), multiply);
}
private static int[] multWithMonomial(int[] iArr, int i) {
int computeDegree = computeDegree(iArr);
if (computeDegree == -1) {
return new int[1];
}
int[] iArr2 = new int[computeDegree + i + 1];
System.arraycopy(iArr, 0, iArr2, i, computeDegree + 1);
return iArr2;
}
private int[] multWithElement(int[] iArr, int i) {
int computeDegree = computeDegree(iArr);
if (computeDegree == -1 || i == 0) {
return new int[1];
}
if (i == 1) {
return IntUtils.clone(iArr);
}
int[] iArr2 = new int[computeDegree + 1];
while (computeDegree >= 0) {
iArr2[computeDegree] = this.field.mult(iArr[computeDegree], i);
computeDegree--;
}
return iArr2;
}
private int[] modMultiply(int[] iArr, int[] iArr2, int[] iArr3) {
return mod(multiply(iArr, iArr2), iArr3);
}
private int[] modDiv(int[] iArr, int[] iArr2, int[] iArr3) {
int[] normalForm = normalForm(iArr3);
int[] mod = mod(iArr2, iArr3);
int[] iArr4 = {0};
int[] mod2 = mod(iArr, iArr3);
while (computeDegree(mod) != -1) {
int[][] div = div(normalForm, mod);
int[] normalForm2 = normalForm(mod);
int[] normalForm3 = normalForm(div[1]);
int[] add = add(iArr4, modMultiply(div[0], mod2, iArr3));
iArr4 = normalForm(mod2);
mod2 = normalForm(add);
normalForm = normalForm2;
mod = normalForm3;
}
return multWithElement(iArr4, this.field.inverse(headCoefficient(normalForm)));
}
private int[] mod(int[] iArr, int[] iArr2) {
int computeDegree = computeDegree(iArr2);
if (computeDegree == -1) {
throw new ArithmeticException("Division by zero");
}
int length = iArr.length;
int[] iArr3 = new int[length];
int inverse = this.field.inverse(headCoefficient(iArr2));
System.arraycopy(iArr, 0, iArr3, 0, length);
while (computeDegree <= computeDegree(iArr3)) {
iArr3 = add(multWithElement(multWithMonomial(iArr2, computeDegree(iArr3) - computeDegree), this.field.mult(headCoefficient(iArr3), inverse)), iArr3);
}
return iArr3;
}
private boolean isIrreducible(int[] iArr) {
if (iArr[0] == 0) {
return false;
}
int computeDegree = computeDegree(iArr);
int[] iArr2 = {0, 1};
int[] iArr3 = {0, 1};
int degree = this.field.getDegree();
for (int i = 0; i < (computeDegree >> 1); i++) {
for (int i2 = degree - 1; i2 >= 0; i2--) {
iArr2 = modMultiply(iArr2, iArr2, iArr);
}
iArr2 = normalForm(iArr2);
if (computeDegree(gcd(add(iArr2, iArr3), iArr)) != 0) {
return false;
}
}
return true;
}
private static boolean isEqual(int[] iArr, int[] iArr2) {
int computeDegree = computeDegree(iArr);
if (computeDegree != computeDegree(iArr2)) {
return false;
}
for (int i = 0; i <= computeDegree; i++) {
if (iArr[i] != iArr2[i]) {
return false;
}
}
return true;
}
private static int headCoefficient(int[] iArr) {
int computeDegree = computeDegree(iArr);
if (computeDegree == -1) {
return 0;
}
return iArr[computeDegree];
}
private int[] gcd(int[] iArr, int[] iArr2) {
if (computeDegree(iArr) == -1) {
return iArr2;
}
while (computeDegree(iArr2) != -1) {
int[] mod = mod(iArr, iArr2);
int length = iArr2.length;
int[] iArr3 = new int[length];
System.arraycopy(iArr2, 0, iArr3, 0, length);
int length2 = mod.length;
int[] iArr4 = new int[length2];
System.arraycopy(mod, 0, iArr4, 0, length2);
iArr2 = iArr4;
iArr = iArr3;
}
return multWithElement(iArr, this.field.inverse(headCoefficient(iArr)));
}
private int[][] div(int[] iArr, int[] iArr2) {
int computeDegree = computeDegree(iArr2);
int computeDegree2 = computeDegree(iArr);
if (computeDegree == -1) {
throw new ArithmeticException("Division by zero.");
}
int[][] iArr3 = {new int[1], new int[computeDegree2 + 1]};
int inverse = this.field.inverse(headCoefficient(iArr2));
iArr3[0][0] = 0;
int[] iArr4 = iArr3[1];
System.arraycopy(iArr, 0, iArr4, 0, iArr4.length);
while (computeDegree <= computeDegree(iArr3[1])) {
int[] iArr5 = {this.field.mult(headCoefficient(iArr3[1]), inverse)};
int[] multWithElement = multWithElement(iArr2, iArr5[0]);
int computeDegree3 = computeDegree(iArr3[1]) - computeDegree;
int[] multWithMonomial = multWithMonomial(multWithElement, computeDegree3);
iArr3[0] = add(multWithMonomial(iArr5, computeDegree3), iArr3[0]);
iArr3[1] = add(multWithMonomial, iArr3[1]);
}
return iArr3;
}
private int[] createRandomIrreduciblePolynomial(int i, SecureRandom secureRandom) {
int[] iArr = new int[i + 1];
iArr[i] = 1;
iArr[0] = this.field.getRandomNonZeroElement(secureRandom);
for (int i2 = 1; i2 < i; i2++) {
iArr[i2] = this.field.getRandomElement(secureRandom);
}
while (!isIrreducible(iArr)) {
int nextInt = RandUtils.nextInt(secureRandom, i);
if (nextInt == 0) {
iArr[0] = this.field.getRandomNonZeroElement(secureRandom);
} else {
iArr[nextInt] = this.field.getRandomElement(secureRandom);
}
}
return iArr;
}
private void computeDegree() {
int length = this.coefficients.length;
do {
length--;
this.degree = length;
if (length < 0) {
return;
}
} while (this.coefficients[length] == 0);
}
private static int computeDegree(int[] iArr) {
int length = iArr.length - 1;
while (length >= 0 && iArr[length] == 0) {
length--;
}
return length;
}
private int[] add(int[] iArr, int[] iArr2) {
int[] iArr3;
if (iArr.length < iArr2.length) {
iArr3 = new int[iArr2.length];
System.arraycopy(iArr2, 0, iArr3, 0, iArr2.length);
} else {
iArr3 = new int[iArr.length];
System.arraycopy(iArr, 0, iArr3, 0, iArr.length);
iArr = iArr2;
}
for (int length = iArr.length - 1; length >= 0; length--) {
iArr3[length] = this.field.add(iArr3[length], iArr[length]);
}
return iArr3;
}
public PolynomialGF2mSmallM(PolynomialGF2mSmallM polynomialGF2mSmallM) {
this.field = polynomialGF2mSmallM.field;
this.degree = polynomialGF2mSmallM.degree;
this.coefficients = IntUtils.clone(polynomialGF2mSmallM.coefficients);
}
public PolynomialGF2mSmallM(GF2mVector gF2mVector) {
this(gF2mVector.getField(), gF2mVector.getIntArrayForm());
}
public PolynomialGF2mSmallM(GF2mField gF2mField, int[] iArr) {
this.field = gF2mField;
this.coefficients = normalForm(iArr);
computeDegree();
}
public PolynomialGF2mSmallM(GF2mField gF2mField, byte[] bArr) {
this.field = gF2mField;
int i = 8;
int i2 = 1;
while (gF2mField.getDegree() > i) {
i2++;
i += 8;
}
if (bArr.length % i2 != 0) {
throw new IllegalArgumentException(" Error: byte array is not encoded polynomial over given finite field GF2m");
}
this.coefficients = new int[bArr.length / i2];
int i3 = 0;
int i4 = 0;
while (true) {
int[] iArr = this.coefficients;
if (i3 >= iArr.length) {
if (iArr.length != 1 && iArr[iArr.length - 1] == 0) {
throw new IllegalArgumentException(" Error: byte array is not encoded polynomial over given finite field GF2m");
}
computeDegree();
return;
}
int i5 = 0;
while (i5 < i) {
int[] iArr2 = this.coefficients;
iArr2[i3] = iArr2[i3] ^ ((bArr[i4] & UnsignedBytes.MAX_VALUE) << i5);
i5 += 8;
i4++;
}
if (!this.field.isElementOfThisField(this.coefficients[i3])) {
throw new IllegalArgumentException(" Error: byte array is not encoded polynomial over given finite field GF2m");
}
i3++;
}
}
public PolynomialGF2mSmallM(GF2mField gF2mField, int i, char c, SecureRandom secureRandom) {
this.field = gF2mField;
if (c == 'I') {
this.coefficients = createRandomIrreduciblePolynomial(i, secureRandom);
computeDegree();
} else {
StringBuilder sb = new StringBuilder(" Error: type ");
sb.append(c);
sb.append(" is not defined for GF2smallmPolynomial");
throw new IllegalArgumentException(sb.toString());
}
}
public PolynomialGF2mSmallM(GF2mField gF2mField, int i) {
this.field = gF2mField;
this.degree = i;
int[] iArr = new int[i + 1];
this.coefficients = iArr;
iArr[i] = 1;
}
public PolynomialGF2mSmallM(GF2mField gF2mField) {
this.field = gF2mField;
this.degree = -1;
this.coefficients = new int[1];
}
}