194 lines
11 KiB
Java
194 lines
11 KiB
Java
package org.bouncycastle.crypto.engines;
|
|
|
|
import com.google.common.base.Ascii;
|
|
import com.google.common.primitives.UnsignedBytes;
|
|
import java.util.Hashtable;
|
|
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;
|
|
import org.bouncycastle.crypto.params.ParametersWithSBox;
|
|
import org.bouncycastle.crypto.tls.CipherSuite;
|
|
import org.bouncycastle.util.Arrays;
|
|
import org.bouncycastle.util.Strings;
|
|
|
|
/* loaded from: classes6.dex */
|
|
public class GOST28147Engine implements BlockCipher {
|
|
protected static final int BLOCK_SIZE = 8;
|
|
private boolean forEncryption;
|
|
private static byte[] Sbox_Default = {4, 10, 9, 2, 13, 8, 0, 14, 6, 11, 1, 12, 7, 15, 5, 3, 14, 11, 4, 12, 6, 13, 15, 10, 2, 3, 8, 1, 0, 7, 5, 9, 5, 8, 1, 13, 10, 3, 4, 2, 14, 15, 12, 7, 6, 0, 9, 11, 7, 13, 10, 1, 0, 8, 9, 15, 14, 4, 6, 12, 11, 2, 5, 3, 6, 12, 7, 1, 5, 15, 13, 8, 4, 10, 9, 14, 0, 3, 11, 2, 4, 11, 10, 0, 7, 2, 1, 13, 3, 6, 8, 5, 9, 12, 15, 14, 13, 11, 4, 1, 3, 15, 5, 9, 0, 10, 14, 7, 6, 8, 2, 12, 1, 15, 13, 0, 5, 7, 10, 4, 9, 2, 3, 14, 6, 11, 8, 12};
|
|
private static byte[] ESbox_Test = {4, 2, 15, 5, 9, 1, 0, 8, 14, 3, 11, 12, 13, 7, 10, 6, 12, 9, 15, 14, 8, 1, 3, 10, 2, 7, 4, 13, 6, 0, 11, 5, 13, 8, 14, 12, 7, 3, 9, 10, 1, 5, 2, 4, 6, 15, 0, 11, 14, 9, 11, 2, 5, 15, 7, 1, 0, 13, 12, 6, 10, 4, 3, 8, 3, 14, 5, 9, 6, 8, 0, 13, 10, 11, 7, 12, 2, 1, 15, 4, 8, 15, 6, 11, 1, 9, 12, 5, 13, 3, 7, 10, 0, 14, 2, 4, 9, 11, 12, 0, 3, 6, 7, 5, 4, 8, 14, 15, 1, 10, 2, 13, 12, 6, 5, 2, 11, 0, 9, 13, 3, 14, 7, 10, 15, 4, 1, 8};
|
|
private static byte[] ESbox_A = {9, 6, 3, 2, 8, 11, 1, 7, 10, 4, 14, 15, 12, 0, 13, 5, 3, 7, 14, 9, 8, 10, 15, 0, 5, 2, 6, 12, 11, 4, 13, 1, 14, 4, 6, 2, 11, 3, 13, 8, 12, 15, 5, 10, 0, 7, 1, 9, 14, 7, 10, 12, 13, 1, 3, 9, 0, 2, 11, 4, 15, 8, 5, 6, 11, 5, 1, 9, 8, 13, 15, 0, 14, 4, 2, 3, 12, 7, 10, 6, 3, 10, 13, 12, 1, 2, 0, 11, 7, 5, 9, 4, 8, 15, 14, 6, 1, 13, 2, 9, 7, 10, 6, 0, 8, 12, 4, 5, 15, 3, 11, 14, 11, 10, 15, 5, 0, 12, 14, 8, 6, 2, 3, 9, 1, 7, 13, 4};
|
|
private static byte[] ESbox_B = {8, 4, 11, 1, 3, 5, 0, 9, 2, 14, 10, 12, 13, 6, 7, 15, 0, 1, 2, 10, 4, 13, 5, 12, 9, 7, 3, 15, 11, 8, 6, 14, 14, 12, 0, 10, 9, 2, 13, 11, 7, 5, 8, 15, 3, 6, 1, 4, 7, 5, 0, 13, 11, 6, 1, 2, 3, 10, 12, 15, 4, 14, 9, 8, 2, 7, 12, 15, 9, 5, 10, 11, 1, 4, 0, 13, 6, 8, 14, 3, 8, 3, 2, 6, 4, 13, 14, 11, 12, 1, 7, 15, 10, 0, 9, 5, 5, 2, 10, 11, 9, 1, 12, 3, 7, 4, 13, 0, 6, 15, 8, 14, 0, 4, 11, 14, 8, 3, 7, 1, 10, 2, 9, 6, 15, 13, 5, 12};
|
|
private static byte[] ESbox_C = {1, 11, 12, 2, 9, 13, 0, 15, 4, 5, 8, 14, 10, 7, 6, 3, 0, 1, 7, 13, 11, 4, 5, 2, 8, 14, 15, 12, 9, 10, 6, 3, 8, 2, 5, 0, 4, 9, 15, 10, 3, 7, 12, 13, 6, 14, 1, 11, 3, 6, 0, 1, 5, 13, 10, 8, 11, 2, 9, 7, 14, 15, 12, 4, 8, 13, 11, 0, 4, 5, 1, 2, 9, 3, 12, 14, 6, 15, 10, 7, 12, 9, 11, 1, 8, 14, 2, 4, 7, 3, 6, 5, 10, 0, 15, 13, 10, 9, 6, 8, 13, 14, 2, 0, 15, 3, 5, 11, 4, 1, 12, 7, 7, 4, 0, 5, 10, 2, 15, 14, 12, 6, 1, 11, 13, 9, 3, 8};
|
|
private static byte[] ESbox_D = {15, 12, 2, 10, 6, 4, 5, 0, 7, 9, 14, 13, 1, 11, 8, 3, 11, 6, 3, 4, 12, 15, 14, 2, 7, 13, 8, 0, 5, 10, 9, 1, 1, 12, 11, 0, 15, 14, 6, 5, 10, 13, 4, 8, 9, 3, 7, 2, 1, 5, 14, 12, 10, 7, 0, 13, 6, 2, 11, 4, 9, 3, 15, 8, 0, 12, 8, 9, 13, 2, 10, 11, 7, 3, 6, 5, 4, 14, 15, 1, 8, 0, 15, 3, 2, 5, 14, 11, 1, 10, 4, 7, 12, 9, 13, 6, 3, 0, 6, 15, 1, 14, 9, 2, 13, 8, 12, 4, 11, 10, 5, 7, 1, 10, 6, 8, 15, 11, 0, 4, 12, 3, 5, 9, 7, 13, 2, 14};
|
|
private static byte[] DSbox_Test = {4, 10, 9, 2, 13, 8, 0, 14, 6, 11, 1, 12, 7, 15, 5, 3, 14, 11, 4, 12, 6, 13, 15, 10, 2, 3, 8, 1, 0, 7, 5, 9, 5, 8, 1, 13, 10, 3, 4, 2, 14, 15, 12, 7, 6, 0, 9, 11, 7, 13, 10, 1, 0, 8, 9, 15, 14, 4, 6, 12, 11, 2, 5, 3, 6, 12, 7, 1, 5, 15, 13, 8, 4, 10, 9, 14, 0, 3, 11, 2, 4, 11, 10, 0, 7, 2, 1, 13, 3, 6, 8, 5, 9, 12, 15, 14, 13, 11, 4, 1, 3, 15, 5, 9, 0, 10, 14, 7, 6, 8, 2, 12, 1, 15, 13, 0, 5, 7, 10, 4, 9, 2, 3, 14, 6, 11, 8, 12};
|
|
private static byte[] DSbox_A = {10, 4, 5, 6, 8, 1, 3, 7, 13, 12, 14, 0, 9, 2, 11, 15, 5, 15, 4, 0, 2, 13, 11, 9, 1, 7, 6, 3, 12, 14, 10, 8, 7, 15, 12, 14, 9, 4, 1, 0, 3, 11, 5, 2, 6, 10, 8, 13, 4, 10, 7, 12, 0, 15, 2, 8, 14, 1, 6, 5, 13, 11, 9, 3, 7, 6, 4, 11, 9, 12, 2, 10, 1, 8, 0, 14, 15, 13, 3, 5, 7, 6, 2, 4, 13, 9, 15, 0, 10, 1, 5, 11, 8, 14, 12, 3, 13, 14, 4, 1, 7, 0, 5, 10, 3, 12, 8, 15, 6, 2, 9, 11, 1, 3, 10, 9, 5, 11, 4, 15, 8, 6, 7, 14, 13, 0, 2, 12};
|
|
private static Hashtable sBoxes = new Hashtable();
|
|
private int[] workingKey = null;
|
|
private byte[] S = Sbox_Default;
|
|
|
|
@Override // org.bouncycastle.crypto.BlockCipher
|
|
public int getBlockSize() {
|
|
return 8;
|
|
}
|
|
|
|
@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[] iArr = this.workingKey;
|
|
if (iArr == null) {
|
|
throw new IllegalStateException("GOST28147 engine not initialised");
|
|
}
|
|
if (i + 8 > bArr.length) {
|
|
throw new DataLengthException("input buffer too short");
|
|
}
|
|
if (i2 + 8 > bArr2.length) {
|
|
throw new OutputLengthException("output buffer too short");
|
|
}
|
|
GOST28147Func(iArr, bArr, i, bArr2, i2);
|
|
return 8;
|
|
}
|
|
|
|
@Override // org.bouncycastle.crypto.BlockCipher
|
|
public void init(boolean z, CipherParameters cipherParameters) {
|
|
if (!(cipherParameters instanceof ParametersWithSBox)) {
|
|
if (cipherParameters instanceof KeyParameter) {
|
|
this.workingKey = generateWorkingKey(z, ((KeyParameter) cipherParameters).getKey());
|
|
return;
|
|
} else {
|
|
if (cipherParameters == null) {
|
|
return;
|
|
}
|
|
StringBuilder sb = new StringBuilder("invalid parameter passed to GOST28147 init - ");
|
|
sb.append(cipherParameters.getClass().getName());
|
|
throw new IllegalArgumentException(sb.toString());
|
|
}
|
|
}
|
|
ParametersWithSBox parametersWithSBox = (ParametersWithSBox) cipherParameters;
|
|
byte[] sBox = parametersWithSBox.getSBox();
|
|
if (sBox.length != Sbox_Default.length) {
|
|
throw new IllegalArgumentException("invalid S-box passed to GOST28147 init");
|
|
}
|
|
this.S = Arrays.clone(sBox);
|
|
if (parametersWithSBox.getParameters() != null) {
|
|
this.workingKey = generateWorkingKey(z, ((KeyParameter) parametersWithSBox.getParameters()).getKey());
|
|
}
|
|
}
|
|
|
|
@Override // org.bouncycastle.crypto.BlockCipher
|
|
public String getAlgorithmName() {
|
|
return "GOST28147";
|
|
}
|
|
|
|
private void intTobytes(int i, byte[] bArr, int i2) {
|
|
bArr[i2 + 3] = (byte) (i >>> 24);
|
|
bArr[i2 + 2] = (byte) (i >>> 16);
|
|
bArr[i2 + 1] = (byte) (i >>> 8);
|
|
bArr[i2] = (byte) i;
|
|
}
|
|
|
|
public static byte[] getSBox(String str) {
|
|
byte[] bArr = (byte[]) sBoxes.get(Strings.toUpperCase(str));
|
|
if (bArr != null) {
|
|
return Arrays.clone(bArr);
|
|
}
|
|
throw new IllegalArgumentException("Unknown S-Box - possible types: \"Default\", \"E-Test\", \"E-A\", \"E-B\", \"E-C\", \"E-D\", \"D-Test\", \"D-A\".");
|
|
}
|
|
|
|
private int[] generateWorkingKey(boolean z, byte[] bArr) {
|
|
this.forEncryption = z;
|
|
if (bArr.length != 32) {
|
|
throw new IllegalArgumentException("Key length invalid. Key needs to be 32 byte - 256 bit!!!");
|
|
}
|
|
int[] iArr = new int[8];
|
|
for (int i = 0; i != 8; i++) {
|
|
iArr[i] = bytesToint(bArr, i << 2);
|
|
}
|
|
return iArr;
|
|
}
|
|
|
|
private int bytesToint(byte[] bArr, int i) {
|
|
return ((bArr[i + 3] << Ascii.CAN) & (-16777216)) + ((bArr[i + 2] << 16) & 16711680) + ((bArr[i + 1] << 8) & CipherSuite.DRAFT_TLS_DHE_RSA_WITH_AES_128_OCB) + (bArr[i] & UnsignedBytes.MAX_VALUE);
|
|
}
|
|
|
|
private static void addSBox(String str, byte[] bArr) {
|
|
sBoxes.put(Strings.toUpperCase(str), bArr);
|
|
}
|
|
|
|
private int GOST28147_mainStep(int i, int i2) {
|
|
int i3 = i2 + i;
|
|
byte[] bArr = this.S;
|
|
int i4 = bArr[i3 & 15] + (bArr[((i3 >> 4) & 15) + 16] << 4) + (bArr[((i3 >> 8) & 15) + 32] << 8) + (bArr[((i3 >> 12) & 15) + 48] << 12) + (bArr[((i3 >> 16) & 15) + 64] << 16) + (bArr[((i3 >> 20) & 15) + 80] << Ascii.DC4) + (bArr[((i3 >> 24) & 15) + 96] << Ascii.CAN) + (bArr[((i3 >> 28) & 15) + 112] << 28);
|
|
return (i4 << 11) | (i4 >>> 21);
|
|
}
|
|
|
|
private void GOST28147Func(int[] iArr, byte[] bArr, int i, byte[] bArr2, int i2) {
|
|
int i3;
|
|
int i4;
|
|
int bytesToint = bytesToint(bArr, i);
|
|
int bytesToint2 = bytesToint(bArr, i + 4);
|
|
int i5 = 7;
|
|
if (this.forEncryption) {
|
|
for (int i6 = 0; i6 < 3; i6++) {
|
|
int i7 = 0;
|
|
while (i7 < 8) {
|
|
int GOST28147_mainStep = GOST28147_mainStep(bytesToint, iArr[i7]);
|
|
i7++;
|
|
int i8 = bytesToint;
|
|
bytesToint = bytesToint2 ^ GOST28147_mainStep;
|
|
bytesToint2 = i8;
|
|
}
|
|
}
|
|
i3 = bytesToint2;
|
|
i4 = bytesToint;
|
|
while (i5 > 0) {
|
|
int GOST28147_mainStep2 = GOST28147_mainStep(i4, iArr[i5]);
|
|
i5--;
|
|
int i9 = i3 ^ GOST28147_mainStep2;
|
|
i3 = i4;
|
|
i4 = i9;
|
|
}
|
|
} else {
|
|
int i10 = 0;
|
|
while (i10 < 8) {
|
|
int GOST28147_mainStep3 = GOST28147_mainStep(bytesToint, iArr[i10]);
|
|
i10++;
|
|
int i11 = bytesToint;
|
|
bytesToint = bytesToint2 ^ GOST28147_mainStep3;
|
|
bytesToint2 = i11;
|
|
}
|
|
i3 = bytesToint2;
|
|
i4 = bytesToint;
|
|
for (int i12 = 0; i12 < 3; i12++) {
|
|
int i13 = 7;
|
|
while (i13 >= 0 && (i12 != 2 || i13 != 0)) {
|
|
int GOST28147_mainStep4 = GOST28147_mainStep(i4, iArr[i13]);
|
|
i13--;
|
|
int i14 = i3 ^ GOST28147_mainStep4;
|
|
i3 = i4;
|
|
i4 = i14;
|
|
}
|
|
}
|
|
}
|
|
int GOST28147_mainStep5 = GOST28147_mainStep(i4, iArr[0]);
|
|
intTobytes(i4, bArr2, i2);
|
|
intTobytes(GOST28147_mainStep5 ^ i3, bArr2, i2 + 4);
|
|
}
|
|
|
|
static {
|
|
addSBox("Default", Sbox_Default);
|
|
addSBox("E-TEST", ESbox_Test);
|
|
addSBox("E-A", ESbox_A);
|
|
addSBox("E-B", ESbox_B);
|
|
addSBox("E-C", ESbox_C);
|
|
addSBox("E-D", ESbox_D);
|
|
addSBox("D-TEST", DSbox_Test);
|
|
addSBox("D-A", DSbox_A);
|
|
}
|
|
}
|