目前的公开密钥 算法大部分基于大整数分解、有限域上的离散对数问题和椭 圆曲线上的离散对数问题,这些数学难题的构建大部分都需 要生成一种超大的素数,尤其在经典的RSA算法中,生成的素数的质量对系统的安全性有很大的影响。
1.原理
费马小定理:假如p是质数,且gcd(a,p)=1,那么 a^(p-1)≡1(mod p)。即:假如a是整数,p是质数,且a,p互质(即两者只有一个公约数1),那么a的(p-1)次方除以p的余数恒等于1。
基于此可以快速判断一个大整数是否为素数。
Miller-Rabin算法:Fermat算法的一个变形改进。
2. BigInteger中的API
public static BigInteger probablePrime(int bitLength, Random rnd)
结果是素数的概率为1-2^(-100),貌似内部使用了Miller-Rabin算法。
先不论这个概率问题,生成100个2048位的素数耗时141475ms
调用DHCryptUtils.randomPrime(2048)10次的时间已经达到了143614ms。
再来看这个概率问题,1-2^(-100)已经很接近于1。
如果还想提高这个概率,可以调用
public boolean isProbablePrime(int certainty)
certainty表示判断的准确率为1-2^(-certainty)
Random r = new Random();BigInteger bigInteger = BigInteger.probablePrime(2048, r);while(!bigInteger.isProbablePrime(256)){bigInteger = BigInteger.probablePrime(2048, r);}
3. DH的KeyPairGenerator如何生成P和Q
一步一步进断点之后,发现了DSAParameterGenerator中的方法generatePandQ
certainty的取值和生成素数的长度有关系
byte var11 = -1;if (var1 <= 1024) {var11 = 80;} else if (var1 == 2048) {var11 = 112;}
我这里需要的2048位,因此certainty为112。
内部生成素数的方法:
BigInteger var14 = null;while(true) {BigInteger var13;BigInteger var16;do {var0.nextBytes(var9);var14 = new BigInteger(1, var9);var16 = (new BigInteger(1, var5.digest(var9))).mod(TWO.pow(var2 - 1));var13 = TWO.pow(var2 - 1).add(var16).add(ONE).subtract(var16.mod(TWO));} while(!var13.isProbablePrime(var11));var16 = ONE;for(int var15 = 0; var15 < 4 * var1; ++var15) {BigInteger[] var17 = new BigInteger[var7 + 1];BigInteger var19;BigInteger var20;for(int var18 = 0; var18 <= var7; ++var18) {var19 = BigInteger.valueOf((long)var18);var20 = var14.add(var16).add(var19).mod(var10);byte[] var21 = var5.digest(toByteArray(var20));var17[var18] = new BigInteger(1, var21);}BigInteger var24 = var17[0];for(int var25 = 1; var25 < var7; ++var25) {var24 = var24.add(var17[var25].multiply(TWO.pow(var25 * var6)));}var24 = var24.add(var17[var7].mod(TWO.pow(var8)).multiply(TWO.pow(var7 * var6)));var19 = TWO.pow(var1 - 1);var20 = var24.add(var19);BigInteger var26 = var20.mod(var13.multiply(TWO));BigInteger var12 = var20.subtract(var26.subtract(ONE));if (var12.compareTo(var19) > -1 && var12.isProbablePrime(var11)) {BigInteger[] var22 = new BigInteger[]{var12, var13, var14, BigInteger.valueOf((long)var15)};return var22;}var16 = var16.add(BigInteger.valueOf((long)var7)).add(ONE);}}