423 lines
19 KiB
Java
423 lines
19 KiB
Java
|
package org.bouncycastle.jce.provider;
|
||
|
|
||
|
import java.security.AlgorithmParameters;
|
||
|
import java.security.InvalidAlgorithmParameterException;
|
||
|
import java.security.InvalidKeyException;
|
||
|
import java.security.Key;
|
||
|
import java.security.KeyFactory;
|
||
|
import java.security.NoSuchAlgorithmException;
|
||
|
import java.security.NoSuchProviderException;
|
||
|
import java.security.SecureRandom;
|
||
|
import java.security.spec.AlgorithmParameterSpec;
|
||
|
import java.security.spec.InvalidKeySpecException;
|
||
|
import java.security.spec.PKCS8EncodedKeySpec;
|
||
|
import java.security.spec.X509EncodedKeySpec;
|
||
|
import javax.crypto.BadPaddingException;
|
||
|
import javax.crypto.IllegalBlockSizeException;
|
||
|
import javax.crypto.NoSuchPaddingException;
|
||
|
import javax.crypto.spec.IvParameterSpec;
|
||
|
import javax.crypto.spec.PBEParameterSpec;
|
||
|
import javax.crypto.spec.RC2ParameterSpec;
|
||
|
import javax.crypto.spec.RC5ParameterSpec;
|
||
|
import javax.crypto.spec.SecretKeySpec;
|
||
|
import org.bouncycastle.crypto.BlockCipher;
|
||
|
import org.bouncycastle.crypto.BufferedBlockCipher;
|
||
|
import org.bouncycastle.crypto.CipherParameters;
|
||
|
import org.bouncycastle.crypto.DataLengthException;
|
||
|
import org.bouncycastle.crypto.InvalidCipherTextException;
|
||
|
import org.bouncycastle.crypto.engines.DESEngine;
|
||
|
import org.bouncycastle.crypto.engines.DESedeEngine;
|
||
|
import org.bouncycastle.crypto.engines.TwofishEngine;
|
||
|
import org.bouncycastle.crypto.modes.CBCBlockCipher;
|
||
|
import org.bouncycastle.crypto.modes.CFBBlockCipher;
|
||
|
import org.bouncycastle.crypto.modes.CTSBlockCipher;
|
||
|
import org.bouncycastle.crypto.modes.OFBBlockCipher;
|
||
|
import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher;
|
||
|
import org.bouncycastle.crypto.params.KeyParameter;
|
||
|
import org.bouncycastle.crypto.params.ParametersWithIV;
|
||
|
import org.bouncycastle.crypto.params.RC2Parameters;
|
||
|
import org.bouncycastle.crypto.params.RC5Parameters;
|
||
|
import org.bouncycastle.jcajce.provider.symmetric.util.BCPBEKey;
|
||
|
import org.bouncycastle.jce.provider.BrokenPBE;
|
||
|
import org.bouncycastle.util.Strings;
|
||
|
|
||
|
/* loaded from: classes6.dex */
|
||
|
public class BrokenJCEBlockCipher implements BrokenPBE {
|
||
|
private Class[] availableSpecs;
|
||
|
private BufferedBlockCipher cipher;
|
||
|
private AlgorithmParameters engineParams;
|
||
|
private int ivLength;
|
||
|
private ParametersWithIV ivParam;
|
||
|
private int pbeHash;
|
||
|
private int pbeIvSize;
|
||
|
private int pbeKeySize;
|
||
|
private int pbeType;
|
||
|
|
||
|
protected byte[] engineWrap(Key key) throws IllegalBlockSizeException, InvalidKeyException {
|
||
|
byte[] encoded = key.getEncoded();
|
||
|
if (encoded == null) {
|
||
|
throw new InvalidKeyException("Cannot wrap key, null encoding.");
|
||
|
}
|
||
|
try {
|
||
|
return engineDoFinal(encoded, 0, encoded.length);
|
||
|
} catch (BadPaddingException e) {
|
||
|
throw new IllegalBlockSizeException(e.getMessage());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
protected byte[] engineUpdate(byte[] bArr, int i, int i2) {
|
||
|
int updateOutputSize = this.cipher.getUpdateOutputSize(i2);
|
||
|
if (updateOutputSize <= 0) {
|
||
|
this.cipher.processBytes(bArr, i, i2, null, 0);
|
||
|
return null;
|
||
|
}
|
||
|
byte[] bArr2 = new byte[updateOutputSize];
|
||
|
this.cipher.processBytes(bArr, i, i2, bArr2, 0);
|
||
|
return bArr2;
|
||
|
}
|
||
|
|
||
|
protected int engineUpdate(byte[] bArr, int i, int i2, byte[] bArr2, int i3) {
|
||
|
return this.cipher.processBytes(bArr, i, i2, bArr2, i3);
|
||
|
}
|
||
|
|
||
|
protected Key engineUnwrap(byte[] bArr, String str, int i) throws InvalidKeyException {
|
||
|
try {
|
||
|
byte[] engineDoFinal = engineDoFinal(bArr, 0, bArr.length);
|
||
|
if (i == 3) {
|
||
|
return new SecretKeySpec(engineDoFinal, str);
|
||
|
}
|
||
|
try {
|
||
|
KeyFactory keyFactory = KeyFactory.getInstance(str, BouncyCastleProvider.PROVIDER_NAME);
|
||
|
if (i == 1) {
|
||
|
return keyFactory.generatePublic(new X509EncodedKeySpec(engineDoFinal));
|
||
|
}
|
||
|
if (i == 2) {
|
||
|
return keyFactory.generatePrivate(new PKCS8EncodedKeySpec(engineDoFinal));
|
||
|
}
|
||
|
throw new InvalidKeyException("Unknown key type ".concat(String.valueOf(i)));
|
||
|
} catch (NoSuchAlgorithmException e) {
|
||
|
StringBuilder sb = new StringBuilder("Unknown key type ");
|
||
|
sb.append(e.getMessage());
|
||
|
throw new InvalidKeyException(sb.toString());
|
||
|
} catch (NoSuchProviderException e2) {
|
||
|
StringBuilder sb2 = new StringBuilder("Unknown key type ");
|
||
|
sb2.append(e2.getMessage());
|
||
|
throw new InvalidKeyException(sb2.toString());
|
||
|
} catch (InvalidKeySpecException e3) {
|
||
|
StringBuilder sb3 = new StringBuilder("Unknown key type ");
|
||
|
sb3.append(e3.getMessage());
|
||
|
throw new InvalidKeyException(sb3.toString());
|
||
|
}
|
||
|
} catch (BadPaddingException e4) {
|
||
|
throw new InvalidKeyException(e4.getMessage());
|
||
|
} catch (IllegalBlockSizeException e5) {
|
||
|
throw new InvalidKeyException(e5.getMessage());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
protected void engineSetPadding(String str) throws NoSuchPaddingException {
|
||
|
BufferedBlockCipher paddedBufferedBlockCipher;
|
||
|
String upperCase = Strings.toUpperCase(str);
|
||
|
if (upperCase.equals("NOPADDING")) {
|
||
|
paddedBufferedBlockCipher = new BufferedBlockCipher(this.cipher.getUnderlyingCipher());
|
||
|
} else if (upperCase.equals("PKCS5PADDING") || upperCase.equals("PKCS7PADDING") || upperCase.equals("ISO10126PADDING")) {
|
||
|
paddedBufferedBlockCipher = new PaddedBufferedBlockCipher(this.cipher.getUnderlyingCipher());
|
||
|
} else {
|
||
|
if (!upperCase.equals("WITHCTS")) {
|
||
|
StringBuilder sb = new StringBuilder("Padding ");
|
||
|
sb.append(str);
|
||
|
sb.append(" unknown.");
|
||
|
throw new NoSuchPaddingException(sb.toString());
|
||
|
}
|
||
|
paddedBufferedBlockCipher = new CTSBlockCipher(this.cipher.getUnderlyingCipher());
|
||
|
}
|
||
|
this.cipher = paddedBufferedBlockCipher;
|
||
|
}
|
||
|
|
||
|
protected void engineSetMode(String str) {
|
||
|
PaddedBufferedBlockCipher paddedBufferedBlockCipher;
|
||
|
PaddedBufferedBlockCipher paddedBufferedBlockCipher2;
|
||
|
String upperCase = Strings.toUpperCase(str);
|
||
|
if (upperCase.equals("ECB")) {
|
||
|
this.ivLength = 0;
|
||
|
paddedBufferedBlockCipher = new PaddedBufferedBlockCipher(this.cipher.getUnderlyingCipher());
|
||
|
} else if (upperCase.equals("CBC")) {
|
||
|
this.ivLength = this.cipher.getUnderlyingCipher().getBlockSize();
|
||
|
paddedBufferedBlockCipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(this.cipher.getUnderlyingCipher()));
|
||
|
} else if (upperCase.startsWith("OFB")) {
|
||
|
this.ivLength = this.cipher.getUnderlyingCipher().getBlockSize();
|
||
|
if (upperCase.length() != 3) {
|
||
|
paddedBufferedBlockCipher2 = new PaddedBufferedBlockCipher(new OFBBlockCipher(this.cipher.getUnderlyingCipher(), Integer.parseInt(upperCase.substring(3))));
|
||
|
this.cipher = paddedBufferedBlockCipher2;
|
||
|
return;
|
||
|
}
|
||
|
paddedBufferedBlockCipher = new PaddedBufferedBlockCipher(new OFBBlockCipher(this.cipher.getUnderlyingCipher(), this.cipher.getBlockSize() << 3));
|
||
|
} else {
|
||
|
if (!upperCase.startsWith("CFB")) {
|
||
|
throw new IllegalArgumentException("can't support mode ".concat(String.valueOf(str)));
|
||
|
}
|
||
|
this.ivLength = this.cipher.getUnderlyingCipher().getBlockSize();
|
||
|
if (upperCase.length() != 3) {
|
||
|
paddedBufferedBlockCipher2 = new PaddedBufferedBlockCipher(new CFBBlockCipher(this.cipher.getUnderlyingCipher(), Integer.parseInt(upperCase.substring(3))));
|
||
|
this.cipher = paddedBufferedBlockCipher2;
|
||
|
return;
|
||
|
}
|
||
|
paddedBufferedBlockCipher = new PaddedBufferedBlockCipher(new CFBBlockCipher(this.cipher.getUnderlyingCipher(), this.cipher.getBlockSize() << 3));
|
||
|
}
|
||
|
this.cipher = paddedBufferedBlockCipher;
|
||
|
}
|
||
|
|
||
|
protected void engineInit(int i, Key key, AlgorithmParameterSpec algorithmParameterSpec, SecureRandom secureRandom) throws InvalidKeyException, InvalidAlgorithmParameterException {
|
||
|
ParametersWithIV parametersWithIV;
|
||
|
CipherParameters cipherParameters;
|
||
|
CipherParameters cipherParameters2;
|
||
|
CipherParameters keyParameter;
|
||
|
if (key instanceof BCPBEKey) {
|
||
|
CipherParameters makePBEParameters = BrokenPBE.Util.makePBEParameters((BCPBEKey) key, algorithmParameterSpec, this.pbeType, this.pbeHash, this.cipher.getUnderlyingCipher().getAlgorithmName(), this.pbeKeySize, this.pbeIvSize);
|
||
|
cipherParameters2 = makePBEParameters;
|
||
|
if (this.pbeIvSize != 0) {
|
||
|
this.ivParam = (ParametersWithIV) makePBEParameters;
|
||
|
cipherParameters2 = makePBEParameters;
|
||
|
}
|
||
|
} else {
|
||
|
if (algorithmParameterSpec == null) {
|
||
|
keyParameter = new KeyParameter(key.getEncoded());
|
||
|
} else {
|
||
|
if (algorithmParameterSpec instanceof IvParameterSpec) {
|
||
|
if (this.ivLength != 0) {
|
||
|
ParametersWithIV parametersWithIV2 = new ParametersWithIV(new KeyParameter(key.getEncoded()), ((IvParameterSpec) algorithmParameterSpec).getIV());
|
||
|
this.ivParam = parametersWithIV2;
|
||
|
cipherParameters = parametersWithIV2;
|
||
|
} else {
|
||
|
keyParameter = new KeyParameter(key.getEncoded());
|
||
|
}
|
||
|
} else if (algorithmParameterSpec instanceof RC2ParameterSpec) {
|
||
|
RC2ParameterSpec rC2ParameterSpec = (RC2ParameterSpec) algorithmParameterSpec;
|
||
|
CipherParameters rC2Parameters = new RC2Parameters(key.getEncoded(), rC2ParameterSpec.getEffectiveKeyBits());
|
||
|
cipherParameters = rC2Parameters;
|
||
|
if (rC2ParameterSpec.getIV() != null) {
|
||
|
cipherParameters = rC2Parameters;
|
||
|
if (this.ivLength != 0) {
|
||
|
parametersWithIV = new ParametersWithIV(rC2Parameters, rC2ParameterSpec.getIV());
|
||
|
this.ivParam = parametersWithIV;
|
||
|
cipherParameters2 = parametersWithIV;
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
if (!(algorithmParameterSpec instanceof RC5ParameterSpec)) {
|
||
|
throw new InvalidAlgorithmParameterException("unknown parameter type.");
|
||
|
}
|
||
|
RC5ParameterSpec rC5ParameterSpec = (RC5ParameterSpec) algorithmParameterSpec;
|
||
|
CipherParameters rC5Parameters = new RC5Parameters(key.getEncoded(), rC5ParameterSpec.getRounds());
|
||
|
if (rC5ParameterSpec.getWordSize() != 32) {
|
||
|
throw new IllegalArgumentException("can only accept RC5 word size 32 (at the moment...)");
|
||
|
}
|
||
|
cipherParameters = rC5Parameters;
|
||
|
if (rC5ParameterSpec.getIV() != null) {
|
||
|
cipherParameters = rC5Parameters;
|
||
|
if (this.ivLength != 0) {
|
||
|
parametersWithIV = new ParametersWithIV(rC5Parameters, rC5ParameterSpec.getIV());
|
||
|
this.ivParam = parametersWithIV;
|
||
|
cipherParameters2 = parametersWithIV;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
cipherParameters2 = cipherParameters;
|
||
|
}
|
||
|
cipherParameters2 = keyParameter;
|
||
|
}
|
||
|
CipherParameters cipherParameters3 = cipherParameters2;
|
||
|
if (this.ivLength != 0) {
|
||
|
boolean z = cipherParameters2 instanceof ParametersWithIV;
|
||
|
cipherParameters3 = cipherParameters2;
|
||
|
if (!z) {
|
||
|
if (secureRandom == null) {
|
||
|
secureRandom = new SecureRandom();
|
||
|
}
|
||
|
if (i != 1 && i != 3) {
|
||
|
throw new InvalidAlgorithmParameterException("no IV set when one expected");
|
||
|
}
|
||
|
byte[] bArr = new byte[this.ivLength];
|
||
|
secureRandom.nextBytes(bArr);
|
||
|
ParametersWithIV parametersWithIV3 = new ParametersWithIV(cipherParameters2, bArr);
|
||
|
this.ivParam = parametersWithIV3;
|
||
|
cipherParameters3 = parametersWithIV3;
|
||
|
}
|
||
|
}
|
||
|
if (i != 1) {
|
||
|
if (i != 2) {
|
||
|
if (i != 3) {
|
||
|
if (i != 4) {
|
||
|
System.out.println("eeek!");
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
this.cipher.init(false, cipherParameters3);
|
||
|
return;
|
||
|
}
|
||
|
this.cipher.init(true, cipherParameters3);
|
||
|
}
|
||
|
|
||
|
protected void engineInit(int i, Key key, SecureRandom secureRandom) throws InvalidKeyException {
|
||
|
try {
|
||
|
engineInit(i, key, (AlgorithmParameterSpec) null, secureRandom);
|
||
|
} catch (InvalidAlgorithmParameterException e) {
|
||
|
throw new IllegalArgumentException(e.getMessage());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
protected void engineInit(int i, Key key, AlgorithmParameters algorithmParameters, SecureRandom secureRandom) throws InvalidKeyException, InvalidAlgorithmParameterException {
|
||
|
AlgorithmParameterSpec algorithmParameterSpec = null;
|
||
|
if (algorithmParameters != null) {
|
||
|
int i2 = 0;
|
||
|
while (true) {
|
||
|
Class[] clsArr = this.availableSpecs;
|
||
|
if (i2 == clsArr.length) {
|
||
|
break;
|
||
|
}
|
||
|
try {
|
||
|
algorithmParameterSpec = algorithmParameters.getParameterSpec(clsArr[i2]);
|
||
|
break;
|
||
|
} catch (Exception unused) {
|
||
|
i2++;
|
||
|
}
|
||
|
}
|
||
|
if (algorithmParameterSpec == null) {
|
||
|
StringBuilder sb = new StringBuilder("can't handle parameter ");
|
||
|
sb.append(algorithmParameters.toString());
|
||
|
throw new InvalidAlgorithmParameterException(sb.toString());
|
||
|
}
|
||
|
}
|
||
|
this.engineParams = algorithmParameters;
|
||
|
engineInit(i, key, algorithmParameterSpec, secureRandom);
|
||
|
}
|
||
|
|
||
|
protected AlgorithmParameters engineGetParameters() {
|
||
|
if (this.engineParams == null && this.ivParam != null) {
|
||
|
String algorithmName = this.cipher.getUnderlyingCipher().getAlgorithmName();
|
||
|
if (algorithmName.indexOf(47) >= 0) {
|
||
|
algorithmName = algorithmName.substring(0, algorithmName.indexOf(47));
|
||
|
}
|
||
|
try {
|
||
|
AlgorithmParameters algorithmParameters = AlgorithmParameters.getInstance(algorithmName, BouncyCastleProvider.PROVIDER_NAME);
|
||
|
this.engineParams = algorithmParameters;
|
||
|
algorithmParameters.init(this.ivParam.getIV());
|
||
|
} catch (Exception e) {
|
||
|
throw new RuntimeException(e.toString());
|
||
|
}
|
||
|
}
|
||
|
return this.engineParams;
|
||
|
}
|
||
|
|
||
|
protected int engineGetOutputSize(int i) {
|
||
|
return this.cipher.getOutputSize(i);
|
||
|
}
|
||
|
|
||
|
protected int engineGetKeySize(Key key) {
|
||
|
return key.getEncoded().length;
|
||
|
}
|
||
|
|
||
|
protected byte[] engineGetIV() {
|
||
|
ParametersWithIV parametersWithIV = this.ivParam;
|
||
|
if (parametersWithIV != null) {
|
||
|
return parametersWithIV.getIV();
|
||
|
}
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
protected int engineGetBlockSize() {
|
||
|
return this.cipher.getBlockSize();
|
||
|
}
|
||
|
|
||
|
protected byte[] engineDoFinal(byte[] bArr, int i, int i2) throws IllegalBlockSizeException, BadPaddingException {
|
||
|
byte[] bArr2 = new byte[engineGetOutputSize(i2)];
|
||
|
int processBytes = i2 != 0 ? this.cipher.processBytes(bArr, i, i2, bArr2, 0) : 0;
|
||
|
try {
|
||
|
int doFinal = processBytes + this.cipher.doFinal(bArr2, processBytes);
|
||
|
byte[] bArr3 = new byte[doFinal];
|
||
|
System.arraycopy(bArr2, 0, bArr3, 0, doFinal);
|
||
|
return bArr3;
|
||
|
} catch (DataLengthException e) {
|
||
|
throw new IllegalBlockSizeException(e.getMessage());
|
||
|
} catch (InvalidCipherTextException e2) {
|
||
|
throw new BadPaddingException(e2.getMessage());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
protected int engineDoFinal(byte[] bArr, int i, int i2, byte[] bArr2, int i3) throws IllegalBlockSizeException, BadPaddingException {
|
||
|
int processBytes = i2 != 0 ? this.cipher.processBytes(bArr, i, i2, bArr2, i3) : 0;
|
||
|
try {
|
||
|
return processBytes + this.cipher.doFinal(bArr2, i3 + processBytes);
|
||
|
} catch (DataLengthException e) {
|
||
|
throw new IllegalBlockSizeException(e.getMessage());
|
||
|
} catch (InvalidCipherTextException e2) {
|
||
|
throw new BadPaddingException(e2.getMessage());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* loaded from: classes6.dex */
|
||
|
public static class BrokePBEWithMD5AndDES extends BrokenJCEBlockCipher {
|
||
|
public BrokePBEWithMD5AndDES() {
|
||
|
super(new CBCBlockCipher(new DESEngine()), 0, 0, 64, 64);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* loaded from: classes6.dex */
|
||
|
public static class BrokePBEWithSHA1AndDES extends BrokenJCEBlockCipher {
|
||
|
public BrokePBEWithSHA1AndDES() {
|
||
|
super(new CBCBlockCipher(new DESEngine()), 0, 1, 64, 64);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* loaded from: classes6.dex */
|
||
|
public static class BrokePBEWithSHAAndDES2Key extends BrokenJCEBlockCipher {
|
||
|
public BrokePBEWithSHAAndDES2Key() {
|
||
|
super(new CBCBlockCipher(new DESedeEngine()), 2, 1, 128, 64);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* loaded from: classes6.dex */
|
||
|
public static class BrokePBEWithSHAAndDES3Key extends BrokenJCEBlockCipher {
|
||
|
public BrokePBEWithSHAAndDES3Key() {
|
||
|
super(new CBCBlockCipher(new DESedeEngine()), 2, 1, 192, 64);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* loaded from: classes6.dex */
|
||
|
public static class OldPBEWithSHAAndDES3Key extends BrokenJCEBlockCipher {
|
||
|
public OldPBEWithSHAAndDES3Key() {
|
||
|
super(new CBCBlockCipher(new DESedeEngine()), 3, 1, 192, 64);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* loaded from: classes6.dex */
|
||
|
public static class OldPBEWithSHAAndTwofish extends BrokenJCEBlockCipher {
|
||
|
public OldPBEWithSHAAndTwofish() {
|
||
|
super(new CBCBlockCipher(new TwofishEngine()), 3, 1, 256, 128);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
protected BrokenJCEBlockCipher(BlockCipher blockCipher, int i, int i2, int i3, int i4) {
|
||
|
this.availableSpecs = new Class[]{IvParameterSpec.class, PBEParameterSpec.class, RC2ParameterSpec.class, RC5ParameterSpec.class};
|
||
|
this.pbeType = 2;
|
||
|
this.pbeHash = 1;
|
||
|
this.ivLength = 0;
|
||
|
this.engineParams = null;
|
||
|
this.cipher = new PaddedBufferedBlockCipher(blockCipher);
|
||
|
this.pbeType = i;
|
||
|
this.pbeHash = i2;
|
||
|
this.pbeKeySize = i3;
|
||
|
this.pbeIvSize = i4;
|
||
|
}
|
||
|
|
||
|
protected BrokenJCEBlockCipher(BlockCipher blockCipher) {
|
||
|
this.availableSpecs = new Class[]{IvParameterSpec.class, PBEParameterSpec.class, RC2ParameterSpec.class, RC5ParameterSpec.class};
|
||
|
this.pbeType = 2;
|
||
|
this.pbeHash = 1;
|
||
|
this.ivLength = 0;
|
||
|
this.engineParams = null;
|
||
|
this.cipher = new PaddedBufferedBlockCipher(blockCipher);
|
||
|
}
|
||
|
}
|