what-the-bank/sources/org/bouncycastle/pqc/crypto/mceliece/McElieceKobaraImaiCipher.java

179 lines
8.4 KiB
Java
Raw Permalink Normal View History

2024-07-27 18:17:47 +07:00
package org.bouncycastle.pqc.crypto.mceliece;
import java.security.SecureRandom;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.InvalidCipherTextException;
import org.bouncycastle.crypto.digests.SHA1Digest;
import org.bouncycastle.crypto.params.ParametersWithRandom;
import org.bouncycastle.crypto.prng.DigestRandomGenerator;
import org.bouncycastle.pqc.crypto.MessageEncryptor;
import org.bouncycastle.pqc.math.linearalgebra.ByteUtils;
import org.bouncycastle.pqc.math.linearalgebra.GF2Vector;
import org.bouncycastle.pqc.math.linearalgebra.IntegerFunctions;
/* loaded from: classes6.dex */
public class McElieceKobaraImaiCipher implements MessageEncryptor {
private static final String DEFAULT_PRNG_NAME = "SHA1PRNG";
public static final String OID = "1.3.6.1.4.1.8301.3.1.3.4.2.3";
public static final byte[] PUBLIC_CONSTANT = "a predetermined public constant".getBytes();
private boolean forEncryption;
private int k;
McElieceCCA2KeyParameters key;
private Digest messDigest;
private int n;
private SecureRandom sr;
private int t;
@Override // org.bouncycastle.pqc.crypto.MessageEncryptor
public byte[] messageEncrypt(byte[] bArr) {
if (!this.forEncryption) {
throw new IllegalStateException("cipher initialised for decryption");
}
int digestSize = this.messDigest.getDigestSize();
int i = this.k >> 3;
int bitLength = (IntegerFunctions.binomial(this.n, this.t).bitLength() - 1) >> 3;
byte[] bArr2 = PUBLIC_CONSTANT;
int length = ((i + bitLength) - digestSize) - bArr2.length;
if (bArr.length > length) {
length = bArr.length;
}
int length2 = bArr2.length + length;
int i2 = ((length2 + digestSize) - i) - bitLength;
byte[] bArr3 = new byte[length2];
System.arraycopy(bArr, 0, bArr3, 0, bArr.length);
System.arraycopy(bArr2, 0, bArr3, length, bArr2.length);
byte[] bArr4 = new byte[digestSize];
this.sr.nextBytes(bArr4);
DigestRandomGenerator digestRandomGenerator = new DigestRandomGenerator(new SHA1Digest());
digestRandomGenerator.addSeedMaterial(bArr4);
byte[] bArr5 = new byte[length2];
digestRandomGenerator.nextBytes(bArr5);
for (int i3 = length2 - 1; i3 >= 0; i3--) {
bArr5[i3] = (byte) (bArr5[i3] ^ bArr3[i3]);
}
byte[] bArr6 = new byte[this.messDigest.getDigestSize()];
this.messDigest.update(bArr5, 0, length2);
this.messDigest.doFinal(bArr6, 0);
for (int i4 = digestSize - 1; i4 >= 0; i4--) {
bArr6[i4] = (byte) (bArr6[i4] ^ bArr4[i4]);
}
byte[] concatenate = ByteUtils.concatenate(bArr6, bArr5);
byte[] bArr7 = new byte[0];
if (i2 > 0) {
bArr7 = new byte[i2];
System.arraycopy(concatenate, 0, bArr7, 0, i2);
}
byte[] bArr8 = new byte[bitLength];
System.arraycopy(concatenate, i2, bArr8, 0, bitLength);
byte[] bArr9 = new byte[i];
System.arraycopy(concatenate, bitLength + i2, bArr9, 0, i);
byte[] encoded = McElieceCCA2Primitives.encryptionPrimitive((McElieceCCA2PublicKeyParameters) this.key, GF2Vector.OS2VP(this.k, bArr9), Conversions.encode(this.n, this.t, bArr8)).getEncoded();
return i2 > 0 ? ByteUtils.concatenate(bArr7, encoded) : encoded;
}
@Override // org.bouncycastle.pqc.crypto.MessageEncryptor
public byte[] messageDecrypt(byte[] bArr) throws InvalidCipherTextException {
byte[] bArr2;
if (this.forEncryption) {
throw new IllegalStateException("cipher initialised for decryption");
}
int i = this.n >> 3;
if (bArr.length < i) {
throw new InvalidCipherTextException("Bad Padding: Ciphertext too short.");
}
int digestSize = this.messDigest.getDigestSize();
int i2 = this.k >> 3;
int length = bArr.length - i;
if (length > 0) {
byte[][] split = ByteUtils.split(bArr, length);
bArr2 = split[0];
bArr = split[1];
} else {
bArr2 = new byte[0];
}
GF2Vector[] decryptionPrimitive = McElieceCCA2Primitives.decryptionPrimitive((McElieceCCA2PrivateKeyParameters) this.key, GF2Vector.OS2VP(this.n, bArr));
byte[] encoded = decryptionPrimitive[0].getEncoded();
GF2Vector gF2Vector = decryptionPrimitive[1];
if (encoded.length > i2) {
encoded = ByteUtils.subArray(encoded, 0, i2);
}
byte[] concatenate = ByteUtils.concatenate(ByteUtils.concatenate(bArr2, Conversions.decode(this.n, this.t, gF2Vector)), encoded);
int length2 = concatenate.length - digestSize;
byte[][] split2 = ByteUtils.split(concatenate, digestSize);
byte[] bArr3 = split2[0];
byte[] bArr4 = split2[1];
byte[] bArr5 = new byte[this.messDigest.getDigestSize()];
this.messDigest.update(bArr4, 0, bArr4.length);
this.messDigest.doFinal(bArr5, 0);
while (true) {
digestSize--;
if (digestSize < 0) {
break;
}
bArr5[digestSize] = (byte) (bArr5[digestSize] ^ bArr3[digestSize]);
}
DigestRandomGenerator digestRandomGenerator = new DigestRandomGenerator(new SHA1Digest());
digestRandomGenerator.addSeedMaterial(bArr5);
byte[] bArr6 = new byte[length2];
digestRandomGenerator.nextBytes(bArr6);
for (int i3 = length2 - 1; i3 >= 0; i3--) {
bArr6[i3] = (byte) (bArr6[i3] ^ bArr4[i3]);
}
byte[] bArr7 = PUBLIC_CONSTANT;
byte[][] split3 = ByteUtils.split(bArr6, length2 - bArr7.length);
byte[] bArr8 = split3[0];
if (ByteUtils.equals(split3[1], bArr7)) {
return bArr8;
}
throw new InvalidCipherTextException("Bad Padding: invalid ciphertext");
}
public void initCipherDecrypt(McElieceCCA2PrivateKeyParameters mcElieceCCA2PrivateKeyParameters) {
this.messDigest = Utils.getDigest(mcElieceCCA2PrivateKeyParameters.getDigest());
this.n = mcElieceCCA2PrivateKeyParameters.getN();
this.k = mcElieceCCA2PrivateKeyParameters.getK();
this.t = mcElieceCCA2PrivateKeyParameters.getT();
}
@Override // org.bouncycastle.pqc.crypto.MessageEncryptor
public void init(boolean z, CipherParameters cipherParameters) {
this.forEncryption = z;
if (!z) {
McElieceCCA2PrivateKeyParameters mcElieceCCA2PrivateKeyParameters = (McElieceCCA2PrivateKeyParameters) cipherParameters;
this.key = mcElieceCCA2PrivateKeyParameters;
initCipherDecrypt(mcElieceCCA2PrivateKeyParameters);
} else {
if (!(cipherParameters instanceof ParametersWithRandom)) {
this.sr = new SecureRandom();
McElieceCCA2PublicKeyParameters mcElieceCCA2PublicKeyParameters = (McElieceCCA2PublicKeyParameters) cipherParameters;
this.key = mcElieceCCA2PublicKeyParameters;
initCipherEncrypt(mcElieceCCA2PublicKeyParameters);
return;
}
ParametersWithRandom parametersWithRandom = (ParametersWithRandom) cipherParameters;
this.sr = parametersWithRandom.getRandom();
McElieceCCA2PublicKeyParameters mcElieceCCA2PublicKeyParameters2 = (McElieceCCA2PublicKeyParameters) parametersWithRandom.getParameters();
this.key = mcElieceCCA2PublicKeyParameters2;
initCipherEncrypt(mcElieceCCA2PublicKeyParameters2);
}
}
public int getKeySize(McElieceCCA2KeyParameters mcElieceCCA2KeyParameters) {
if (mcElieceCCA2KeyParameters instanceof McElieceCCA2PublicKeyParameters) {
return ((McElieceCCA2PublicKeyParameters) mcElieceCCA2KeyParameters).getN();
}
if (mcElieceCCA2KeyParameters instanceof McElieceCCA2PrivateKeyParameters) {
return ((McElieceCCA2PrivateKeyParameters) mcElieceCCA2KeyParameters).getN();
}
throw new IllegalArgumentException("unsupported type");
}
private void initCipherEncrypt(McElieceCCA2PublicKeyParameters mcElieceCCA2PublicKeyParameters) {
this.messDigest = Utils.getDigest(mcElieceCCA2PublicKeyParameters.getDigest());
this.n = mcElieceCCA2PublicKeyParameters.getN();
this.k = mcElieceCCA2PublicKeyParameters.getK();
this.t = mcElieceCCA2PublicKeyParameters.getT();
}
}