223 lines
8.6 KiB
Java
223 lines
8.6 KiB
Java
package org.bouncycastle.crypto.encodings;
|
|
|
|
import java.security.AccessController;
|
|
import java.security.PrivilegedAction;
|
|
import java.security.SecureRandom;
|
|
import org.bouncycastle.crypto.AsymmetricBlockCipher;
|
|
import org.bouncycastle.crypto.CipherParameters;
|
|
import org.bouncycastle.crypto.InvalidCipherTextException;
|
|
import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
|
|
import org.bouncycastle.crypto.params.ParametersWithRandom;
|
|
|
|
/* loaded from: classes6.dex */
|
|
public class PKCS1Encoding implements AsymmetricBlockCipher {
|
|
private static final int HEADER_LENGTH = 10;
|
|
public static final String NOT_STRICT_LENGTH_ENABLED_PROPERTY = "org.bouncycastle.pkcs1.not_strict";
|
|
public static final String STRICT_LENGTH_ENABLED_PROPERTY = "org.bouncycastle.pkcs1.strict";
|
|
private AsymmetricBlockCipher engine;
|
|
private byte[] fallback;
|
|
private boolean forEncryption;
|
|
private boolean forPrivateKey;
|
|
private int pLen;
|
|
private SecureRandom random;
|
|
private boolean useStrictLength;
|
|
|
|
@Override // org.bouncycastle.crypto.AsymmetricBlockCipher
|
|
public byte[] processBlock(byte[] bArr, int i, int i2) throws InvalidCipherTextException {
|
|
return this.forEncryption ? encodeBlock(bArr, i, i2) : decodeBlock(bArr, i, i2);
|
|
}
|
|
|
|
@Override // org.bouncycastle.crypto.AsymmetricBlockCipher
|
|
public void init(boolean z, CipherParameters cipherParameters) {
|
|
AsymmetricKeyParameter asymmetricKeyParameter;
|
|
if (cipherParameters instanceof ParametersWithRandom) {
|
|
ParametersWithRandom parametersWithRandom = (ParametersWithRandom) cipherParameters;
|
|
this.random = parametersWithRandom.getRandom();
|
|
asymmetricKeyParameter = (AsymmetricKeyParameter) parametersWithRandom.getParameters();
|
|
} else {
|
|
asymmetricKeyParameter = (AsymmetricKeyParameter) cipherParameters;
|
|
if (!asymmetricKeyParameter.isPrivate() && z) {
|
|
this.random = new SecureRandom();
|
|
}
|
|
}
|
|
this.engine.init(z, cipherParameters);
|
|
this.forPrivateKey = asymmetricKeyParameter.isPrivate();
|
|
this.forEncryption = z;
|
|
}
|
|
|
|
public AsymmetricBlockCipher getUnderlyingCipher() {
|
|
return this.engine;
|
|
}
|
|
|
|
@Override // org.bouncycastle.crypto.AsymmetricBlockCipher
|
|
public int getOutputBlockSize() {
|
|
int outputBlockSize = this.engine.getOutputBlockSize();
|
|
return this.forEncryption ? outputBlockSize : outputBlockSize - 10;
|
|
}
|
|
|
|
@Override // org.bouncycastle.crypto.AsymmetricBlockCipher
|
|
public int getInputBlockSize() {
|
|
int inputBlockSize = this.engine.getInputBlockSize();
|
|
return this.forEncryption ? inputBlockSize - 10 : inputBlockSize;
|
|
}
|
|
|
|
private boolean useStrict() {
|
|
String str = (String) AccessController.doPrivileged(new PrivilegedAction(this) { // from class: org.bouncycastle.crypto.encodings.PKCS1Encoding.1
|
|
final PKCS1Encoding this$0;
|
|
|
|
@Override // java.security.PrivilegedAction
|
|
public Object run() {
|
|
return System.getProperty(PKCS1Encoding.STRICT_LENGTH_ENABLED_PROPERTY);
|
|
}
|
|
|
|
{
|
|
this.this$0 = this;
|
|
}
|
|
});
|
|
return ((String) AccessController.doPrivileged(new PrivilegedAction(this) { // from class: org.bouncycastle.crypto.encodings.PKCS1Encoding.2
|
|
final PKCS1Encoding this$0;
|
|
|
|
@Override // java.security.PrivilegedAction
|
|
public Object run() {
|
|
return System.getProperty(PKCS1Encoding.NOT_STRICT_LENGTH_ENABLED_PROPERTY);
|
|
}
|
|
|
|
{
|
|
this.this$0 = this;
|
|
}
|
|
})) != null ? !r1.equals("true") : str == null || str.equals("true");
|
|
}
|
|
|
|
private byte[] encodeBlock(byte[] bArr, int i, int i2) throws InvalidCipherTextException {
|
|
if (i2 > getInputBlockSize()) {
|
|
throw new IllegalArgumentException("input data too large");
|
|
}
|
|
int inputBlockSize = this.engine.getInputBlockSize();
|
|
byte[] bArr2 = new byte[inputBlockSize];
|
|
if (this.forPrivateKey) {
|
|
bArr2[0] = 1;
|
|
for (int i3 = 1; i3 != (inputBlockSize - i2) - 1; i3++) {
|
|
bArr2[i3] = -1;
|
|
}
|
|
} else {
|
|
this.random.nextBytes(bArr2);
|
|
bArr2[0] = 2;
|
|
for (int i4 = 1; i4 != (inputBlockSize - i2) - 1; i4++) {
|
|
while (bArr2[i4] == 0) {
|
|
bArr2[i4] = (byte) this.random.nextInt();
|
|
}
|
|
}
|
|
}
|
|
int i5 = inputBlockSize - i2;
|
|
bArr2[i5 - 1] = 0;
|
|
System.arraycopy(bArr, i, bArr2, i5, i2);
|
|
return this.engine.processBlock(bArr2, 0, inputBlockSize);
|
|
}
|
|
|
|
private byte[] decodeBlockOrRandom(byte[] bArr, int i, int i2) throws InvalidCipherTextException {
|
|
if (!this.forPrivateKey) {
|
|
throw new InvalidCipherTextException("sorry, this method is only for decryption, not for signing");
|
|
}
|
|
byte[] processBlock = this.engine.processBlock(bArr, i, i2);
|
|
byte[] bArr2 = this.fallback;
|
|
if (bArr2 == null) {
|
|
bArr2 = new byte[this.pLen];
|
|
this.random.nextBytes(bArr2);
|
|
}
|
|
if (processBlock.length < getOutputBlockSize()) {
|
|
throw new InvalidCipherTextException("block truncated");
|
|
}
|
|
if (this.useStrictLength && processBlock.length != this.engine.getOutputBlockSize()) {
|
|
throw new InvalidCipherTextException("block incorrect size");
|
|
}
|
|
int checkPkcs1Encoding = checkPkcs1Encoding(processBlock, this.pLen);
|
|
byte[] bArr3 = new byte[this.pLen];
|
|
int i3 = 0;
|
|
while (true) {
|
|
int i4 = this.pLen;
|
|
if (i3 >= i4) {
|
|
return bArr3;
|
|
}
|
|
bArr3[i3] = (byte) ((processBlock[(processBlock.length - i4) + i3] & (~checkPkcs1Encoding)) | (bArr2[i3] & checkPkcs1Encoding));
|
|
i3++;
|
|
}
|
|
}
|
|
|
|
private byte[] decodeBlock(byte[] bArr, int i, int i2) throws InvalidCipherTextException {
|
|
byte b;
|
|
if (this.pLen != -1) {
|
|
return decodeBlockOrRandom(bArr, i, i2);
|
|
}
|
|
byte[] processBlock = this.engine.processBlock(bArr, i, i2);
|
|
if (processBlock.length < getOutputBlockSize()) {
|
|
throw new InvalidCipherTextException("block truncated");
|
|
}
|
|
byte b2 = processBlock[0];
|
|
if (this.forPrivateKey) {
|
|
if (b2 != 2) {
|
|
throw new InvalidCipherTextException("unknown block type");
|
|
}
|
|
} else if (b2 != 1) {
|
|
throw new InvalidCipherTextException("unknown block type");
|
|
}
|
|
if (this.useStrictLength && processBlock.length != this.engine.getOutputBlockSize()) {
|
|
throw new InvalidCipherTextException("block incorrect size");
|
|
}
|
|
int i3 = 1;
|
|
while (i3 != processBlock.length && (b = processBlock[i3]) != 0) {
|
|
if (b2 == 1 && b != -1) {
|
|
throw new InvalidCipherTextException("block padding incorrect");
|
|
}
|
|
i3++;
|
|
}
|
|
int i4 = i3 + 1;
|
|
if (i4 > processBlock.length || i4 < 10) {
|
|
throw new InvalidCipherTextException("no data in block");
|
|
}
|
|
int length = processBlock.length - i4;
|
|
byte[] bArr2 = new byte[length];
|
|
System.arraycopy(processBlock, i4, bArr2, 0, length);
|
|
return bArr2;
|
|
}
|
|
|
|
private static int checkPkcs1Encoding(byte[] bArr, int i) {
|
|
int i2 = bArr[0] ^ 2;
|
|
int length = bArr.length;
|
|
int i3 = i + 1;
|
|
for (int i4 = 1; i4 < length - i3; i4++) {
|
|
byte b = bArr[i4];
|
|
int i5 = b | (b >> 1);
|
|
int i6 = i5 | (i5 >> 2);
|
|
i2 |= ((i6 | (i6 >> 4)) & 1) - 1;
|
|
}
|
|
int i7 = bArr[bArr.length - i3] | i2;
|
|
int i8 = i7 | (i7 >> 1);
|
|
int i9 = i8 | (i8 >> 2);
|
|
return ~(((i9 | (i9 >> 4)) & 1) - 1);
|
|
}
|
|
|
|
public PKCS1Encoding(AsymmetricBlockCipher asymmetricBlockCipher, byte[] bArr) {
|
|
this.pLen = -1;
|
|
this.fallback = null;
|
|
this.engine = asymmetricBlockCipher;
|
|
this.useStrictLength = useStrict();
|
|
this.fallback = bArr;
|
|
this.pLen = bArr.length;
|
|
}
|
|
|
|
public PKCS1Encoding(AsymmetricBlockCipher asymmetricBlockCipher, int i) {
|
|
this.pLen = -1;
|
|
this.fallback = null;
|
|
this.engine = asymmetricBlockCipher;
|
|
this.useStrictLength = useStrict();
|
|
this.pLen = i;
|
|
}
|
|
|
|
public PKCS1Encoding(AsymmetricBlockCipher asymmetricBlockCipher) {
|
|
this.pLen = -1;
|
|
this.fallback = null;
|
|
this.engine = asymmetricBlockCipher;
|
|
this.useStrictLength = useStrict();
|
|
}
|
|
}
|