447 lines
16 KiB
Java
447 lines
16 KiB
Java
|
package org.bouncycastle.crypto.signers;
|
||
|
|
||
|
import com.google.common.base.Ascii;
|
||
|
import com.google.common.primitives.UnsignedBytes;
|
||
|
import java.security.SecureRandom;
|
||
|
import org.bouncycastle.crypto.AsymmetricBlockCipher;
|
||
|
import org.bouncycastle.crypto.CryptoException;
|
||
|
import org.bouncycastle.crypto.Digest;
|
||
|
import org.bouncycastle.crypto.InvalidCipherTextException;
|
||
|
import org.bouncycastle.crypto.SignerWithRecovery;
|
||
|
import org.bouncycastle.util.Arrays;
|
||
|
|
||
|
/* loaded from: classes6.dex */
|
||
|
public class ISO9796d2PSSSigner implements SignerWithRecovery {
|
||
|
public static final int TRAILER_IMPLICIT = 188;
|
||
|
public static final int TRAILER_RIPEMD128 = 13004;
|
||
|
public static final int TRAILER_RIPEMD160 = 12748;
|
||
|
public static final int TRAILER_SHA1 = 13260;
|
||
|
public static final int TRAILER_SHA256 = 13516;
|
||
|
public static final int TRAILER_SHA384 = 14028;
|
||
|
public static final int TRAILER_SHA512 = 13772;
|
||
|
public static final int TRAILER_WHIRLPOOL = 14284;
|
||
|
private byte[] block;
|
||
|
private AsymmetricBlockCipher cipher;
|
||
|
private Digest digest;
|
||
|
private boolean fullMessage;
|
||
|
private int hLen;
|
||
|
private int keyBits;
|
||
|
private byte[] mBuf;
|
||
|
private int messageLength;
|
||
|
private byte[] preBlock;
|
||
|
private int preMStart;
|
||
|
private byte[] preSig;
|
||
|
private int preTLength;
|
||
|
private SecureRandom random;
|
||
|
private byte[] recoveredMessage;
|
||
|
private int saltLength;
|
||
|
private byte[] standardSalt;
|
||
|
private int trailer;
|
||
|
|
||
|
@Override // org.bouncycastle.crypto.Signer
|
||
|
public boolean verifySignature(byte[] bArr) {
|
||
|
int i = this.hLen;
|
||
|
byte[] bArr2 = new byte[i];
|
||
|
this.digest.doFinal(bArr2, 0);
|
||
|
byte[] bArr3 = this.preSig;
|
||
|
if (bArr3 == null) {
|
||
|
try {
|
||
|
updateWithRecoveredMessage(bArr);
|
||
|
} catch (Exception unused) {
|
||
|
return false;
|
||
|
}
|
||
|
} else if (!Arrays.areEqual(bArr3, bArr)) {
|
||
|
throw new IllegalStateException("updateWithRecoveredMessage called on different signature");
|
||
|
}
|
||
|
byte[] bArr4 = this.preBlock;
|
||
|
int i2 = this.preMStart;
|
||
|
int i3 = this.preTLength;
|
||
|
this.preSig = null;
|
||
|
this.preBlock = null;
|
||
|
byte[] bArr5 = new byte[8];
|
||
|
LtoOSP(this.recoveredMessage.length << 3, bArr5);
|
||
|
this.digest.update(bArr5, 0, 8);
|
||
|
byte[] bArr6 = this.recoveredMessage;
|
||
|
if (bArr6.length != 0) {
|
||
|
this.digest.update(bArr6, 0, bArr6.length);
|
||
|
}
|
||
|
this.digest.update(bArr2, 0, i);
|
||
|
byte[] bArr7 = this.standardSalt;
|
||
|
if (bArr7 != null) {
|
||
|
this.digest.update(bArr7, 0, bArr7.length);
|
||
|
} else {
|
||
|
this.digest.update(bArr4, i2 + this.recoveredMessage.length, this.saltLength);
|
||
|
}
|
||
|
int digestSize = this.digest.getDigestSize();
|
||
|
byte[] bArr8 = new byte[digestSize];
|
||
|
this.digest.doFinal(bArr8, 0);
|
||
|
int length = bArr4.length;
|
||
|
boolean z = true;
|
||
|
for (int i4 = 0; i4 != digestSize; i4++) {
|
||
|
if (bArr8[i4] != bArr4[((length - i3) - digestSize) + i4]) {
|
||
|
z = false;
|
||
|
}
|
||
|
}
|
||
|
clearBlock(bArr4);
|
||
|
clearBlock(bArr8);
|
||
|
if (!z) {
|
||
|
this.fullMessage = false;
|
||
|
clearBlock(this.recoveredMessage);
|
||
|
return false;
|
||
|
}
|
||
|
if (this.messageLength != 0) {
|
||
|
if (!isSameAs(this.mBuf, this.recoveredMessage)) {
|
||
|
clearBlock(this.mBuf);
|
||
|
return false;
|
||
|
}
|
||
|
this.messageLength = 0;
|
||
|
}
|
||
|
clearBlock(this.mBuf);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
@Override // org.bouncycastle.crypto.SignerWithRecovery
|
||
|
public void updateWithRecoveredMessage(byte[] bArr) throws InvalidCipherTextException {
|
||
|
int i;
|
||
|
byte[] processBlock = this.cipher.processBlock(bArr, 0, bArr.length);
|
||
|
int length = processBlock.length;
|
||
|
int i2 = (this.keyBits + 7) / 8;
|
||
|
if (length < i2) {
|
||
|
byte[] bArr2 = new byte[i2];
|
||
|
System.arraycopy(processBlock, 0, bArr2, i2 - processBlock.length, processBlock.length);
|
||
|
clearBlock(processBlock);
|
||
|
processBlock = bArr2;
|
||
|
}
|
||
|
if (((processBlock[processBlock.length - 1] & UnsignedBytes.MAX_VALUE) ^ 188) == 0) {
|
||
|
i = 1;
|
||
|
} else {
|
||
|
i = 2;
|
||
|
int i3 = ((processBlock[processBlock.length - 2] & UnsignedBytes.MAX_VALUE) << 8) | (processBlock[processBlock.length - 1] & UnsignedBytes.MAX_VALUE);
|
||
|
Integer trailer = ISOTrailers.getTrailer(this.digest);
|
||
|
if (trailer == null) {
|
||
|
throw new IllegalArgumentException("unrecognised hash in signature");
|
||
|
}
|
||
|
if (i3 != trailer.intValue()) {
|
||
|
throw new IllegalStateException("signer initialised with wrong digest for trailer ".concat(String.valueOf(i3)));
|
||
|
}
|
||
|
}
|
||
|
this.digest.doFinal(new byte[this.hLen], 0);
|
||
|
int length2 = processBlock.length;
|
||
|
int i4 = this.hLen;
|
||
|
byte[] maskGeneratorFunction1 = maskGeneratorFunction1(processBlock, (length2 - i4) - i, i4, (processBlock.length - i4) - i);
|
||
|
for (int i5 = 0; i5 != maskGeneratorFunction1.length; i5++) {
|
||
|
processBlock[i5] = (byte) (processBlock[i5] ^ maskGeneratorFunction1[i5]);
|
||
|
}
|
||
|
processBlock[0] = (byte) (processBlock[0] & Ascii.DEL);
|
||
|
int i6 = 0;
|
||
|
while (i6 != processBlock.length && processBlock[i6] != 1) {
|
||
|
i6++;
|
||
|
}
|
||
|
int i7 = i6 + 1;
|
||
|
if (i7 >= processBlock.length) {
|
||
|
clearBlock(processBlock);
|
||
|
}
|
||
|
this.fullMessage = i7 > 1;
|
||
|
int length3 = (maskGeneratorFunction1.length - i7) - this.saltLength;
|
||
|
byte[] bArr3 = new byte[length3];
|
||
|
this.recoveredMessage = bArr3;
|
||
|
System.arraycopy(processBlock, i7, bArr3, 0, length3);
|
||
|
byte[] bArr4 = this.recoveredMessage;
|
||
|
System.arraycopy(bArr4, 0, this.mBuf, 0, bArr4.length);
|
||
|
this.preSig = bArr;
|
||
|
this.preBlock = processBlock;
|
||
|
this.preMStart = i7;
|
||
|
this.preTLength = i;
|
||
|
}
|
||
|
|
||
|
@Override // org.bouncycastle.crypto.Signer
|
||
|
public void update(byte[] bArr, int i, int i2) {
|
||
|
if (this.preSig == null) {
|
||
|
while (i2 > 0 && this.messageLength < this.mBuf.length) {
|
||
|
update(bArr[i]);
|
||
|
i++;
|
||
|
i2--;
|
||
|
}
|
||
|
}
|
||
|
if (i2 > 0) {
|
||
|
this.digest.update(bArr, i, i2);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@Override // org.bouncycastle.crypto.Signer
|
||
|
public void update(byte b) {
|
||
|
if (this.preSig == null) {
|
||
|
int i = this.messageLength;
|
||
|
byte[] bArr = this.mBuf;
|
||
|
if (i < bArr.length) {
|
||
|
this.messageLength = i + 1;
|
||
|
bArr[i] = b;
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
this.digest.update(b);
|
||
|
}
|
||
|
|
||
|
@Override // org.bouncycastle.crypto.Signer
|
||
|
public void reset() {
|
||
|
this.digest.reset();
|
||
|
this.messageLength = 0;
|
||
|
byte[] bArr = this.mBuf;
|
||
|
if (bArr != null) {
|
||
|
clearBlock(bArr);
|
||
|
}
|
||
|
byte[] bArr2 = this.recoveredMessage;
|
||
|
if (bArr2 != null) {
|
||
|
clearBlock(bArr2);
|
||
|
this.recoveredMessage = null;
|
||
|
}
|
||
|
this.fullMessage = false;
|
||
|
if (this.preSig != null) {
|
||
|
this.preSig = null;
|
||
|
clearBlock(this.preBlock);
|
||
|
this.preBlock = null;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* JADX WARN: Removed duplicated region for block: B:13:0x006f */
|
||
|
/* JADX WARN: Removed duplicated region for block: B:9:0x0060 */
|
||
|
@Override // org.bouncycastle.crypto.Signer
|
||
|
/*
|
||
|
Code decompiled incorrectly, please refer to instructions dump.
|
||
|
To view partially-correct add '--show-bad-code' argument
|
||
|
*/
|
||
|
public void init(boolean r4, org.bouncycastle.crypto.CipherParameters r5) {
|
||
|
/*
|
||
|
r3 = this;
|
||
|
int r0 = r3.saltLength
|
||
|
boolean r1 = r5 instanceof org.bouncycastle.crypto.params.ParametersWithRandom
|
||
|
if (r1 == 0) goto L15
|
||
|
org.bouncycastle.crypto.params.ParametersWithRandom r5 = (org.bouncycastle.crypto.params.ParametersWithRandom) r5
|
||
|
org.bouncycastle.crypto.CipherParameters r1 = r5.getParameters()
|
||
|
org.bouncycastle.crypto.params.RSAKeyParameters r1 = (org.bouncycastle.crypto.params.RSAKeyParameters) r1
|
||
|
if (r4 == 0) goto L43
|
||
|
java.security.SecureRandom r5 = r5.getRandom()
|
||
|
goto L41
|
||
|
L15:
|
||
|
boolean r1 = r5 instanceof org.bouncycastle.crypto.params.ParametersWithSalt
|
||
|
if (r1 == 0) goto L37
|
||
|
org.bouncycastle.crypto.params.ParametersWithSalt r5 = (org.bouncycastle.crypto.params.ParametersWithSalt) r5
|
||
|
org.bouncycastle.crypto.CipherParameters r0 = r5.getParameters()
|
||
|
r1 = r0
|
||
|
org.bouncycastle.crypto.params.RSAKeyParameters r1 = (org.bouncycastle.crypto.params.RSAKeyParameters) r1
|
||
|
byte[] r5 = r5.getSalt()
|
||
|
r3.standardSalt = r5
|
||
|
int r0 = r5.length
|
||
|
int r5 = r5.length
|
||
|
int r2 = r3.saltLength
|
||
|
if (r5 != r2) goto L2f
|
||
|
goto L43
|
||
|
L2f:
|
||
|
java.lang.IllegalArgumentException r4 = new java.lang.IllegalArgumentException
|
||
|
java.lang.String r5 = "Fixed salt is of wrong length"
|
||
|
r4.<init>(r5)
|
||
|
throw r4
|
||
|
L37:
|
||
|
r1 = r5
|
||
|
org.bouncycastle.crypto.params.RSAKeyParameters r1 = (org.bouncycastle.crypto.params.RSAKeyParameters) r1
|
||
|
if (r4 == 0) goto L43
|
||
|
java.security.SecureRandom r5 = new java.security.SecureRandom
|
||
|
r5.<init>()
|
||
|
L41:
|
||
|
r3.random = r5
|
||
|
L43:
|
||
|
org.bouncycastle.crypto.AsymmetricBlockCipher r5 = r3.cipher
|
||
|
r5.init(r4, r1)
|
||
|
java.math.BigInteger r4 = r1.getModulus()
|
||
|
int r4 = r4.bitLength()
|
||
|
r3.keyBits = r4
|
||
|
int r4 = r4 + 7
|
||
|
int r4 = r4 / 8
|
||
|
byte[] r5 = new byte[r4]
|
||
|
r3.block = r5
|
||
|
int r5 = r3.trailer
|
||
|
r1 = 188(0xbc, float:2.63E-43)
|
||
|
if (r5 != r1) goto L6f
|
||
|
org.bouncycastle.crypto.Digest r5 = r3.digest
|
||
|
int r5 = r5.getDigestSize()
|
||
|
int r4 = r4 - r5
|
||
|
int r4 = r4 - r0
|
||
|
int r4 = r4 + (-2)
|
||
|
byte[] r4 = new byte[r4]
|
||
|
r3.mBuf = r4
|
||
|
goto L7d
|
||
|
L6f:
|
||
|
org.bouncycastle.crypto.Digest r5 = r3.digest
|
||
|
int r5 = r5.getDigestSize()
|
||
|
int r4 = r4 - r5
|
||
|
int r4 = r4 - r0
|
||
|
int r4 = r4 + (-3)
|
||
|
byte[] r4 = new byte[r4]
|
||
|
r3.mBuf = r4
|
||
|
L7d:
|
||
|
r3.reset()
|
||
|
return
|
||
|
*/
|
||
|
throw new UnsupportedOperationException("Method not decompiled: org.bouncycastle.crypto.signers.ISO9796d2PSSSigner.init(boolean, org.bouncycastle.crypto.CipherParameters):void");
|
||
|
}
|
||
|
|
||
|
@Override // org.bouncycastle.crypto.SignerWithRecovery
|
||
|
public boolean hasFullMessage() {
|
||
|
return this.fullMessage;
|
||
|
}
|
||
|
|
||
|
@Override // org.bouncycastle.crypto.SignerWithRecovery
|
||
|
public byte[] getRecoveredMessage() {
|
||
|
return this.recoveredMessage;
|
||
|
}
|
||
|
|
||
|
@Override // org.bouncycastle.crypto.Signer
|
||
|
public byte[] generateSignature() throws CryptoException {
|
||
|
int digestSize = this.digest.getDigestSize();
|
||
|
byte[] bArr = new byte[digestSize];
|
||
|
this.digest.doFinal(bArr, 0);
|
||
|
byte[] bArr2 = new byte[8];
|
||
|
LtoOSP(this.messageLength << 3, bArr2);
|
||
|
this.digest.update(bArr2, 0, 8);
|
||
|
this.digest.update(this.mBuf, 0, this.messageLength);
|
||
|
this.digest.update(bArr, 0, digestSize);
|
||
|
byte[] bArr3 = this.standardSalt;
|
||
|
if (bArr3 == null) {
|
||
|
bArr3 = new byte[this.saltLength];
|
||
|
this.random.nextBytes(bArr3);
|
||
|
}
|
||
|
this.digest.update(bArr3, 0, bArr3.length);
|
||
|
int digestSize2 = this.digest.getDigestSize();
|
||
|
byte[] bArr4 = new byte[digestSize2];
|
||
|
this.digest.doFinal(bArr4, 0);
|
||
|
int i = this.trailer == 188 ? 1 : 2;
|
||
|
byte[] bArr5 = this.block;
|
||
|
int length = bArr5.length;
|
||
|
int i2 = this.messageLength;
|
||
|
int length2 = (((length - i2) - bArr3.length) - this.hLen) - i;
|
||
|
bArr5[length2 - 1] = 1;
|
||
|
System.arraycopy(this.mBuf, 0, bArr5, length2, i2);
|
||
|
System.arraycopy(bArr3, 0, this.block, length2 + this.messageLength, bArr3.length);
|
||
|
byte[] maskGeneratorFunction1 = maskGeneratorFunction1(bArr4, 0, digestSize2, (this.block.length - this.hLen) - i);
|
||
|
for (int i3 = 0; i3 != maskGeneratorFunction1.length; i3++) {
|
||
|
byte[] bArr6 = this.block;
|
||
|
bArr6[i3] = (byte) (bArr6[i3] ^ maskGeneratorFunction1[i3]);
|
||
|
}
|
||
|
byte[] bArr7 = this.block;
|
||
|
int length3 = bArr7.length;
|
||
|
int i4 = this.hLen;
|
||
|
System.arraycopy(bArr4, 0, bArr7, (length3 - i4) - i, i4);
|
||
|
int i5 = this.trailer;
|
||
|
if (i5 == 188) {
|
||
|
byte[] bArr8 = this.block;
|
||
|
bArr8[bArr8.length - 1] = PSSSigner.TRAILER_IMPLICIT;
|
||
|
} else {
|
||
|
byte[] bArr9 = this.block;
|
||
|
bArr9[bArr9.length - 2] = (byte) (i5 >>> 8);
|
||
|
bArr9[bArr9.length - 1] = (byte) i5;
|
||
|
}
|
||
|
byte[] bArr10 = this.block;
|
||
|
bArr10[0] = (byte) (bArr10[0] & Ascii.DEL);
|
||
|
byte[] processBlock = this.cipher.processBlock(bArr10, 0, bArr10.length);
|
||
|
int i6 = this.messageLength;
|
||
|
byte[] bArr11 = new byte[i6];
|
||
|
this.recoveredMessage = bArr11;
|
||
|
byte[] bArr12 = this.mBuf;
|
||
|
this.fullMessage = i6 <= bArr12.length;
|
||
|
System.arraycopy(bArr12, 0, bArr11, 0, i6);
|
||
|
clearBlock(this.mBuf);
|
||
|
clearBlock(this.block);
|
||
|
this.messageLength = 0;
|
||
|
return processBlock;
|
||
|
}
|
||
|
|
||
|
private byte[] maskGeneratorFunction1(byte[] bArr, int i, int i2, int i3) {
|
||
|
int i4;
|
||
|
byte[] bArr2 = new byte[i3];
|
||
|
byte[] bArr3 = new byte[this.hLen];
|
||
|
byte[] bArr4 = new byte[4];
|
||
|
this.digest.reset();
|
||
|
int i5 = 0;
|
||
|
while (true) {
|
||
|
i4 = this.hLen;
|
||
|
if (i5 >= i3 / i4) {
|
||
|
break;
|
||
|
}
|
||
|
ItoOSP(i5, bArr4);
|
||
|
this.digest.update(bArr, i, i2);
|
||
|
this.digest.update(bArr4, 0, 4);
|
||
|
this.digest.doFinal(bArr3, 0);
|
||
|
int i6 = this.hLen;
|
||
|
System.arraycopy(bArr3, 0, bArr2, i5 * i6, i6);
|
||
|
i5++;
|
||
|
}
|
||
|
if (i4 * i5 < i3) {
|
||
|
ItoOSP(i5, bArr4);
|
||
|
this.digest.update(bArr, i, i2);
|
||
|
this.digest.update(bArr4, 0, 4);
|
||
|
this.digest.doFinal(bArr3, 0);
|
||
|
int i7 = i5 * this.hLen;
|
||
|
System.arraycopy(bArr3, 0, bArr2, i7, i3 - i7);
|
||
|
}
|
||
|
return bArr2;
|
||
|
}
|
||
|
|
||
|
private boolean isSameAs(byte[] bArr, byte[] bArr2) {
|
||
|
boolean z = this.messageLength == bArr2.length;
|
||
|
for (int i = 0; i != bArr2.length; i++) {
|
||
|
if (bArr[i] != bArr2[i]) {
|
||
|
z = false;
|
||
|
}
|
||
|
}
|
||
|
return z;
|
||
|
}
|
||
|
|
||
|
private void clearBlock(byte[] bArr) {
|
||
|
for (int i = 0; i != bArr.length; i++) {
|
||
|
bArr[i] = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void LtoOSP(long j, byte[] bArr) {
|
||
|
bArr[0] = (byte) (j >>> 56);
|
||
|
bArr[1] = (byte) (j >>> 48);
|
||
|
bArr[2] = (byte) (j >>> 40);
|
||
|
bArr[3] = (byte) (j >>> 32);
|
||
|
bArr[4] = (byte) (j >>> 24);
|
||
|
bArr[5] = (byte) (j >>> 16);
|
||
|
bArr[6] = (byte) (j >>> 8);
|
||
|
bArr[7] = (byte) j;
|
||
|
}
|
||
|
|
||
|
private void ItoOSP(int i, byte[] bArr) {
|
||
|
bArr[0] = (byte) (i >>> 24);
|
||
|
bArr[1] = (byte) (i >>> 16);
|
||
|
bArr[2] = (byte) (i >>> 8);
|
||
|
bArr[3] = (byte) i;
|
||
|
}
|
||
|
|
||
|
public ISO9796d2PSSSigner(AsymmetricBlockCipher asymmetricBlockCipher, Digest digest, int i, boolean z) {
|
||
|
int intValue;
|
||
|
this.cipher = asymmetricBlockCipher;
|
||
|
this.digest = digest;
|
||
|
this.hLen = digest.getDigestSize();
|
||
|
this.saltLength = i;
|
||
|
if (z) {
|
||
|
intValue = 188;
|
||
|
} else {
|
||
|
Integer trailer = ISOTrailers.getTrailer(digest);
|
||
|
if (trailer == null) {
|
||
|
StringBuilder sb = new StringBuilder("no valid trailer for digest: ");
|
||
|
sb.append(digest.getAlgorithmName());
|
||
|
throw new IllegalArgumentException(sb.toString());
|
||
|
}
|
||
|
intValue = trailer.intValue();
|
||
|
}
|
||
|
this.trailer = intValue;
|
||
|
}
|
||
|
|
||
|
public ISO9796d2PSSSigner(AsymmetricBlockCipher asymmetricBlockCipher, Digest digest, int i) {
|
||
|
this(asymmetricBlockCipher, digest, i, false);
|
||
|
}
|
||
|
}
|