码迷,mamicode.com
首页 > 编程语言 > 详细

重复造轮子之RSA算法(一) 大素数生成

时间:2015-02-25 00:42:20      阅读:290      评论:0      收藏:0      [点我收藏+]

标签:

出于无聊, 打算从头实现一遍RSA算法

 

第一步, 大素数生成

Java的BigInteger里, 有个现成的方法

  public static BigInteger probablePrime(int bitLength, Random rnd) {

  bitLength是期望生成的素数的二进制位数, rnd是随机数发生器

  函数注释表明, 这个方法的返回值为合数的概率为2^-100

生成100个1024位的素数, 耗时13471ms

但是显然我不打算直接使用这个函数, 要做就从最底层做起!

 

目前的做法是基于费马素性检测

假如a是整数,p是质数,且a,p互质(即两者只有一个公约数1),那么a的(p-1)次方除以p的余数恒等于1。

也就是说, 如果p为素数, 那么对于任何a<p, 有

a ^ p % p == a   成立

而它的逆命题则至少有1/2的概率成立

那么我们就可以通过多次素性检测, 来减少假素数出现的概率

 

而素数定理, 又指出了素数的密度与ln(x)成反比, 也就是说, 我们可以先随机生成一个n bit的整数, 如果不是素数, 则继续向后取, 那么, 大概取n个数, 就能碰到一个素数

 

原理大概就是这样

 

中间有一些优化, 是为了减少对大整数的直接计算

附上代码如下

技术分享
 1     /**
 2      * 计算 base^exp % n
 3      *
 4      * @param base
 5      * @param exp
 6      * @param n
 7      * @return
 8      */
 9     public static BigInteger expmod(int base, BigInteger exp, BigInteger n) {
10         if (exp.equals(BigInteger.ZERO)) {
11             return BigInteger.ONE;
12         }
13 
14         if (!exp.testBit(0)) {//如果为偶数
15             return expmod(base, exp.divide(BigInteger.valueOf(2)), n).pow(2).remainder(n);
16         } else {
17             return (expmod(base, exp.subtract(BigInteger.ONE).divide(BigInteger.valueOf(2)), n).pow(2).multiply(BigInteger.valueOf(base))).remainder(n);
18         }
19     }
20 
21     /**
22      * 费马测试, 如果返回false, 则n肯定为合数, 如果为true, 则n有一半以上的概率为素数
23      *
24      * @param n
25      * @return
26      */
27     public static boolean fermatTest(BigInteger n) {
28         int base = 0;
29         if (n.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) < 0) {
30             base = ran.nextInt(n.intValue() - 1) + 1;
31         } else {
32             base = ran.nextInt(Integer.MAX_VALUE - 1) + 1;
33         }
34         if (expmod(base, n, n).equals(BigInteger.valueOf(base))) {
35             return true;
36         } else {
37             return false;
38         }
39     }
40 
41 
42     public static boolean isPrime(BigInteger n) {
43         return isPrime(n, 100);
44     }
45 
46     /**
47      * 多次调用费马测试, 判定输入的n是否为质数
48      *
49      * @param n
50      * @param tryTime
51      * @return
52      */
53     public static boolean isPrime(BigInteger n, int tryTime) {
54         for (int i = 0; i < tryTime; i++) {
55             if (!fermatTest(n)) {
56                 return false;
57             }
58         }
59         return true;
60     }
61 
62     /**
63      * 产生一个n bit的素数
64      *
65      * @param bitCount
66      * @return
67      */
68     public static BigInteger getPrime(int bitCount) {
69         //随机生成一个n bit的大整数
70         BigInteger init = new BigInteger(bitCount, ran);
71         //如果n为偶数, 则加一变为奇数
72         if (!init.testBit(0)) {
73             init = init.setBit(0);
74         }
75         int i = 0;
76         //基于素数定理, 平均只需要不到n次搜索, 就能找到一个素数
77         while (!isPrime(init)) {
78             i++;
79             init = init.add(BigInteger.valueOf(2));
80         }
81         //System.out.println(String.format("try %d\ttimes", i));
82         return init;
83     }
View Code

 

重复造轮子之RSA算法(一) 大素数生成

标签:

原文地址:http://www.cnblogs.com/stevenczp/p/4299072.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!