239 lines
9.8 KiB
Java
239 lines
9.8 KiB
Java
|
package org.bouncycastle.crypto.generators;
|
||
|
|
||
|
import java.math.BigInteger;
|
||
|
import java.security.SecureRandom;
|
||
|
import org.bouncycastle.crypto.Digest;
|
||
|
import org.bouncycastle.crypto.digests.SHA1Digest;
|
||
|
import org.bouncycastle.crypto.params.DSAParameterGenerationParameters;
|
||
|
import org.bouncycastle.crypto.params.DSAParameters;
|
||
|
import org.bouncycastle.crypto.params.DSAValidationParameters;
|
||
|
import org.bouncycastle.util.Arrays;
|
||
|
import org.bouncycastle.util.BigIntegers;
|
||
|
import org.bouncycastle.util.encoders.Hex;
|
||
|
|
||
|
/* loaded from: classes6.dex */
|
||
|
public class DSAParametersGenerator {
|
||
|
private int L;
|
||
|
private int N;
|
||
|
private int certainty;
|
||
|
private Digest digest;
|
||
|
private int iterations;
|
||
|
private SecureRandom random;
|
||
|
private int usageIndex;
|
||
|
private boolean use186_3;
|
||
|
private static final BigInteger ZERO = BigInteger.valueOf(0);
|
||
|
private static final BigInteger ONE = BigInteger.valueOf(1);
|
||
|
private static final BigInteger TWO = BigInteger.valueOf(2);
|
||
|
|
||
|
private static int getDefaultN(int i) {
|
||
|
return i > 1024 ? 256 : 160;
|
||
|
}
|
||
|
|
||
|
public void init(DSAParameterGenerationParameters dSAParameterGenerationParameters) {
|
||
|
int l = dSAParameterGenerationParameters.getL();
|
||
|
int n = dSAParameterGenerationParameters.getN();
|
||
|
if (l < 1024 || l > 3072 || l % 1024 != 0) {
|
||
|
throw new IllegalArgumentException("L values must be between 1024 and 3072 and a multiple of 1024");
|
||
|
}
|
||
|
if (l == 1024 && n != 160) {
|
||
|
throw new IllegalArgumentException("N must be 160 for L = 1024");
|
||
|
}
|
||
|
if (l == 2048 && n != 224 && n != 256) {
|
||
|
throw new IllegalArgumentException("N must be 224 or 256 for L = 2048");
|
||
|
}
|
||
|
if (l == 3072 && n != 256) {
|
||
|
throw new IllegalArgumentException("N must be 256 for L = 3072");
|
||
|
}
|
||
|
if ((this.digest.getDigestSize() << 3) < n) {
|
||
|
throw new IllegalStateException("Digest output size too small for value of N");
|
||
|
}
|
||
|
this.L = l;
|
||
|
this.N = n;
|
||
|
this.certainty = dSAParameterGenerationParameters.getCertainty();
|
||
|
this.iterations = Math.max(getMinimumIterations(l), (this.certainty + 1) / 2);
|
||
|
this.random = dSAParameterGenerationParameters.getRandom();
|
||
|
this.use186_3 = true;
|
||
|
this.usageIndex = dSAParameterGenerationParameters.getUsageIndex();
|
||
|
}
|
||
|
|
||
|
public void init(int i, int i2, SecureRandom secureRandom) {
|
||
|
this.L = i;
|
||
|
this.N = getDefaultN(i);
|
||
|
this.certainty = i2;
|
||
|
this.iterations = Math.max(getMinimumIterations(this.L), (i2 + 1) / 2);
|
||
|
this.random = secureRandom;
|
||
|
this.use186_3 = false;
|
||
|
this.usageIndex = -1;
|
||
|
}
|
||
|
|
||
|
public DSAParameters generateParameters() {
|
||
|
return this.use186_3 ? generateParameters_FIPS186_3() : generateParameters_FIPS186_2();
|
||
|
}
|
||
|
|
||
|
private boolean isProbablePrime(BigInteger bigInteger) {
|
||
|
return bigInteger.isProbablePrime(this.certainty);
|
||
|
}
|
||
|
|
||
|
private static void inc(byte[] bArr) {
|
||
|
for (int length = bArr.length - 1; length >= 0; length--) {
|
||
|
byte b = (byte) (bArr[length] + 1);
|
||
|
bArr[length] = b;
|
||
|
if (b != 0) {
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private static void hash(Digest digest, byte[] bArr, byte[] bArr2, int i) {
|
||
|
digest.update(bArr, 0, bArr.length);
|
||
|
digest.doFinal(bArr2, i);
|
||
|
}
|
||
|
|
||
|
private static int getMinimumIterations(int i) {
|
||
|
if (i <= 1024) {
|
||
|
return 40;
|
||
|
}
|
||
|
return (((i - 1) / 1024) << 3) + 48;
|
||
|
}
|
||
|
|
||
|
private DSAParameters generateParameters_FIPS186_3() {
|
||
|
BigInteger bit;
|
||
|
int i;
|
||
|
BigInteger subtract;
|
||
|
BigInteger calculateGenerator_FIPS186_3_Verifiable;
|
||
|
Digest digest = this.digest;
|
||
|
int digestSize = digest.getDigestSize() << 3;
|
||
|
byte[] bArr = new byte[this.N / 8];
|
||
|
int i2 = this.L;
|
||
|
int i3 = (i2 - 1) / digestSize;
|
||
|
int i4 = i2 / 8;
|
||
|
byte[] bArr2 = new byte[i4];
|
||
|
int digestSize2 = digest.getDigestSize();
|
||
|
byte[] bArr3 = new byte[digestSize2];
|
||
|
loop0: while (true) {
|
||
|
this.random.nextBytes(bArr);
|
||
|
int i5 = 0;
|
||
|
hash(digest, bArr, bArr3, 0);
|
||
|
bit = new BigInteger(1, bArr3).mod(ONE.shiftLeft(this.N - 1)).setBit(0).setBit(this.N - 1);
|
||
|
if (isProbablePrime(bit)) {
|
||
|
byte[] clone = Arrays.clone(bArr);
|
||
|
int i6 = this.L;
|
||
|
i = 0;
|
||
|
while (i < (i6 << 2)) {
|
||
|
for (int i7 = 1; i7 <= i3; i7++) {
|
||
|
inc(clone);
|
||
|
hash(digest, clone, bArr2, i4 - (i7 * digestSize2));
|
||
|
}
|
||
|
int i8 = i4 - (i3 * digestSize2);
|
||
|
inc(clone);
|
||
|
hash(digest, clone, bArr3, i5);
|
||
|
System.arraycopy(bArr3, digestSize2 - i8, bArr2, i5, i8);
|
||
|
bArr2[i5] = (byte) (bArr2[i5] | Byte.MIN_VALUE);
|
||
|
BigInteger bigInteger = new BigInteger(1, bArr2);
|
||
|
subtract = bigInteger.subtract(bigInteger.mod(bit.shiftLeft(1)).subtract(ONE));
|
||
|
if (subtract.bitLength() == this.L && isProbablePrime(subtract)) {
|
||
|
break loop0;
|
||
|
}
|
||
|
i++;
|
||
|
i5 = 0;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
int i9 = this.usageIndex;
|
||
|
return (i9 < 0 || (calculateGenerator_FIPS186_3_Verifiable = calculateGenerator_FIPS186_3_Verifiable(digest, subtract, bit, bArr, i9)) == null) ? new DSAParameters(subtract, bit, calculateGenerator_FIPS186_3_Unverifiable(subtract, bit, this.random), new DSAValidationParameters(bArr, i)) : new DSAParameters(subtract, bit, calculateGenerator_FIPS186_3_Verifiable, new DSAValidationParameters(bArr, i, this.usageIndex));
|
||
|
}
|
||
|
|
||
|
private DSAParameters generateParameters_FIPS186_2() {
|
||
|
int i = 20;
|
||
|
byte[] bArr = new byte[20];
|
||
|
byte[] bArr2 = new byte[20];
|
||
|
byte[] bArr3 = new byte[20];
|
||
|
byte[] bArr4 = new byte[20];
|
||
|
int i2 = this.L;
|
||
|
int i3 = (i2 - 1) / 160;
|
||
|
int i4 = i2 / 8;
|
||
|
byte[] bArr5 = new byte[i4];
|
||
|
if (!(this.digest instanceof SHA1Digest)) {
|
||
|
throw new IllegalStateException("can only use SHA-1 for generating FIPS 186-2 parameters");
|
||
|
}
|
||
|
while (true) {
|
||
|
this.random.nextBytes(bArr);
|
||
|
hash(this.digest, bArr, bArr2, 0);
|
||
|
System.arraycopy(bArr, 0, bArr3, 0, i);
|
||
|
inc(bArr3);
|
||
|
hash(this.digest, bArr3, bArr3, 0);
|
||
|
for (int i5 = 0; i5 != i; i5++) {
|
||
|
bArr4[i5] = (byte) (bArr2[i5] ^ bArr3[i5]);
|
||
|
}
|
||
|
bArr4[0] = (byte) (bArr4[0] | Byte.MIN_VALUE);
|
||
|
bArr4[19] = (byte) (bArr4[19] | 1);
|
||
|
BigInteger bigInteger = new BigInteger(1, bArr4);
|
||
|
if (isProbablePrime(bigInteger)) {
|
||
|
byte[] clone = Arrays.clone(bArr);
|
||
|
inc(clone);
|
||
|
int i6 = 0;
|
||
|
while (i6 < 4096) {
|
||
|
for (int i7 = 1; i7 <= i3; i7++) {
|
||
|
inc(clone);
|
||
|
hash(this.digest, clone, bArr5, i4 - (i7 * 20));
|
||
|
}
|
||
|
int i8 = i4 - (i3 * 20);
|
||
|
inc(clone);
|
||
|
hash(this.digest, clone, bArr2, 0);
|
||
|
System.arraycopy(bArr2, 20 - i8, bArr5, 0, i8);
|
||
|
bArr5[0] = (byte) (bArr5[0] | Byte.MIN_VALUE);
|
||
|
BigInteger bigInteger2 = new BigInteger(1, bArr5);
|
||
|
BigInteger subtract = bigInteger2.subtract(bigInteger2.mod(bigInteger.shiftLeft(1)).subtract(ONE));
|
||
|
if (subtract.bitLength() == this.L && isProbablePrime(subtract)) {
|
||
|
return new DSAParameters(subtract, bigInteger, calculateGenerator_FIPS186_2(subtract, bigInteger, this.random), new DSAValidationParameters(bArr, i6));
|
||
|
}
|
||
|
i6++;
|
||
|
i = 20;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private static BigInteger calculateGenerator_FIPS186_3_Verifiable(Digest digest, BigInteger bigInteger, BigInteger bigInteger2, byte[] bArr, int i) {
|
||
|
BigInteger divide = bigInteger.subtract(ONE).divide(bigInteger2);
|
||
|
byte[] decode = Hex.decode("6767656E");
|
||
|
int length = bArr.length + decode.length;
|
||
|
byte[] bArr2 = new byte[length + 3];
|
||
|
System.arraycopy(bArr, 0, bArr2, 0, bArr.length);
|
||
|
System.arraycopy(decode, 0, bArr2, bArr.length, decode.length);
|
||
|
bArr2[length] = (byte) i;
|
||
|
byte[] bArr3 = new byte[digest.getDigestSize()];
|
||
|
for (int i2 = 1; i2 < 65536; i2++) {
|
||
|
inc(bArr2);
|
||
|
hash(digest, bArr2, bArr3, 0);
|
||
|
BigInteger modPow = new BigInteger(1, bArr3).modPow(divide, bigInteger);
|
||
|
if (modPow.compareTo(TWO) >= 0) {
|
||
|
return modPow;
|
||
|
}
|
||
|
}
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
private static BigInteger calculateGenerator_FIPS186_3_Unverifiable(BigInteger bigInteger, BigInteger bigInteger2, SecureRandom secureRandom) {
|
||
|
return calculateGenerator_FIPS186_2(bigInteger, bigInteger2, secureRandom);
|
||
|
}
|
||
|
|
||
|
private static BigInteger calculateGenerator_FIPS186_2(BigInteger bigInteger, BigInteger bigInteger2, SecureRandom secureRandom) {
|
||
|
BigInteger modPow;
|
||
|
BigInteger divide = bigInteger.subtract(ONE).divide(bigInteger2);
|
||
|
BigInteger subtract = bigInteger.subtract(TWO);
|
||
|
do {
|
||
|
modPow = BigIntegers.createRandomInRange(TWO, subtract, secureRandom).modPow(divide, bigInteger);
|
||
|
} while (modPow.bitLength() <= 1);
|
||
|
return modPow;
|
||
|
}
|
||
|
|
||
|
public DSAParametersGenerator(Digest digest) {
|
||
|
this.digest = digest;
|
||
|
}
|
||
|
|
||
|
public DSAParametersGenerator() {
|
||
|
this(new SHA1Digest());
|
||
|
}
|
||
|
}
|