what-the-bank/sources/org/bouncycastle/crypto/modes/SICBlockCipher.java

253 lines
8.0 KiB
Java
Raw Permalink Normal View History

2024-07-27 18:17:47 +07:00
package org.bouncycastle.crypto.modes;
import com.google.common.primitives.UnsignedBytes;
import org.bouncycastle.crypto.BlockCipher;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.DataLengthException;
import org.bouncycastle.crypto.SkippingStreamCipher;
import org.bouncycastle.crypto.StreamBlockCipher;
import org.bouncycastle.crypto.params.ParametersWithIV;
import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.Pack;
/* loaded from: classes6.dex */
public class SICBlockCipher extends StreamBlockCipher implements SkippingStreamCipher {
private byte[] IV;
private final int blockSize;
private int byteCount;
private final BlockCipher cipher;
private byte[] counter;
private byte[] counterOut;
@Override // org.bouncycastle.crypto.SkippingCipher
public long skip(long j) {
adjustCounter(j);
checkCounter();
this.cipher.processBlock(this.counter, 0, this.counterOut, 0);
return j;
}
@Override // org.bouncycastle.crypto.SkippingCipher
public long seekTo(long j) {
reset();
return skip(j);
}
@Override // org.bouncycastle.crypto.BlockCipher
public void reset() {
Arrays.fill(this.counter, (byte) 0);
byte[] bArr = this.IV;
System.arraycopy(bArr, 0, this.counter, 0, bArr.length);
this.cipher.reset();
this.byteCount = 0;
}
@Override // org.bouncycastle.crypto.BlockCipher
public int processBlock(byte[] bArr, int i, byte[] bArr2, int i2) throws DataLengthException, IllegalStateException {
processBytes(bArr, i, this.blockSize, bArr2, i2);
return this.blockSize;
}
@Override // org.bouncycastle.crypto.BlockCipher
public void init(boolean z, CipherParameters cipherParameters) throws IllegalArgumentException {
if (!(cipherParameters instanceof ParametersWithIV)) {
throw new IllegalArgumentException("CTR/SIC mode requires ParametersWithIV");
}
ParametersWithIV parametersWithIV = (ParametersWithIV) cipherParameters;
byte[] clone = Arrays.clone(parametersWithIV.getIV());
this.IV = clone;
int i = this.blockSize;
if (i < clone.length) {
StringBuilder sb = new StringBuilder("CTR/SIC mode requires IV no greater than: ");
sb.append(this.blockSize);
sb.append(" bytes.");
throw new IllegalArgumentException(sb.toString());
}
int i2 = i / 2;
if (8 <= i2) {
i2 = 8;
}
if (i - clone.length <= i2) {
if (parametersWithIV.getParameters() != null) {
this.cipher.init(true, parametersWithIV.getParameters());
}
reset();
} else {
StringBuilder sb2 = new StringBuilder("CTR/SIC mode requires IV of at least: ");
sb2.append(this.blockSize - i2);
sb2.append(" bytes.");
throw new IllegalArgumentException(sb2.toString());
}
}
@Override // org.bouncycastle.crypto.SkippingCipher
public long getPosition() {
byte[] bArr = this.counter;
int length = bArr.length;
byte[] bArr2 = new byte[length];
System.arraycopy(bArr, 0, bArr2, 0, length);
int i = length - 1;
while (i > 0) {
byte[] bArr3 = this.IV;
int i2 = i < bArr3.length ? (bArr2[i] & UnsignedBytes.MAX_VALUE) - (bArr3[i] & UnsignedBytes.MAX_VALUE) : bArr2[i] & UnsignedBytes.MAX_VALUE;
if (i2 < 0) {
bArr2[i - 1] = (byte) (bArr2[r3] - 1);
i2 += 256;
}
bArr2[i] = (byte) i2;
i--;
}
return (Pack.bigEndianToLong(bArr2, length - 8) * this.blockSize) + this.byteCount;
}
@Override // org.bouncycastle.crypto.BlockCipher
public int getBlockSize() {
return this.cipher.getBlockSize();
}
@Override // org.bouncycastle.crypto.BlockCipher
public String getAlgorithmName() {
StringBuilder sb = new StringBuilder();
sb.append(this.cipher.getAlgorithmName());
sb.append("/SIC");
return sb.toString();
}
@Override // org.bouncycastle.crypto.StreamBlockCipher
public byte calculateByte(byte b) throws DataLengthException, IllegalStateException {
int i = this.byteCount;
if (i == 0) {
this.cipher.processBlock(this.counter, 0, this.counterOut, 0);
byte[] bArr = this.counterOut;
int i2 = this.byteCount;
this.byteCount = i2 + 1;
return (byte) (b ^ bArr[i2]);
}
byte[] bArr2 = this.counterOut;
int i3 = i + 1;
this.byteCount = i3;
byte b2 = (byte) (b ^ bArr2[i]);
if (i3 == this.counter.length) {
this.byteCount = 0;
incrementCounterAt(0);
checkCounter();
}
return b2;
}
private void incrementCounterAt(int i) {
byte b;
int length = this.counter.length - i;
do {
length--;
if (length < 0) {
return;
}
byte[] bArr = this.counter;
b = (byte) (bArr[length] + 1);
bArr[length] = b;
} while (b == 0);
}
private void incrementCounter(int i) {
byte[] bArr = this.counter;
byte b = bArr[bArr.length - 1];
int length = bArr.length - 1;
bArr[length] = (byte) (bArr[length] + i);
if (b == 0 || bArr[bArr.length - 1] >= b) {
return;
}
incrementCounterAt(1);
}
private void decrementCounterAt(int i) {
byte b;
int length = this.counter.length - i;
do {
length--;
if (length < 0) {
return;
}
b = (byte) (r1[length] - 1);
this.counter[length] = b;
} while (b == -1);
}
private void checkCounter() {
if (this.IV.length >= this.blockSize) {
return;
}
int i = 0;
while (true) {
byte[] bArr = this.IV;
if (i == bArr.length) {
return;
}
if (this.counter[i] != bArr[i]) {
throw new IllegalStateException("Counter in CTR/SIC mode out of range.");
}
i++;
}
}
private void adjustCounter(long j) {
long j2;
long j3;
int i = 5;
if (j >= 0) {
long j4 = (this.byteCount + j) / this.blockSize;
if (j4 > 255) {
j3 = j4;
while (i > 0) {
long j5 = 1 << (i << 3);
while (j3 >= j5) {
incrementCounterAt(i);
j3 -= j5;
}
i--;
}
} else {
j3 = j4;
}
incrementCounter((int) j3);
this.byteCount = (int) ((j + this.byteCount) - (this.blockSize * j4));
return;
}
long j6 = ((-j) - this.byteCount) / this.blockSize;
if (j6 > 255) {
j2 = j6;
while (i > 0) {
long j7 = 1 << (i << 3);
while (j2 > j7) {
decrementCounterAt(i);
j2 -= j7;
}
i--;
}
} else {
j2 = j6;
}
for (long j8 = 0; j8 != j2; j8++) {
decrementCounterAt(0);
}
int i2 = (int) (this.byteCount + j + (this.blockSize * j6));
if (i2 >= 0) {
this.byteCount = 0;
} else {
decrementCounterAt(0);
this.byteCount = this.blockSize + i2;
}
}
public SICBlockCipher(BlockCipher blockCipher) {
super(blockCipher);
this.cipher = blockCipher;
int blockSize = blockCipher.getBlockSize();
this.blockSize = blockSize;
this.IV = new byte[blockSize];
this.counter = new byte[blockSize];
this.counterOut = new byte[blockSize];
this.byteCount = 0;
}
}