444 lines
18 KiB
Java
444 lines
18 KiB
Java
|
package org.bouncycastle.jcajce.provider.asymmetric.ec;
|
||
|
|
||
|
import java.io.ByteArrayOutputStream;
|
||
|
import java.security.AlgorithmParameters;
|
||
|
import java.security.InvalidAlgorithmParameterException;
|
||
|
import java.security.InvalidKeyException;
|
||
|
import java.security.Key;
|
||
|
import java.security.NoSuchAlgorithmException;
|
||
|
import java.security.PrivateKey;
|
||
|
import java.security.PublicKey;
|
||
|
import java.security.SecureRandom;
|
||
|
import java.security.spec.AlgorithmParameterSpec;
|
||
|
import javax.crypto.BadPaddingException;
|
||
|
import javax.crypto.CipherSpi;
|
||
|
import javax.crypto.IllegalBlockSizeException;
|
||
|
import javax.crypto.NoSuchPaddingException;
|
||
|
import javax.crypto.ShortBufferException;
|
||
|
import org.bouncycastle.crypto.BlockCipher;
|
||
|
import org.bouncycastle.crypto.BufferedBlockCipher;
|
||
|
import org.bouncycastle.crypto.CipherParameters;
|
||
|
import org.bouncycastle.crypto.InvalidCipherTextException;
|
||
|
import org.bouncycastle.crypto.KeyEncoder;
|
||
|
import org.bouncycastle.crypto.agreement.ECDHBasicAgreement;
|
||
|
import org.bouncycastle.crypto.digests.SHA1Digest;
|
||
|
import org.bouncycastle.crypto.engines.AESEngine;
|
||
|
import org.bouncycastle.crypto.engines.DESedeEngine;
|
||
|
import org.bouncycastle.crypto.engines.IESEngine;
|
||
|
import org.bouncycastle.crypto.engines.OldIESEngine;
|
||
|
import org.bouncycastle.crypto.generators.ECKeyPairGenerator;
|
||
|
import org.bouncycastle.crypto.generators.EphemeralKeyPairGenerator;
|
||
|
import org.bouncycastle.crypto.generators.KDF2BytesGenerator;
|
||
|
import org.bouncycastle.crypto.macs.HMac;
|
||
|
import org.bouncycastle.crypto.modes.CBCBlockCipher;
|
||
|
import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher;
|
||
|
import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
|
||
|
import org.bouncycastle.crypto.params.ECDomainParameters;
|
||
|
import org.bouncycastle.crypto.params.ECKeyGenerationParameters;
|
||
|
import org.bouncycastle.crypto.params.ECKeyParameters;
|
||
|
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
|
||
|
import org.bouncycastle.crypto.params.IESWithCipherParameters;
|
||
|
import org.bouncycastle.crypto.params.ParametersWithIV;
|
||
|
import org.bouncycastle.crypto.parsers.ECIESPublicKeyParser;
|
||
|
import org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil;
|
||
|
import org.bouncycastle.jcajce.provider.asymmetric.util.IESUtil;
|
||
|
import org.bouncycastle.jcajce.util.BCJcaJceHelper;
|
||
|
import org.bouncycastle.jcajce.util.JcaJceHelper;
|
||
|
import org.bouncycastle.jce.interfaces.ECKey;
|
||
|
import org.bouncycastle.jce.interfaces.IESKey;
|
||
|
import org.bouncycastle.jce.spec.IESParameterSpec;
|
||
|
import org.bouncycastle.util.Strings;
|
||
|
|
||
|
/* loaded from: classes6.dex */
|
||
|
public class IESCipher extends CipherSpi {
|
||
|
private ByteArrayOutputStream buffer;
|
||
|
private boolean dhaesMode;
|
||
|
private IESEngine engine;
|
||
|
private AlgorithmParameters engineParam;
|
||
|
private IESParameterSpec engineSpec;
|
||
|
private final JcaJceHelper helper;
|
||
|
private int ivLength;
|
||
|
private AsymmetricKeyParameter key;
|
||
|
private AsymmetricKeyParameter otherKeyParameter;
|
||
|
private SecureRandom random;
|
||
|
private int state;
|
||
|
|
||
|
@Override // javax.crypto.CipherSpi
|
||
|
public byte[] engineGetIV() {
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
@Override // javax.crypto.CipherSpi
|
||
|
public byte[] engineUpdate(byte[] bArr, int i, int i2) {
|
||
|
this.buffer.write(bArr, i, i2);
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
@Override // javax.crypto.CipherSpi
|
||
|
public int engineUpdate(byte[] bArr, int i, int i2, byte[] bArr2, int i3) {
|
||
|
this.buffer.write(bArr, i, i2);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
@Override // javax.crypto.CipherSpi
|
||
|
public void engineSetPadding(String str) throws NoSuchPaddingException {
|
||
|
String upperCase = Strings.toUpperCase(str);
|
||
|
if (!upperCase.equals("NOPADDING") && !upperCase.equals("PKCS5PADDING") && !upperCase.equals("PKCS7PADDING")) {
|
||
|
throw new NoSuchPaddingException("padding not available with IESCipher");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@Override // javax.crypto.CipherSpi
|
||
|
public void engineSetMode(String str) throws NoSuchAlgorithmException {
|
||
|
boolean z;
|
||
|
String upperCase = Strings.toUpperCase(str);
|
||
|
if (upperCase.equals("NONE")) {
|
||
|
z = false;
|
||
|
} else {
|
||
|
if (!upperCase.equals("DHAES")) {
|
||
|
throw new IllegalArgumentException("can't support mode ".concat(String.valueOf(str)));
|
||
|
}
|
||
|
z = true;
|
||
|
}
|
||
|
this.dhaesMode = z;
|
||
|
}
|
||
|
|
||
|
@Override // javax.crypto.CipherSpi
|
||
|
public void engineInit(int i, Key key, AlgorithmParameterSpec algorithmParameterSpec, SecureRandom secureRandom) throws InvalidAlgorithmParameterException, InvalidKeyException {
|
||
|
IESParameterSpec iESParameterSpec;
|
||
|
AsymmetricKeyParameter generatePublicKeyParameter;
|
||
|
PrivateKey privateKey;
|
||
|
this.otherKeyParameter = null;
|
||
|
if (algorithmParameterSpec == null) {
|
||
|
iESParameterSpec = IESUtil.guessParameterSpec(this.engine.getCipher());
|
||
|
} else {
|
||
|
if (!(algorithmParameterSpec instanceof IESParameterSpec)) {
|
||
|
throw new InvalidAlgorithmParameterException("must be passed IES parameters");
|
||
|
}
|
||
|
iESParameterSpec = (IESParameterSpec) algorithmParameterSpec;
|
||
|
}
|
||
|
this.engineSpec = iESParameterSpec;
|
||
|
byte[] nonce = iESParameterSpec.getNonce();
|
||
|
if (nonce != null) {
|
||
|
int i2 = this.ivLength;
|
||
|
if (i2 == 0) {
|
||
|
throw new InvalidAlgorithmParameterException("NONCE present in IES Parameters when none required");
|
||
|
}
|
||
|
if (nonce.length != i2) {
|
||
|
StringBuilder sb = new StringBuilder("NONCE in IES Parameters needs to be ");
|
||
|
sb.append(this.ivLength);
|
||
|
sb.append(" bytes long");
|
||
|
throw new InvalidAlgorithmParameterException(sb.toString());
|
||
|
}
|
||
|
}
|
||
|
if (i == 1 || i == 3) {
|
||
|
if (!(key instanceof PublicKey)) {
|
||
|
if (!(key instanceof IESKey)) {
|
||
|
throw new InvalidKeyException("must be passed recipient's public EC key for encryption");
|
||
|
}
|
||
|
IESKey iESKey = (IESKey) key;
|
||
|
this.key = ECUtil.generatePublicKeyParameter(iESKey.getPublic());
|
||
|
this.otherKeyParameter = ECUtil.generatePrivateKeyParameter(iESKey.getPrivate());
|
||
|
this.random = secureRandom;
|
||
|
this.state = i;
|
||
|
this.buffer.reset();
|
||
|
}
|
||
|
generatePublicKeyParameter = ECUtil.generatePublicKeyParameter((PublicKey) key);
|
||
|
} else {
|
||
|
if (i != 2 && i != 4) {
|
||
|
throw new InvalidKeyException("must be passed EC key");
|
||
|
}
|
||
|
if (key instanceof PrivateKey) {
|
||
|
privateKey = (PrivateKey) key;
|
||
|
} else {
|
||
|
if (!(key instanceof IESKey)) {
|
||
|
throw new InvalidKeyException("must be passed recipient's private EC key for decryption");
|
||
|
}
|
||
|
IESKey iESKey2 = (IESKey) key;
|
||
|
this.otherKeyParameter = ECUtil.generatePublicKeyParameter(iESKey2.getPublic());
|
||
|
privateKey = iESKey2.getPrivate();
|
||
|
}
|
||
|
generatePublicKeyParameter = ECUtil.generatePrivateKeyParameter(privateKey);
|
||
|
}
|
||
|
this.key = generatePublicKeyParameter;
|
||
|
this.random = secureRandom;
|
||
|
this.state = i;
|
||
|
this.buffer.reset();
|
||
|
}
|
||
|
|
||
|
@Override // javax.crypto.CipherSpi
|
||
|
public void engineInit(int i, Key key, SecureRandom secureRandom) throws InvalidKeyException {
|
||
|
try {
|
||
|
engineInit(i, key, (AlgorithmParameterSpec) null, secureRandom);
|
||
|
} catch (InvalidAlgorithmParameterException unused) {
|
||
|
throw new IllegalArgumentException("can't handle supplied parameter spec");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@Override // javax.crypto.CipherSpi
|
||
|
public void engineInit(int i, Key key, AlgorithmParameters algorithmParameters, SecureRandom secureRandom) throws InvalidKeyException, InvalidAlgorithmParameterException {
|
||
|
AlgorithmParameterSpec parameterSpec;
|
||
|
if (algorithmParameters != null) {
|
||
|
try {
|
||
|
parameterSpec = algorithmParameters.getParameterSpec(IESParameterSpec.class);
|
||
|
} catch (Exception e) {
|
||
|
StringBuilder sb = new StringBuilder("cannot recognise parameters: ");
|
||
|
sb.append(e.toString());
|
||
|
throw new InvalidAlgorithmParameterException(sb.toString());
|
||
|
}
|
||
|
} else {
|
||
|
parameterSpec = null;
|
||
|
}
|
||
|
this.engineParam = algorithmParameters;
|
||
|
engineInit(i, key, parameterSpec, secureRandom);
|
||
|
}
|
||
|
|
||
|
@Override // javax.crypto.CipherSpi
|
||
|
public AlgorithmParameters engineGetParameters() {
|
||
|
if (this.engineParam == null && this.engineSpec != null) {
|
||
|
try {
|
||
|
AlgorithmParameters createAlgorithmParameters = this.helper.createAlgorithmParameters("IES");
|
||
|
this.engineParam = createAlgorithmParameters;
|
||
|
createAlgorithmParameters.init(this.engineSpec);
|
||
|
} catch (Exception e) {
|
||
|
throw new RuntimeException(e.toString());
|
||
|
}
|
||
|
}
|
||
|
return this.engineParam;
|
||
|
}
|
||
|
|
||
|
@Override // javax.crypto.CipherSpi
|
||
|
public int engineGetOutputSize(int i) {
|
||
|
int size;
|
||
|
BufferedBlockCipher cipher;
|
||
|
if (this.key == null) {
|
||
|
throw new IllegalStateException("cipher not initialised");
|
||
|
}
|
||
|
int macSize = this.engine.getMac().getMacSize();
|
||
|
int fieldSize = this.otherKeyParameter == null ? ((((ECKeyParameters) this.key).getParameters().getCurve().getFieldSize() + 7) << 1) / 8 : 0;
|
||
|
if (this.engine.getCipher() != null) {
|
||
|
int i2 = this.state;
|
||
|
if (i2 == 1 || i2 == 3) {
|
||
|
cipher = this.engine.getCipher();
|
||
|
} else {
|
||
|
if (i2 != 2 && i2 != 4) {
|
||
|
throw new IllegalStateException("cipher not initialised");
|
||
|
}
|
||
|
cipher = this.engine.getCipher();
|
||
|
i = (i - macSize) - fieldSize;
|
||
|
}
|
||
|
i = cipher.getOutputSize(i);
|
||
|
}
|
||
|
int i3 = this.state;
|
||
|
if (i3 == 1 || i3 == 3) {
|
||
|
size = this.buffer.size() + macSize + 1 + fieldSize;
|
||
|
} else {
|
||
|
if (i3 != 2 && i3 != 4) {
|
||
|
throw new IllegalStateException("cipher not initialised");
|
||
|
}
|
||
|
size = (this.buffer.size() - macSize) - fieldSize;
|
||
|
}
|
||
|
return size + i;
|
||
|
}
|
||
|
|
||
|
@Override // javax.crypto.CipherSpi
|
||
|
public int engineGetKeySize(Key key) {
|
||
|
if (key instanceof ECKey) {
|
||
|
return ((ECKey) key).getParameters().getCurve().getFieldSize();
|
||
|
}
|
||
|
throw new IllegalArgumentException("not an EC key");
|
||
|
}
|
||
|
|
||
|
@Override // javax.crypto.CipherSpi
|
||
|
public int engineGetBlockSize() {
|
||
|
if (this.engine.getCipher() != null) {
|
||
|
return this.engine.getCipher().getBlockSize();
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
@Override // javax.crypto.CipherSpi
|
||
|
public byte[] engineDoFinal(byte[] bArr, int i, int i2) throws IllegalBlockSizeException, BadPaddingException {
|
||
|
if (i2 != 0) {
|
||
|
this.buffer.write(bArr, i, i2);
|
||
|
}
|
||
|
byte[] byteArray = this.buffer.toByteArray();
|
||
|
this.buffer.reset();
|
||
|
CipherParameters iESWithCipherParameters = new IESWithCipherParameters(this.engineSpec.getDerivationV(), this.engineSpec.getEncodingV(), this.engineSpec.getMacKeySize(), this.engineSpec.getCipherKeySize());
|
||
|
if (this.engineSpec.getNonce() != null) {
|
||
|
iESWithCipherParameters = new ParametersWithIV(iESWithCipherParameters, this.engineSpec.getNonce());
|
||
|
}
|
||
|
ECDomainParameters parameters = ((ECKeyParameters) this.key).getParameters();
|
||
|
AsymmetricKeyParameter asymmetricKeyParameter = this.otherKeyParameter;
|
||
|
if (asymmetricKeyParameter != null) {
|
||
|
try {
|
||
|
int i3 = this.state;
|
||
|
if (i3 == 1 || i3 == 3) {
|
||
|
this.engine.init(true, asymmetricKeyParameter, this.key, iESWithCipherParameters);
|
||
|
} else {
|
||
|
this.engine.init(false, this.key, asymmetricKeyParameter, iESWithCipherParameters);
|
||
|
}
|
||
|
return this.engine.processBlock(byteArray, 0, byteArray.length);
|
||
|
} catch (Exception e) {
|
||
|
throw new BadPaddingException(e.getMessage());
|
||
|
}
|
||
|
}
|
||
|
int i4 = this.state;
|
||
|
if (i4 == 1 || i4 == 3) {
|
||
|
ECKeyPairGenerator eCKeyPairGenerator = new ECKeyPairGenerator();
|
||
|
eCKeyPairGenerator.init(new ECKeyGenerationParameters(parameters, this.random));
|
||
|
try {
|
||
|
this.engine.init(this.key, iESWithCipherParameters, new EphemeralKeyPairGenerator(eCKeyPairGenerator, new KeyEncoder(this, this.engineSpec.getPointCompression()) { // from class: org.bouncycastle.jcajce.provider.asymmetric.ec.IESCipher.1
|
||
|
final IESCipher this$0;
|
||
|
final boolean val$usePointCompression;
|
||
|
|
||
|
@Override // org.bouncycastle.crypto.KeyEncoder
|
||
|
public byte[] getEncoded(AsymmetricKeyParameter asymmetricKeyParameter2) {
|
||
|
return ((ECPublicKeyParameters) asymmetricKeyParameter2).getQ().getEncoded(this.val$usePointCompression);
|
||
|
}
|
||
|
|
||
|
{
|
||
|
this.this$0 = this;
|
||
|
this.val$usePointCompression = r2;
|
||
|
}
|
||
|
}));
|
||
|
return this.engine.processBlock(byteArray, 0, byteArray.length);
|
||
|
} catch (Exception e2) {
|
||
|
throw new BadPaddingException(e2.getMessage());
|
||
|
}
|
||
|
}
|
||
|
if (i4 != 2 && i4 != 4) {
|
||
|
throw new IllegalStateException("cipher not initialised");
|
||
|
}
|
||
|
try {
|
||
|
this.engine.init(this.key, iESWithCipherParameters, new ECIESPublicKeyParser(parameters));
|
||
|
return this.engine.processBlock(byteArray, 0, byteArray.length);
|
||
|
} catch (InvalidCipherTextException e3) {
|
||
|
throw new BadPaddingException(e3.getMessage());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* loaded from: classes6.dex */
|
||
|
public static class ECIESwithCipher extends IESCipher {
|
||
|
public ECIESwithCipher(BlockCipher blockCipher, int i) {
|
||
|
super(new IESEngine(new ECDHBasicAgreement(), new KDF2BytesGenerator(new SHA1Digest()), new HMac(new SHA1Digest()), new PaddedBufferedBlockCipher(blockCipher)), i);
|
||
|
}
|
||
|
|
||
|
public ECIESwithCipher(BlockCipher blockCipher) {
|
||
|
super(new IESEngine(new ECDHBasicAgreement(), new KDF2BytesGenerator(new SHA1Digest()), new HMac(new SHA1Digest()), new PaddedBufferedBlockCipher(blockCipher)));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* loaded from: classes6.dex */
|
||
|
public static class OldECIESwithCipher extends IESCipher {
|
||
|
public OldECIESwithCipher(BlockCipher blockCipher, int i) {
|
||
|
super(new OldIESEngine(new ECDHBasicAgreement(), new KDF2BytesGenerator(new SHA1Digest()), new HMac(new SHA1Digest()), new PaddedBufferedBlockCipher(blockCipher)), i);
|
||
|
}
|
||
|
|
||
|
public OldECIESwithCipher(BlockCipher blockCipher) {
|
||
|
super(new OldIESEngine(new ECDHBasicAgreement(), new KDF2BytesGenerator(new SHA1Digest()), new HMac(new SHA1Digest()), new PaddedBufferedBlockCipher(blockCipher)));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@Override // javax.crypto.CipherSpi
|
||
|
public int engineDoFinal(byte[] bArr, int i, int i2, byte[] bArr2, int i3) throws ShortBufferException, IllegalBlockSizeException, BadPaddingException {
|
||
|
byte[] engineDoFinal = engineDoFinal(bArr, i, i2);
|
||
|
System.arraycopy(engineDoFinal, 0, bArr2, i3, engineDoFinal.length);
|
||
|
return engineDoFinal.length;
|
||
|
}
|
||
|
|
||
|
/* loaded from: classes6.dex */
|
||
|
public static class ECIES extends IESCipher {
|
||
|
public ECIES() {
|
||
|
super(new IESEngine(new ECDHBasicAgreement(), new KDF2BytesGenerator(new SHA1Digest()), new HMac(new SHA1Digest())));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* loaded from: classes6.dex */
|
||
|
public static class ECIESwithAES extends ECIESwithCipher {
|
||
|
public ECIESwithAES() {
|
||
|
super(new AESEngine());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* loaded from: classes6.dex */
|
||
|
public static class ECIESwithAESCBC extends ECIESwithCipher {
|
||
|
public ECIESwithAESCBC() {
|
||
|
super(new CBCBlockCipher(new AESEngine()), 16);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* loaded from: classes6.dex */
|
||
|
public static class ECIESwithDESede extends ECIESwithCipher {
|
||
|
public ECIESwithDESede() {
|
||
|
super(new DESedeEngine());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* loaded from: classes6.dex */
|
||
|
public static class ECIESwithDESedeCBC extends ECIESwithCipher {
|
||
|
public ECIESwithDESedeCBC() {
|
||
|
super(new CBCBlockCipher(new DESedeEngine()), 8);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* loaded from: classes6.dex */
|
||
|
public static class OldECIES extends IESCipher {
|
||
|
public OldECIES() {
|
||
|
super(new OldIESEngine(new ECDHBasicAgreement(), new KDF2BytesGenerator(new SHA1Digest()), new HMac(new SHA1Digest())));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* loaded from: classes6.dex */
|
||
|
public static class OldECIESwithAES extends OldECIESwithCipher {
|
||
|
public OldECIESwithAES() {
|
||
|
super(new AESEngine());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* loaded from: classes6.dex */
|
||
|
public static class OldECIESwithAESCBC extends OldECIESwithCipher {
|
||
|
public OldECIESwithAESCBC() {
|
||
|
super(new CBCBlockCipher(new AESEngine()), 16);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* loaded from: classes6.dex */
|
||
|
public static class OldECIESwithDESede extends OldECIESwithCipher {
|
||
|
public OldECIESwithDESede() {
|
||
|
super(new DESedeEngine());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* loaded from: classes6.dex */
|
||
|
public static class OldECIESwithDESedeCBC extends OldECIESwithCipher {
|
||
|
public OldECIESwithDESedeCBC() {
|
||
|
super(new CBCBlockCipher(new DESedeEngine()), 8);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public IESCipher(IESEngine iESEngine, int i) {
|
||
|
this.helper = new BCJcaJceHelper();
|
||
|
this.state = -1;
|
||
|
this.buffer = new ByteArrayOutputStream();
|
||
|
this.engineParam = null;
|
||
|
this.engineSpec = null;
|
||
|
this.dhaesMode = false;
|
||
|
this.otherKeyParameter = null;
|
||
|
this.engine = iESEngine;
|
||
|
this.ivLength = i;
|
||
|
}
|
||
|
|
||
|
public IESCipher(IESEngine iESEngine) {
|
||
|
this.helper = new BCJcaJceHelper();
|
||
|
this.state = -1;
|
||
|
this.buffer = new ByteArrayOutputStream();
|
||
|
this.engineParam = null;
|
||
|
this.engineSpec = null;
|
||
|
this.dhaesMode = false;
|
||
|
this.otherKeyParameter = null;
|
||
|
this.engine = iESEngine;
|
||
|
this.ivLength = 0;
|
||
|
}
|
||
|
}
|