what-the-bank/sources/org/bouncycastle/crypto/engines/Salsa20Engine.java

468 lines
15 KiB
Java
Raw Permalink Normal View History

2024-07-27 18:17:47 +07:00
package org.bouncycastle.crypto.engines;
import io.flutter.embedding.android.KeyboardMap;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.DataLengthException;
import org.bouncycastle.crypto.MaxBytesExceededException;
import org.bouncycastle.crypto.OutputLengthException;
import org.bouncycastle.crypto.SkippingStreamCipher;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.ParametersWithIV;
import org.bouncycastle.util.Pack;
import org.bouncycastle.util.Strings;
/* loaded from: classes6.dex */
public class Salsa20Engine implements SkippingStreamCipher {
public static final int DEFAULT_ROUNDS = 20;
private static final int STATE_SIZE = 16;
private static final int[] TAU_SIGMA = Pack.littleEndianToInt(Strings.toByteArray("expand 16-byte kexpand 32-byte k"), 0, 8);
protected static final byte[] sigma = Strings.toByteArray("expand 32-byte k");
protected static final byte[] tau = Strings.toByteArray("expand 16-byte k");
private int cW0;
private int cW1;
private int cW2;
protected int[] engineState;
private int index;
private boolean initialised;
private byte[] keyStream;
protected int rounds;
protected int[] x;
/* JADX INFO: Access modifiers changed from: protected */
public static int rotl(int i, int i2) {
return (i << i2) | (i >>> (-i2));
}
protected int getNonceSize() {
return 8;
}
@Override // org.bouncycastle.crypto.SkippingCipher
public long skip(long j) {
long j2;
if (j >= 0) {
if (j >= 64) {
long j3 = j / 64;
advanceCounter(j3);
j2 = j - (j3 << 6);
} else {
j2 = j;
}
int i = this.index;
int i2 = (((int) j2) + i) & 63;
this.index = i2;
if (i2 < i) {
advanceCounter();
}
} else {
long j4 = -j;
if (j4 >= 64) {
long j5 = j4 / 64;
retreatCounter(j5);
j4 -= j5 << 6;
}
for (long j6 = 0; j6 < j4; j6++) {
if (this.index == 0) {
retreatCounter();
}
this.index = (this.index - 1) & 63;
}
}
generateKeyStream(this.keyStream);
return j;
}
/* JADX INFO: Access modifiers changed from: protected */
public void setKey(byte[] bArr, byte[] bArr2) {
if (bArr != null) {
if (bArr.length != 16 && bArr.length != 32) {
StringBuilder sb = new StringBuilder();
sb.append(getAlgorithmName());
sb.append(" requires 128 bit or 256 bit key");
throw new IllegalArgumentException(sb.toString());
}
int length = (bArr.length - 16) / 4;
int[] iArr = this.engineState;
int[] iArr2 = TAU_SIGMA;
iArr[0] = iArr2[length];
iArr[5] = iArr2[length + 1];
iArr[10] = iArr2[length + 2];
iArr[15] = iArr2[length + 3];
Pack.littleEndianToInt(bArr, 0, iArr, 1, 4);
Pack.littleEndianToInt(bArr, bArr.length - 16, this.engineState, 11, 4);
}
Pack.littleEndianToInt(bArr2, 0, this.engineState, 6, 2);
}
@Override // org.bouncycastle.crypto.SkippingCipher
public long seekTo(long j) {
reset();
return skip(j);
}
@Override // org.bouncycastle.crypto.StreamCipher
public byte returnByte(byte b) {
if (limitExceeded()) {
throw new MaxBytesExceededException("2^70 byte limit per IV; Change IV");
}
byte[] bArr = this.keyStream;
int i = this.index;
byte b2 = (byte) (b ^ bArr[i]);
int i2 = (i + 1) & 63;
this.index = i2;
if (i2 == 0) {
advanceCounter();
generateKeyStream(this.keyStream);
}
return b2;
}
protected void retreatCounter(long j) {
int i = (int) (j >>> 32);
int i2 = (int) j;
if (i != 0) {
int[] iArr = this.engineState;
int i3 = iArr[9];
if ((i3 & KeyboardMap.kValueMask) < (i & KeyboardMap.kValueMask)) {
throw new IllegalStateException("attempt to reduce counter past zero.");
}
iArr[9] = i3 - i;
}
int[] iArr2 = this.engineState;
int i4 = iArr2[8];
if ((i4 & KeyboardMap.kValueMask) >= (KeyboardMap.kValueMask & i2)) {
iArr2[8] = i4 - i2;
return;
}
int i5 = iArr2[9];
if (i5 == 0) {
throw new IllegalStateException("attempt to reduce counter past zero.");
}
iArr2[9] = i5 - 1;
iArr2[8] = i4 - i2;
}
protected void retreatCounter() {
int[] iArr = this.engineState;
int i = iArr[8];
if (i == 0 && iArr[9] == 0) {
throw new IllegalStateException("attempt to reduce counter past zero.");
}
int i2 = i - 1;
iArr[8] = i2;
if (i2 == -1) {
iArr[9] = iArr[9] - 1;
}
}
protected void resetCounter() {
int[] iArr = this.engineState;
iArr[9] = 0;
iArr[8] = 0;
}
@Override // org.bouncycastle.crypto.StreamCipher
public void reset() {
this.index = 0;
resetLimitCounter();
resetCounter();
generateKeyStream(this.keyStream);
}
@Override // org.bouncycastle.crypto.StreamCipher
public int processBytes(byte[] bArr, int i, int i2, byte[] bArr2, int i3) {
if (!this.initialised) {
StringBuilder sb = new StringBuilder();
sb.append(getAlgorithmName());
sb.append(" not initialised");
throw new IllegalStateException(sb.toString());
}
if (i + i2 > bArr.length) {
throw new DataLengthException("input buffer too short");
}
if (i3 + i2 > bArr2.length) {
throw new OutputLengthException("output buffer too short");
}
if (limitExceeded(i2)) {
throw new MaxBytesExceededException("2^70 byte limit per IV would be exceeded; Change IV");
}
for (int i4 = 0; i4 < i2; i4++) {
byte[] bArr3 = this.keyStream;
int i5 = this.index;
bArr2[i4 + i3] = (byte) (bArr3[i5] ^ bArr[i4 + i]);
int i6 = (i5 + 1) & 63;
this.index = i6;
if (i6 == 0) {
advanceCounter();
generateKeyStream(this.keyStream);
}
}
return i2;
}
/* JADX INFO: Access modifiers changed from: protected */
public void packTauOrSigma(int i, int[] iArr, int i2) {
int i3 = (i - 16) / 4;
int[] iArr2 = TAU_SIGMA;
iArr[i2] = iArr2[i3];
iArr[i2 + 1] = iArr2[i3 + 1];
iArr[i2 + 2] = iArr2[i3 + 2];
iArr[i2 + 3] = iArr2[i3 + 3];
}
@Override // org.bouncycastle.crypto.StreamCipher
public void init(boolean z, CipherParameters cipherParameters) {
if (!(cipherParameters instanceof ParametersWithIV)) {
StringBuilder sb = new StringBuilder();
sb.append(getAlgorithmName());
sb.append(" Init parameters must include an IV");
throw new IllegalArgumentException(sb.toString());
}
ParametersWithIV parametersWithIV = (ParametersWithIV) cipherParameters;
byte[] iv = parametersWithIV.getIV();
if (iv == null || iv.length != getNonceSize()) {
StringBuilder sb2 = new StringBuilder();
sb2.append(getAlgorithmName());
sb2.append(" requires exactly ");
sb2.append(getNonceSize());
sb2.append(" bytes of IV");
throw new IllegalArgumentException(sb2.toString());
}
CipherParameters parameters = parametersWithIV.getParameters();
if (parameters == null) {
if (!this.initialised) {
StringBuilder sb3 = new StringBuilder();
sb3.append(getAlgorithmName());
sb3.append(" KeyParameter can not be null for first initialisation");
throw new IllegalStateException(sb3.toString());
}
setKey(null, iv);
} else {
if (!(parameters instanceof KeyParameter)) {
StringBuilder sb4 = new StringBuilder();
sb4.append(getAlgorithmName());
sb4.append(" Init parameters must contain a KeyParameter (or null for re-init)");
throw new IllegalArgumentException(sb4.toString());
}
setKey(((KeyParameter) parameters).getKey(), iv);
}
reset();
this.initialised = true;
}
@Override // org.bouncycastle.crypto.SkippingCipher
public long getPosition() {
return (getCounter() << 6) + this.index;
}
protected long getCounter() {
int[] iArr = this.engineState;
return (iArr[9] << 32) | (iArr[8] & KeyboardMap.kValueMask);
}
@Override // org.bouncycastle.crypto.StreamCipher
public String getAlgorithmName() {
if (this.rounds == 20) {
return "Salsa20";
}
StringBuilder sb = new StringBuilder("Salsa20/");
sb.append(this.rounds);
return sb.toString();
}
protected void generateKeyStream(byte[] bArr) {
salsaCore(this.rounds, this.engineState, this.x);
Pack.intToLittleEndian(this.x, bArr, 0);
}
protected void advanceCounter(long j) {
int i = (int) (j >>> 32);
int i2 = (int) j;
if (i > 0) {
int[] iArr = this.engineState;
iArr[9] = iArr[9] + i;
}
int[] iArr2 = this.engineState;
int i3 = iArr2[8];
int i4 = i2 + i3;
iArr2[8] = i4;
if (i3 == 0 || i4 >= i3) {
return;
}
iArr2[9] = iArr2[9] + 1;
}
protected void advanceCounter() {
int[] iArr = this.engineState;
int i = iArr[8] + 1;
iArr[8] = i;
if (i == 0) {
iArr[9] = iArr[9] + 1;
}
}
public static void salsaCore(int i, int[] iArr, int[] iArr2) {
if (iArr.length != 16) {
throw new IllegalArgumentException();
}
if (iArr2.length != 16) {
throw new IllegalArgumentException();
}
if (i % 2 != 0) {
throw new IllegalArgumentException("Number of rounds must be even");
}
boolean z = false;
int i2 = iArr[0];
int i3 = iArr[1];
int i4 = iArr[2];
int i5 = iArr[3];
int i6 = iArr[4];
int i7 = iArr[5];
int i8 = iArr[6];
int i9 = 7;
int i10 = iArr[7];
int i11 = iArr[8];
int i12 = 9;
int i13 = iArr[9];
int i14 = iArr[10];
int i15 = iArr[11];
int i16 = iArr[12];
int i17 = 13;
int i18 = iArr[13];
int i19 = iArr[14];
int i20 = iArr[15];
int i21 = i19;
int i22 = i18;
int i23 = i16;
int i24 = i15;
int i25 = i14;
int i26 = i13;
int i27 = i11;
int i28 = i10;
int i29 = i8;
int i30 = i7;
int i31 = i6;
int i32 = i5;
int i33 = i4;
int i34 = i3;
int i35 = i2;
int i36 = i;
while (i36 > 0) {
int rotl = rotl(i35 + i23, i9) ^ i31;
int rotl2 = i27 ^ rotl(rotl + i35, i12);
int rotl3 = i23 ^ rotl(rotl2 + rotl, i17);
int rotl4 = rotl(rotl3 + rotl2, 18) ^ i35;
int rotl5 = i26 ^ rotl(i30 + i34, i9);
int rotl6 = i22 ^ rotl(rotl5 + i30, i12);
int rotl7 = i34 ^ rotl(rotl6 + rotl5, i17);
int rotl8 = rotl(rotl7 + rotl6, 18) ^ i30;
int rotl9 = i21 ^ rotl(i25 + i29, 7);
int rotl10 = i33 ^ rotl(rotl9 + i25, 9);
int rotl11 = i29 ^ rotl(rotl10 + rotl9, 13);
int rotl12 = i25 ^ rotl(rotl11 + rotl10, 18);
int rotl13 = i32 ^ rotl(i20 + i24, 7);
int rotl14 = i28 ^ rotl(rotl13 + i20, 9);
int i37 = i36;
int rotl15 = i24 ^ rotl(rotl14 + rotl13, 13);
int rotl16 = i20 ^ rotl(rotl15 + rotl14, 18);
i34 = rotl7 ^ rotl(rotl4 + rotl13, 7);
i33 = rotl10 ^ rotl(i34 + rotl4, 9);
int rotl17 = rotl13 ^ rotl(i33 + i34, 13);
int rotl18 = rotl(rotl17 + i33, 18);
int rotl19 = rotl11 ^ rotl(rotl8 + rotl, 7);
i28 = rotl14 ^ rotl(rotl19 + rotl8, 9);
int rotl20 = rotl(i28 + rotl19, 13) ^ rotl;
int rotl21 = rotl(rotl20 + i28, 18) ^ rotl8;
i24 = rotl15 ^ rotl(rotl12 + rotl5, 7);
int rotl22 = rotl(i24 + rotl12, 9) ^ rotl2;
i26 = rotl5 ^ rotl(rotl22 + i24, 13);
i25 = rotl12 ^ rotl(i26 + rotl22, 18);
i23 = rotl3 ^ rotl(rotl16 + rotl9, 7);
i22 = rotl6 ^ rotl(i23 + rotl16, 9);
i21 = rotl9 ^ rotl(i22 + i23, 13);
i20 = rotl16 ^ rotl(i21 + i22, 18);
i35 = rotl4 ^ rotl18;
i27 = rotl22;
i31 = rotl20;
i30 = rotl21;
i32 = rotl17;
z = false;
i17 = 13;
i12 = 9;
i9 = 7;
i29 = rotl19;
i36 = i37 - 2;
}
boolean z2 = z;
iArr2[z2 ? 1 : 0] = i35 + iArr[z2 ? 1 : 0];
iArr2[1] = i34 + iArr[1];
iArr2[2] = i33 + iArr[2];
iArr2[3] = i32 + iArr[3];
iArr2[4] = i31 + iArr[4];
iArr2[5] = i30 + iArr[5];
iArr2[6] = i29 + iArr[6];
iArr2[7] = i28 + iArr[7];
iArr2[8] = i27 + iArr[8];
iArr2[9] = i26 + iArr[9];
iArr2[10] = i25 + iArr[10];
iArr2[11] = i24 + iArr[11];
iArr2[12] = i23 + iArr[12];
iArr2[13] = i22 + iArr[13];
iArr2[14] = i21 + iArr[14];
iArr2[15] = i20 + iArr[15];
}
private void resetLimitCounter() {
this.cW0 = 0;
this.cW1 = 0;
this.cW2 = 0;
}
private boolean limitExceeded(int i) {
int i2 = this.cW0 + i;
this.cW0 = i2;
if (i2 >= i || i2 < 0) {
return false;
}
int i3 = this.cW1 + 1;
this.cW1 = i3;
if (i3 != 0) {
return false;
}
int i4 = this.cW2 + 1;
this.cW2 = i4;
return (i4 & 32) != 0;
}
private boolean limitExceeded() {
int i = this.cW0 + 1;
this.cW0 = i;
if (i == 0) {
int i2 = this.cW1 + 1;
this.cW1 = i2;
if (i2 == 0) {
int i3 = this.cW2 + 1;
this.cW2 = i3;
return (i3 & 32) != 0;
}
}
return false;
}
public Salsa20Engine(int i) {
this.index = 0;
this.engineState = new int[16];
this.x = new int[16];
this.keyStream = new byte[64];
this.initialised = false;
if (i <= 0 || (i & 1) != 0) {
throw new IllegalArgumentException("'rounds' must be a positive, even number");
}
this.rounds = i;
}
public Salsa20Engine() {
this(20);
}
}