342 lines
12 KiB
Java
342 lines
12 KiB
Java
|
package org.bouncycastle.math.ec;
|
||
|
|
||
|
import java.math.BigInteger;
|
||
|
|
||
|
/* loaded from: classes6.dex */
|
||
|
public abstract class WNafUtil {
|
||
|
private static final int[] DEFAULT_WINDOW_SIZE_CUTOFFS = {13, 41, 121, 337, 897, 2305};
|
||
|
private static final byte[] EMPTY_BYTES = new byte[0];
|
||
|
private static final int[] EMPTY_INTS = new int[0];
|
||
|
private static final ECPoint[] EMPTY_POINTS = new ECPoint[0];
|
||
|
public static final String PRECOMP_NAME = "bc_wnaf";
|
||
|
|
||
|
private static int[] trim(int[] iArr, int i) {
|
||
|
int[] iArr2 = new int[i];
|
||
|
System.arraycopy(iArr, 0, iArr2, 0, i);
|
||
|
return iArr2;
|
||
|
}
|
||
|
|
||
|
private static byte[] trim(byte[] bArr, int i) {
|
||
|
byte[] bArr2 = new byte[i];
|
||
|
System.arraycopy(bArr, 0, bArr2, 0, i);
|
||
|
return bArr2;
|
||
|
}
|
||
|
|
||
|
private static ECPoint[] resizeTable(ECPoint[] eCPointArr, int i) {
|
||
|
ECPoint[] eCPointArr2 = new ECPoint[i];
|
||
|
System.arraycopy(eCPointArr, 0, eCPointArr2, 0, eCPointArr.length);
|
||
|
return eCPointArr2;
|
||
|
}
|
||
|
|
||
|
public static WNafPreCompInfo precompute(ECPoint eCPoint, int i, boolean z) {
|
||
|
int length;
|
||
|
int i2;
|
||
|
int coordinateSystem;
|
||
|
ECCurve curve = eCPoint.getCurve();
|
||
|
WNafPreCompInfo wNafPreCompInfo = getWNafPreCompInfo(curve.getPreCompInfo(eCPoint, PRECOMP_NAME));
|
||
|
int i3 = 0;
|
||
|
int max = 1 << Math.max(0, i - 2);
|
||
|
ECPoint[] preComp = wNafPreCompInfo.getPreComp();
|
||
|
if (preComp == null) {
|
||
|
preComp = EMPTY_POINTS;
|
||
|
length = 0;
|
||
|
} else {
|
||
|
length = preComp.length;
|
||
|
}
|
||
|
if (length < max) {
|
||
|
preComp = resizeTable(preComp, max);
|
||
|
if (max == 1) {
|
||
|
preComp[0] = eCPoint.normalize();
|
||
|
} else {
|
||
|
if (length == 0) {
|
||
|
preComp[0] = eCPoint;
|
||
|
i2 = 1;
|
||
|
} else {
|
||
|
i2 = length;
|
||
|
}
|
||
|
ECFieldElement eCFieldElement = null;
|
||
|
if (max == 2) {
|
||
|
preComp[1] = eCPoint.threeTimes();
|
||
|
} else {
|
||
|
ECPoint twice = wNafPreCompInfo.getTwice();
|
||
|
ECPoint eCPoint2 = preComp[i2 - 1];
|
||
|
if (twice == null) {
|
||
|
twice = preComp[0].twice();
|
||
|
wNafPreCompInfo.setTwice(twice);
|
||
|
if (ECAlgorithms.isFpCurve(curve) && curve.getFieldSize() >= 64 && ((coordinateSystem = curve.getCoordinateSystem()) == 2 || coordinateSystem == 3 || coordinateSystem == 4)) {
|
||
|
ECFieldElement zCoord = twice.getZCoord(0);
|
||
|
twice = curve.createPoint(twice.getXCoord().toBigInteger(), twice.getYCoord().toBigInteger());
|
||
|
ECFieldElement square = zCoord.square();
|
||
|
eCPoint2 = eCPoint2.scaleX(square).scaleY(square.multiply(zCoord));
|
||
|
if (length == 0) {
|
||
|
preComp[0] = eCPoint2;
|
||
|
}
|
||
|
eCFieldElement = zCoord;
|
||
|
}
|
||
|
}
|
||
|
while (i2 < max) {
|
||
|
eCPoint2 = eCPoint2.add(twice);
|
||
|
preComp[i2] = eCPoint2;
|
||
|
i2++;
|
||
|
}
|
||
|
}
|
||
|
curve.normalizeAll(preComp, length, max - length, eCFieldElement);
|
||
|
}
|
||
|
}
|
||
|
wNafPreCompInfo.setPreComp(preComp);
|
||
|
if (z) {
|
||
|
ECPoint[] preCompNeg = wNafPreCompInfo.getPreCompNeg();
|
||
|
if (preCompNeg == null) {
|
||
|
preCompNeg = new ECPoint[max];
|
||
|
} else {
|
||
|
i3 = preCompNeg.length;
|
||
|
if (i3 < max) {
|
||
|
preCompNeg = resizeTable(preCompNeg, max);
|
||
|
}
|
||
|
}
|
||
|
while (i3 < max) {
|
||
|
preCompNeg[i3] = preComp[i3].negate();
|
||
|
i3++;
|
||
|
}
|
||
|
wNafPreCompInfo.setPreCompNeg(preCompNeg);
|
||
|
}
|
||
|
curve.setPreCompInfo(eCPoint, PRECOMP_NAME, wNafPreCompInfo);
|
||
|
return wNafPreCompInfo;
|
||
|
}
|
||
|
|
||
|
public static ECPoint mapPointWithPrecomp(ECPoint eCPoint, int i, boolean z, ECPointMap eCPointMap) {
|
||
|
ECCurve curve = eCPoint.getCurve();
|
||
|
WNafPreCompInfo precompute = precompute(eCPoint, i, z);
|
||
|
ECPoint map = eCPointMap.map(eCPoint);
|
||
|
WNafPreCompInfo wNafPreCompInfo = getWNafPreCompInfo(curve.getPreCompInfo(map, PRECOMP_NAME));
|
||
|
ECPoint twice = precompute.getTwice();
|
||
|
if (twice != null) {
|
||
|
wNafPreCompInfo.setTwice(eCPointMap.map(twice));
|
||
|
}
|
||
|
ECPoint[] preComp = precompute.getPreComp();
|
||
|
int length = preComp.length;
|
||
|
ECPoint[] eCPointArr = new ECPoint[length];
|
||
|
for (int i2 = 0; i2 < preComp.length; i2++) {
|
||
|
eCPointArr[i2] = eCPointMap.map(preComp[i2]);
|
||
|
}
|
||
|
wNafPreCompInfo.setPreComp(eCPointArr);
|
||
|
if (z) {
|
||
|
ECPoint[] eCPointArr2 = new ECPoint[length];
|
||
|
for (int i3 = 0; i3 < length; i3++) {
|
||
|
eCPointArr2[i3] = eCPointArr[i3].negate();
|
||
|
}
|
||
|
wNafPreCompInfo.setPreCompNeg(eCPointArr2);
|
||
|
}
|
||
|
curve.setPreCompInfo(map, PRECOMP_NAME, wNafPreCompInfo);
|
||
|
return map;
|
||
|
}
|
||
|
|
||
|
public static int getWindowSize(int i, int[] iArr) {
|
||
|
int i2 = 0;
|
||
|
while (i2 < iArr.length && i >= iArr[i2]) {
|
||
|
i2++;
|
||
|
}
|
||
|
return i2 + 2;
|
||
|
}
|
||
|
|
||
|
public static int getWindowSize(int i) {
|
||
|
return getWindowSize(i, DEFAULT_WINDOW_SIZE_CUTOFFS);
|
||
|
}
|
||
|
|
||
|
public static WNafPreCompInfo getWNafPreCompInfo(PreCompInfo preCompInfo) {
|
||
|
return (preCompInfo == null || !(preCompInfo instanceof WNafPreCompInfo)) ? new WNafPreCompInfo() : (WNafPreCompInfo) preCompInfo;
|
||
|
}
|
||
|
|
||
|
public static WNafPreCompInfo getWNafPreCompInfo(ECPoint eCPoint) {
|
||
|
return getWNafPreCompInfo(eCPoint.getCurve().getPreCompInfo(eCPoint, PRECOMP_NAME));
|
||
|
}
|
||
|
|
||
|
public static int getNafWeight(BigInteger bigInteger) {
|
||
|
if (bigInteger.signum() == 0) {
|
||
|
return 0;
|
||
|
}
|
||
|
return bigInteger.shiftLeft(1).add(bigInteger).xor(bigInteger).bitCount();
|
||
|
}
|
||
|
|
||
|
public static byte[] generateWindowNaf(int i, BigInteger bigInteger) {
|
||
|
if (i == 2) {
|
||
|
return generateNaf(bigInteger);
|
||
|
}
|
||
|
if (i < 2 || i > 8) {
|
||
|
throw new IllegalArgumentException("'width' must be in the range [2, 8]");
|
||
|
}
|
||
|
if (bigInteger.signum() == 0) {
|
||
|
return EMPTY_BYTES;
|
||
|
}
|
||
|
int bitLength = bigInteger.bitLength() + 1;
|
||
|
byte[] bArr = new byte[bitLength];
|
||
|
int i2 = 1 << i;
|
||
|
int i3 = 0;
|
||
|
int i4 = 0;
|
||
|
boolean z = false;
|
||
|
while (i3 <= bigInteger.bitLength()) {
|
||
|
if (bigInteger.testBit(i3) == z) {
|
||
|
i3++;
|
||
|
} else {
|
||
|
bigInteger = bigInteger.shiftRight(i3);
|
||
|
int intValue = bigInteger.intValue() & (i2 - 1);
|
||
|
if (z) {
|
||
|
intValue++;
|
||
|
}
|
||
|
z = ((i2 >>> 1) & intValue) != 0;
|
||
|
if (z) {
|
||
|
intValue -= i2;
|
||
|
}
|
||
|
if (i4 > 0) {
|
||
|
i3--;
|
||
|
}
|
||
|
int i5 = i4 + i3;
|
||
|
bArr[i5] = (byte) intValue;
|
||
|
i4 = i5 + 1;
|
||
|
i3 = i;
|
||
|
}
|
||
|
}
|
||
|
return bitLength > i4 ? trim(bArr, i4) : bArr;
|
||
|
}
|
||
|
|
||
|
public static byte[] generateNaf(BigInteger bigInteger) {
|
||
|
if (bigInteger.signum() == 0) {
|
||
|
return EMPTY_BYTES;
|
||
|
}
|
||
|
BigInteger add = bigInteger.shiftLeft(1).add(bigInteger);
|
||
|
int bitLength = add.bitLength();
|
||
|
int i = bitLength - 1;
|
||
|
byte[] bArr = new byte[i];
|
||
|
BigInteger xor = add.xor(bigInteger);
|
||
|
int i2 = 1;
|
||
|
while (i2 < i) {
|
||
|
if (xor.testBit(i2)) {
|
||
|
bArr[i2 - 1] = (byte) (bigInteger.testBit(i2) ? -1 : 1);
|
||
|
i2++;
|
||
|
}
|
||
|
i2++;
|
||
|
}
|
||
|
bArr[bitLength - 2] = 1;
|
||
|
return bArr;
|
||
|
}
|
||
|
|
||
|
public static byte[] generateJSF(BigInteger bigInteger, BigInteger bigInteger2) {
|
||
|
int max = Math.max(bigInteger.bitLength(), bigInteger2.bitLength()) + 1;
|
||
|
byte[] bArr = new byte[max];
|
||
|
int i = 0;
|
||
|
int i2 = 0;
|
||
|
int i3 = 0;
|
||
|
int i4 = 0;
|
||
|
while (true) {
|
||
|
if ((i | i2) == 0 && bigInteger.bitLength() <= i3 && bigInteger2.bitLength() <= i3) {
|
||
|
break;
|
||
|
}
|
||
|
int intValue = (bigInteger.intValue() >>> i3) + i;
|
||
|
int intValue2 = (bigInteger2.intValue() >>> i3) + i2;
|
||
|
int i5 = intValue & 1;
|
||
|
if (i5 != 0) {
|
||
|
i5 -= intValue & 2;
|
||
|
if ((intValue & 7) + i5 == 4 && (intValue2 & 3) == 2) {
|
||
|
i5 = -i5;
|
||
|
}
|
||
|
}
|
||
|
int i6 = intValue2 & 1;
|
||
|
if (i6 != 0) {
|
||
|
i6 -= intValue2 & 2;
|
||
|
if ((intValue2 & 7) + i6 == 4 && (intValue & 3) == 2) {
|
||
|
i6 = -i6;
|
||
|
}
|
||
|
}
|
||
|
if ((i << 1) == i5 + 1) {
|
||
|
i ^= 1;
|
||
|
}
|
||
|
if ((i2 << 1) == i6 + 1) {
|
||
|
i2 ^= 1;
|
||
|
}
|
||
|
i3++;
|
||
|
if (i3 == 30) {
|
||
|
bigInteger = bigInteger.shiftRight(30);
|
||
|
bigInteger2 = bigInteger2.shiftRight(30);
|
||
|
i3 = 0;
|
||
|
}
|
||
|
bArr[i4] = (byte) ((i6 & 15) | (i5 << 4));
|
||
|
i4++;
|
||
|
}
|
||
|
return max > i4 ? trim(bArr, i4) : bArr;
|
||
|
}
|
||
|
|
||
|
public static int[] generateCompactWindowNaf(int i, BigInteger bigInteger) {
|
||
|
if (i == 2) {
|
||
|
return generateCompactNaf(bigInteger);
|
||
|
}
|
||
|
if (i < 2 || i > 16) {
|
||
|
throw new IllegalArgumentException("'width' must be in the range [2, 16]");
|
||
|
}
|
||
|
if ((bigInteger.bitLength() >>> 16) != 0) {
|
||
|
throw new IllegalArgumentException("'k' must have bitlength < 2^16");
|
||
|
}
|
||
|
if (bigInteger.signum() == 0) {
|
||
|
return EMPTY_INTS;
|
||
|
}
|
||
|
int bitLength = (bigInteger.bitLength() / i) + 1;
|
||
|
int[] iArr = new int[bitLength];
|
||
|
int i2 = 1 << i;
|
||
|
int i3 = 0;
|
||
|
int i4 = 0;
|
||
|
boolean z = false;
|
||
|
while (i3 <= bigInteger.bitLength()) {
|
||
|
if (bigInteger.testBit(i3) == z) {
|
||
|
i3++;
|
||
|
} else {
|
||
|
bigInteger = bigInteger.shiftRight(i3);
|
||
|
int intValue = bigInteger.intValue() & (i2 - 1);
|
||
|
if (z) {
|
||
|
intValue++;
|
||
|
}
|
||
|
z = ((i2 >>> 1) & intValue) != 0;
|
||
|
if (z) {
|
||
|
intValue -= i2;
|
||
|
}
|
||
|
if (i4 > 0) {
|
||
|
i3--;
|
||
|
}
|
||
|
iArr[i4] = i3 | (intValue << 16);
|
||
|
i4++;
|
||
|
i3 = i;
|
||
|
}
|
||
|
}
|
||
|
return bitLength > i4 ? trim(iArr, i4) : iArr;
|
||
|
}
|
||
|
|
||
|
public static int[] generateCompactNaf(BigInteger bigInteger) {
|
||
|
if ((bigInteger.bitLength() >>> 16) != 0) {
|
||
|
throw new IllegalArgumentException("'k' must have bitlength < 2^16");
|
||
|
}
|
||
|
if (bigInteger.signum() == 0) {
|
||
|
return EMPTY_INTS;
|
||
|
}
|
||
|
BigInteger add = bigInteger.shiftLeft(1).add(bigInteger);
|
||
|
int bitLength = add.bitLength();
|
||
|
int i = bitLength >> 1;
|
||
|
int[] iArr = new int[i];
|
||
|
BigInteger xor = add.xor(bigInteger);
|
||
|
int i2 = 0;
|
||
|
int i3 = 1;
|
||
|
int i4 = 0;
|
||
|
while (i3 < bitLength - 1) {
|
||
|
if (xor.testBit(i3)) {
|
||
|
iArr[i2] = i4 | ((bigInteger.testBit(i3) ? -1 : 1) << 16);
|
||
|
i3++;
|
||
|
i2++;
|
||
|
i4 = 1;
|
||
|
} else {
|
||
|
i4++;
|
||
|
}
|
||
|
i3++;
|
||
|
}
|
||
|
int i5 = i2 + 1;
|
||
|
iArr[i2] = 65536 | i4;
|
||
|
return i > i5 ? trim(iArr, i5) : iArr;
|
||
|
}
|
||
|
}
|