189 lines
6.5 KiB
Java
189 lines
6.5 KiB
Java
package org.bouncycastle.crypto.engines;
|
|
|
|
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.OutputLengthException;
|
|
import org.bouncycastle.crypto.params.KeyParameter;
|
|
|
|
/* loaded from: classes6.dex */
|
|
public class RC6Engine implements BlockCipher {
|
|
private static final int LGW = 5;
|
|
private static final int P32 = -1209970333;
|
|
private static final int Q32 = -1640531527;
|
|
private static final int _noRounds = 20;
|
|
private static final int bytesPerWord = 4;
|
|
private static final int wordSize = 32;
|
|
private int[] _S = null;
|
|
private boolean forEncryption;
|
|
|
|
private int rotateLeft(int i, int i2) {
|
|
return (i << i2) | (i >>> (-i2));
|
|
}
|
|
|
|
private int rotateRight(int i, int i2) {
|
|
return (i >>> i2) | (i << (-i2));
|
|
}
|
|
|
|
@Override // org.bouncycastle.crypto.BlockCipher
|
|
public int getBlockSize() {
|
|
return 16;
|
|
}
|
|
|
|
@Override // org.bouncycastle.crypto.BlockCipher
|
|
public void reset() {
|
|
}
|
|
|
|
@Override // org.bouncycastle.crypto.BlockCipher
|
|
public int processBlock(byte[] bArr, int i, byte[] bArr2, int i2) {
|
|
int blockSize = getBlockSize();
|
|
if (this._S == null) {
|
|
throw new IllegalStateException("RC6 engine not initialised");
|
|
}
|
|
if (i + blockSize > bArr.length) {
|
|
throw new DataLengthException("input buffer too short");
|
|
}
|
|
if (blockSize + i2 <= bArr2.length) {
|
|
return this.forEncryption ? encryptBlock(bArr, i, bArr2, i2) : decryptBlock(bArr, i, bArr2, i2);
|
|
}
|
|
throw new OutputLengthException("output buffer too short");
|
|
}
|
|
|
|
@Override // org.bouncycastle.crypto.BlockCipher
|
|
public void init(boolean z, CipherParameters cipherParameters) {
|
|
if (cipherParameters instanceof KeyParameter) {
|
|
this.forEncryption = z;
|
|
setKey(((KeyParameter) cipherParameters).getKey());
|
|
} else {
|
|
StringBuilder sb = new StringBuilder("invalid parameter passed to RC6 init - ");
|
|
sb.append(cipherParameters.getClass().getName());
|
|
throw new IllegalArgumentException(sb.toString());
|
|
}
|
|
}
|
|
|
|
@Override // org.bouncycastle.crypto.BlockCipher
|
|
public String getAlgorithmName() {
|
|
return "RC6";
|
|
}
|
|
|
|
private void wordToBytes(int i, byte[] bArr, int i2) {
|
|
for (int i3 = 0; i3 < 4; i3++) {
|
|
bArr[i3 + i2] = (byte) i;
|
|
i >>>= 8;
|
|
}
|
|
}
|
|
|
|
private void setKey(byte[] bArr) {
|
|
int[] iArr;
|
|
int length = (bArr.length + 3) / 4;
|
|
int length2 = (bArr.length + 3) / 4;
|
|
int[] iArr2 = new int[length2];
|
|
for (int length3 = bArr.length - 1; length3 >= 0; length3--) {
|
|
int i = length3 / 4;
|
|
iArr2[i] = (iArr2[i] << 8) + (bArr[length3] & UnsignedBytes.MAX_VALUE);
|
|
}
|
|
int[] iArr3 = new int[44];
|
|
this._S = iArr3;
|
|
iArr3[0] = P32;
|
|
int i2 = 1;
|
|
while (true) {
|
|
iArr = this._S;
|
|
if (i2 >= iArr.length) {
|
|
break;
|
|
}
|
|
iArr[i2] = iArr[i2 - 1] - 1640531527;
|
|
i2++;
|
|
}
|
|
int length4 = length2 > iArr.length ? length2 * 3 : iArr.length * 3;
|
|
int i3 = 0;
|
|
int i4 = 0;
|
|
int i5 = 0;
|
|
int i6 = 0;
|
|
for (int i7 = 0; i7 < length4; i7++) {
|
|
int[] iArr4 = this._S;
|
|
i4 = rotateLeft(iArr4[i3] + i4 + i5, 3);
|
|
iArr4[i3] = i4;
|
|
i5 = rotateLeft(iArr2[i6] + i4 + i5, i5 + i4);
|
|
iArr2[i6] = i5;
|
|
i3 = (i3 + 1) % this._S.length;
|
|
i6 = (i6 + 1) % length2;
|
|
}
|
|
}
|
|
|
|
private int encryptBlock(byte[] bArr, int i, byte[] bArr2, int i2) {
|
|
int bytesToWord = bytesToWord(bArr, i);
|
|
int bytesToWord2 = bytesToWord(bArr, i + 4);
|
|
int bytesToWord3 = bytesToWord(bArr, i + 8);
|
|
int bytesToWord4 = bytesToWord(bArr, i + 12);
|
|
int[] iArr = this._S;
|
|
int i3 = bytesToWord2 + iArr[0];
|
|
int i4 = bytesToWord4 + iArr[1];
|
|
int i5 = 1;
|
|
while (i5 <= 20) {
|
|
int rotateLeft = rotateLeft(((i3 << 1) + 1) * i3, 5);
|
|
int rotateLeft2 = rotateLeft(((i4 << 1) + 1) * i4, 5);
|
|
int rotateLeft3 = rotateLeft(bytesToWord ^ rotateLeft, rotateLeft2);
|
|
int i6 = i5 << 1;
|
|
int i7 = this._S[i6];
|
|
i5++;
|
|
int rotateLeft4 = rotateLeft(bytesToWord3 ^ rotateLeft2, rotateLeft) + this._S[i6 + 1];
|
|
bytesToWord3 = i4;
|
|
i4 = rotateLeft3 + i7;
|
|
bytesToWord = i3;
|
|
i3 = rotateLeft4;
|
|
}
|
|
int[] iArr2 = this._S;
|
|
int i8 = iArr2[42];
|
|
int i9 = iArr2[43];
|
|
wordToBytes(bytesToWord + i8, bArr2, i2);
|
|
wordToBytes(i3, bArr2, i2 + 4);
|
|
wordToBytes(bytesToWord3 + i9, bArr2, i2 + 8);
|
|
wordToBytes(i4, bArr2, i2 + 12);
|
|
return 16;
|
|
}
|
|
|
|
private int decryptBlock(byte[] bArr, int i, byte[] bArr2, int i2) {
|
|
int bytesToWord = bytesToWord(bArr, i);
|
|
int bytesToWord2 = bytesToWord(bArr, i + 4);
|
|
int bytesToWord3 = bytesToWord(bArr, i + 8);
|
|
int bytesToWord4 = bytesToWord(bArr, i + 12);
|
|
int[] iArr = this._S;
|
|
int i3 = bytesToWord3 - iArr[43];
|
|
int i4 = bytesToWord - iArr[42];
|
|
int i5 = bytesToWord4;
|
|
int i6 = i3;
|
|
int i7 = bytesToWord2;
|
|
int i8 = i4;
|
|
int i9 = 20;
|
|
while (i9 > 0) {
|
|
int rotateLeft = rotateLeft(((i8 << 1) + 1) * i8, 5);
|
|
int rotateLeft2 = rotateLeft(((i6 << 1) + 1) * i6, 5);
|
|
int i10 = i9 << 1;
|
|
int rotateRight = rotateRight(i7 - this._S[i10 + 1], rotateLeft);
|
|
i9--;
|
|
int rotateRight2 = rotateRight(i5 - this._S[i10], rotateLeft2) ^ rotateLeft;
|
|
i5 = i6;
|
|
i6 = rotateRight ^ rotateLeft2;
|
|
i7 = i8;
|
|
i8 = rotateRight2;
|
|
}
|
|
int[] iArr2 = this._S;
|
|
int i11 = iArr2[1];
|
|
int i12 = iArr2[0];
|
|
wordToBytes(i8, bArr2, i2);
|
|
wordToBytes(i7 - i12, bArr2, i2 + 4);
|
|
wordToBytes(i6, bArr2, i2 + 8);
|
|
wordToBytes(i5 - i11, bArr2, i2 + 12);
|
|
return 16;
|
|
}
|
|
|
|
private int bytesToWord(byte[] bArr, int i) {
|
|
int i2 = 0;
|
|
for (int i3 = 3; i3 >= 0; i3--) {
|
|
i2 = (i2 << 8) + (bArr[i3 + i] & UnsignedBytes.MAX_VALUE);
|
|
}
|
|
return i2;
|
|
}
|
|
}
|