258 lines
12 KiB
Java
258 lines
12 KiB
Java
package org.bouncycastle.crypto.engines;
|
|
|
|
import java.io.PrintStream;
|
|
import java.math.BigInteger;
|
|
import java.util.Vector;
|
|
import org.bouncycastle.crypto.AsymmetricBlockCipher;
|
|
import org.bouncycastle.crypto.CipherParameters;
|
|
import org.bouncycastle.crypto.DataLengthException;
|
|
import org.bouncycastle.crypto.InvalidCipherTextException;
|
|
import org.bouncycastle.crypto.params.NaccacheSternKeyParameters;
|
|
import org.bouncycastle.crypto.params.NaccacheSternPrivateKeyParameters;
|
|
import org.bouncycastle.crypto.params.ParametersWithRandom;
|
|
import org.bouncycastle.util.Arrays;
|
|
|
|
/* loaded from: classes6.dex */
|
|
public class NaccacheSternEngine implements AsymmetricBlockCipher {
|
|
private boolean forEncryption;
|
|
private NaccacheSternKeyParameters key;
|
|
private static BigInteger ZERO = BigInteger.valueOf(0);
|
|
private static BigInteger ONE = BigInteger.valueOf(1);
|
|
private Vector[] lookup = null;
|
|
private boolean debug = false;
|
|
|
|
public void setDebug(boolean z) {
|
|
this.debug = z;
|
|
}
|
|
|
|
public byte[] processData(byte[] bArr) throws InvalidCipherTextException {
|
|
byte[] processBlock;
|
|
if (this.debug) {
|
|
System.out.println();
|
|
}
|
|
if (bArr.length <= getInputBlockSize()) {
|
|
if (this.debug) {
|
|
System.out.println("data size is less then input block size, processing directly");
|
|
}
|
|
return processBlock(bArr, 0, bArr.length);
|
|
}
|
|
int inputBlockSize = getInputBlockSize();
|
|
int outputBlockSize = getOutputBlockSize();
|
|
if (this.debug) {
|
|
PrintStream printStream = System.out;
|
|
StringBuilder sb = new StringBuilder("Input blocksize is: ");
|
|
sb.append(inputBlockSize);
|
|
sb.append(" bytes");
|
|
printStream.println(sb.toString());
|
|
PrintStream printStream2 = System.out;
|
|
StringBuilder sb2 = new StringBuilder("Output blocksize is: ");
|
|
sb2.append(outputBlockSize);
|
|
sb2.append(" bytes");
|
|
printStream2.println(sb2.toString());
|
|
PrintStream printStream3 = System.out;
|
|
StringBuilder sb3 = new StringBuilder("Data has length:.... ");
|
|
sb3.append(bArr.length);
|
|
sb3.append(" bytes");
|
|
printStream3.println(sb3.toString());
|
|
}
|
|
byte[] bArr2 = new byte[((bArr.length / inputBlockSize) + 1) * outputBlockSize];
|
|
int i = 0;
|
|
int i2 = 0;
|
|
while (i < bArr.length) {
|
|
int i3 = i + inputBlockSize;
|
|
if (i3 < bArr.length) {
|
|
processBlock = processBlock(bArr, i, inputBlockSize);
|
|
i = i3;
|
|
} else {
|
|
processBlock = processBlock(bArr, i, bArr.length - i);
|
|
i += bArr.length - i;
|
|
}
|
|
if (this.debug) {
|
|
System.out.println("new datapos is ".concat(String.valueOf(i)));
|
|
}
|
|
if (processBlock == null) {
|
|
if (this.debug) {
|
|
System.out.println("cipher returned null");
|
|
}
|
|
throw new InvalidCipherTextException("cipher returned null");
|
|
}
|
|
System.arraycopy(processBlock, 0, bArr2, i2, processBlock.length);
|
|
i2 += processBlock.length;
|
|
}
|
|
byte[] bArr3 = new byte[i2];
|
|
System.arraycopy(bArr2, 0, bArr3, 0, i2);
|
|
if (this.debug) {
|
|
PrintStream printStream4 = System.out;
|
|
StringBuilder sb4 = new StringBuilder("returning ");
|
|
sb4.append(i2);
|
|
sb4.append(" bytes");
|
|
printStream4.println(sb4.toString());
|
|
}
|
|
return bArr3;
|
|
}
|
|
|
|
@Override // org.bouncycastle.crypto.AsymmetricBlockCipher
|
|
public byte[] processBlock(byte[] bArr, int i, int i2) throws InvalidCipherTextException {
|
|
if (this.key == null) {
|
|
throw new IllegalStateException("NaccacheStern engine not initialised");
|
|
}
|
|
if (i2 > getInputBlockSize() + 1) {
|
|
throw new DataLengthException("input too large for Naccache-Stern cipher.\n");
|
|
}
|
|
if (!this.forEncryption && i2 < getInputBlockSize()) {
|
|
throw new InvalidCipherTextException("BlockLength does not match modulus for Naccache-Stern cipher.\n");
|
|
}
|
|
if (i != 0 || i2 != bArr.length) {
|
|
byte[] bArr2 = new byte[i2];
|
|
System.arraycopy(bArr, i, bArr2, 0, i2);
|
|
bArr = bArr2;
|
|
}
|
|
BigInteger bigInteger = new BigInteger(1, bArr);
|
|
if (this.debug) {
|
|
System.out.println("input as BigInteger: ".concat(String.valueOf(bigInteger)));
|
|
}
|
|
if (this.forEncryption) {
|
|
return encrypt(bigInteger);
|
|
}
|
|
Vector vector = new Vector();
|
|
NaccacheSternPrivateKeyParameters naccacheSternPrivateKeyParameters = (NaccacheSternPrivateKeyParameters) this.key;
|
|
Vector smallPrimes = naccacheSternPrivateKeyParameters.getSmallPrimes();
|
|
for (int i3 = 0; i3 < smallPrimes.size(); i3++) {
|
|
BigInteger modPow = bigInteger.modPow(naccacheSternPrivateKeyParameters.getPhi_n().divide((BigInteger) smallPrimes.elementAt(i3)), naccacheSternPrivateKeyParameters.getModulus());
|
|
Vector vector2 = this.lookup[i3];
|
|
if (vector2.size() != ((BigInteger) smallPrimes.elementAt(i3)).intValue()) {
|
|
if (this.debug) {
|
|
PrintStream printStream = System.out;
|
|
StringBuilder sb = new StringBuilder("Prime is ");
|
|
sb.append(smallPrimes.elementAt(i3));
|
|
sb.append(", lookup table has size ");
|
|
sb.append(vector2.size());
|
|
printStream.println(sb.toString());
|
|
}
|
|
StringBuilder sb2 = new StringBuilder("Error in lookup Array for ");
|
|
sb2.append(((BigInteger) smallPrimes.elementAt(i3)).intValue());
|
|
sb2.append(": Size mismatch. Expected ArrayList with length ");
|
|
sb2.append(((BigInteger) smallPrimes.elementAt(i3)).intValue());
|
|
sb2.append(" but found ArrayList of length ");
|
|
sb2.append(this.lookup[i3].size());
|
|
throw new InvalidCipherTextException(sb2.toString());
|
|
}
|
|
int indexOf = vector2.indexOf(modPow);
|
|
if (indexOf == -1) {
|
|
if (this.debug) {
|
|
PrintStream printStream2 = System.out;
|
|
StringBuilder sb3 = new StringBuilder("Actual prime is ");
|
|
sb3.append(smallPrimes.elementAt(i3));
|
|
printStream2.println(sb3.toString());
|
|
System.out.println("Decrypted value is ".concat(String.valueOf(modPow)));
|
|
PrintStream printStream3 = System.out;
|
|
StringBuilder sb4 = new StringBuilder("LookupList for ");
|
|
sb4.append(smallPrimes.elementAt(i3));
|
|
sb4.append(" with size ");
|
|
sb4.append(this.lookup[i3].size());
|
|
sb4.append(" is: ");
|
|
printStream3.println(sb4.toString());
|
|
for (int i4 = 0; i4 < this.lookup[i3].size(); i4++) {
|
|
System.out.println(this.lookup[i3].elementAt(i4));
|
|
}
|
|
}
|
|
throw new InvalidCipherTextException("Lookup failed");
|
|
}
|
|
vector.addElement(BigInteger.valueOf(indexOf));
|
|
}
|
|
return chineseRemainder(vector, smallPrimes).toByteArray();
|
|
}
|
|
|
|
@Override // org.bouncycastle.crypto.AsymmetricBlockCipher
|
|
public void init(boolean z, CipherParameters cipherParameters) {
|
|
this.forEncryption = z;
|
|
if (cipherParameters instanceof ParametersWithRandom) {
|
|
cipherParameters = ((ParametersWithRandom) cipherParameters).getParameters();
|
|
}
|
|
this.key = (NaccacheSternKeyParameters) cipherParameters;
|
|
if (this.forEncryption) {
|
|
return;
|
|
}
|
|
if (this.debug) {
|
|
System.out.println("Constructing lookup Array");
|
|
}
|
|
NaccacheSternPrivateKeyParameters naccacheSternPrivateKeyParameters = (NaccacheSternPrivateKeyParameters) this.key;
|
|
Vector smallPrimes = naccacheSternPrivateKeyParameters.getSmallPrimes();
|
|
this.lookup = new Vector[smallPrimes.size()];
|
|
for (int i = 0; i < smallPrimes.size(); i++) {
|
|
BigInteger bigInteger = (BigInteger) smallPrimes.elementAt(i);
|
|
int intValue = bigInteger.intValue();
|
|
this.lookup[i] = new Vector();
|
|
this.lookup[i].addElement(ONE);
|
|
if (this.debug) {
|
|
System.out.println("Constructing lookup ArrayList for ".concat(String.valueOf(intValue)));
|
|
}
|
|
BigInteger bigInteger2 = ZERO;
|
|
for (int i2 = 1; i2 < intValue; i2++) {
|
|
bigInteger2 = bigInteger2.add(naccacheSternPrivateKeyParameters.getPhi_n());
|
|
this.lookup[i].addElement(naccacheSternPrivateKeyParameters.getG().modPow(bigInteger2.divide(bigInteger), naccacheSternPrivateKeyParameters.getModulus()));
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override // org.bouncycastle.crypto.AsymmetricBlockCipher
|
|
public int getOutputBlockSize() {
|
|
return this.forEncryption ? this.key.getModulus().toByteArray().length : ((this.key.getLowerSigmaBound() + 7) / 8) - 1;
|
|
}
|
|
|
|
@Override // org.bouncycastle.crypto.AsymmetricBlockCipher
|
|
public int getInputBlockSize() {
|
|
return this.forEncryption ? ((this.key.getLowerSigmaBound() + 7) / 8) - 1 : this.key.getModulus().toByteArray().length;
|
|
}
|
|
|
|
public byte[] encrypt(BigInteger bigInteger) {
|
|
byte[] byteArray = this.key.getModulus().toByteArray();
|
|
Arrays.fill(byteArray, (byte) 0);
|
|
byte[] byteArray2 = this.key.getG().modPow(bigInteger, this.key.getModulus()).toByteArray();
|
|
System.arraycopy(byteArray2, 0, byteArray, byteArray.length - byteArray2.length, byteArray2.length);
|
|
if (this.debug) {
|
|
PrintStream printStream = System.out;
|
|
StringBuilder sb = new StringBuilder("Encrypted value is: ");
|
|
sb.append(new BigInteger(byteArray));
|
|
printStream.println(sb.toString());
|
|
}
|
|
return byteArray;
|
|
}
|
|
|
|
public byte[] addCryptedBlocks(byte[] bArr, byte[] bArr2) throws InvalidCipherTextException {
|
|
if (this.forEncryption) {
|
|
if (bArr.length > getOutputBlockSize() || bArr2.length > getOutputBlockSize()) {
|
|
throw new InvalidCipherTextException("BlockLength too large for simple addition.\n");
|
|
}
|
|
} else if (bArr.length > getInputBlockSize() || bArr2.length > getInputBlockSize()) {
|
|
throw new InvalidCipherTextException("BlockLength too large for simple addition.\n");
|
|
}
|
|
BigInteger bigInteger = new BigInteger(1, bArr);
|
|
BigInteger bigInteger2 = new BigInteger(1, bArr2);
|
|
BigInteger mod = bigInteger.multiply(bigInteger2).mod(this.key.getModulus());
|
|
if (this.debug) {
|
|
System.out.println("c(m1) as BigInteger:....... ".concat(String.valueOf(bigInteger)));
|
|
System.out.println("c(m2) as BigInteger:....... ".concat(String.valueOf(bigInteger2)));
|
|
System.out.println("c(m1)*c(m2)%n = c(m1+m2)%n: ".concat(String.valueOf(mod)));
|
|
}
|
|
byte[] byteArray = this.key.getModulus().toByteArray();
|
|
Arrays.fill(byteArray, (byte) 0);
|
|
System.arraycopy(mod.toByteArray(), 0, byteArray, byteArray.length - mod.toByteArray().length, mod.toByteArray().length);
|
|
return byteArray;
|
|
}
|
|
|
|
private static BigInteger chineseRemainder(Vector vector, Vector vector2) {
|
|
BigInteger bigInteger = ZERO;
|
|
BigInteger bigInteger2 = ONE;
|
|
for (int i = 0; i < vector2.size(); i++) {
|
|
bigInteger2 = bigInteger2.multiply((BigInteger) vector2.elementAt(i));
|
|
}
|
|
for (int i2 = 0; i2 < vector2.size(); i2++) {
|
|
BigInteger bigInteger3 = (BigInteger) vector2.elementAt(i2);
|
|
BigInteger divide = bigInteger2.divide(bigInteger3);
|
|
bigInteger = bigInteger.add(divide.multiply(divide.modInverse(bigInteger3)).multiply((BigInteger) vector.elementAt(i2)));
|
|
}
|
|
return bigInteger.mod(bigInteger2);
|
|
}
|
|
}
|