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

出于无聊, 打算从头实现一遍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     }

时间: 2024-08-24 00:52:59

重复造轮子之RSA算法(一) 大素数生成的相关文章

重复造轮子系列--dijkstra算法

spf.h 1 #ifndef SPF_H_ 2 #define SPF_H_ 3 4 5 typedef struct { 6 int length; 7 char src; 8 char dst; 9 char prev_hop; 10 } dijkstra; 11 12 #define MAX 1024 13 #define NODE_NUM 5 14 #define TRUE 1 15 #define FALSE 0 16 17 #endif spf.c 1 #include <stdi

避免重复造轮子的UI自动化测试框架开发

一懒起来就好久没更新文章了,其实懒也还是因为忙,今年上半年的加班赶上了去年一年的加班,加班不息啊,好了吐槽完就写写一直打算继续的自动化开发 目前各种UI测试框架层出不穷,但是万变不离其宗,驱动PC浏览器的基本上底层都是selenium,驱动无线app和浏览器基本是appium.monkey之类的,底层都是基于官方支持的自动化测试框架开发而来,然后上层又做了各种封装 首先在开始计划开发自动化时,第一步是了解目前已有的自动化开发技术,上面说了,最底层的就那几种,根据实际要去测试的业务需求选择合适的自

重复造轮子,编写一个轻量级的异步写日志的实用工具类(LogAsyncWriter)

一说到写日志,大家可能推荐一堆的开源日志框架,如:Log4Net.NLog,这些日志框架确实也不错,比较强大也比较灵活,但也正因为又强大又灵活,导致我们使用他们时需要引用一些DLL,同时还要学习各种用法及配置文件,这对于有些小工具.小程序.小网站来说,有点“杀鸡焉俺用牛刀”的感觉,而且如果对这些日志框架不了解,可能输出来的日志性能或效果未毕是与自己所想的,鉴于这几个原因,我自己重复造轮子,编写了一个轻量级的异步写日志的实用工具类(LogAsyncWriter),这个类还是比较简单的,实现思路也很

重复造轮子系列——基于FastReport设计打印模板实现桌面端WPF套打和商超POS高度自适应小票打印

重复造轮子系列——基于FastReport设计打印模板实现桌面端WPF套打和商超POS高度自适应小票打印 一.引言 桌面端系统经常需要对接各种硬件设备,比如扫描器.读卡器.打印机等. 这里介绍下桌面端系统打印经常使用的场景. 1.一种是类似票务方面的系统需要打印固定格式的票据.比如景点门票.车票.电影票. 这种基本是根据模板调整位置套打. 2.还有一种是交易小票,比如商超POS小票,打印长度会随着内容的大小自动伸缩. 这种就不仅仅是固定格式的套打了,还得计算数据行以适应不同的打印长度. 打印方式

GitHub Android 最火开源项目Top20 GitHub 上的开源项目不胜枚举,越来越多的开源项目正在迁移到GitHub平台上。基于不要重复造轮子的原则,了解当下比较流行的Android与iOS开源项目很是必要。利用这些项目,有时能够让你达到事半功倍的效果。

1. ActionBarSherlock(推荐) ActionBarSherlock应该算得上是GitHub上最火的Android开源项目了,它是一个独立的库,通过一个API和主题,开发者就可以很方便地使用所有版本的Android动作栏的设计模式. 对于Android 4.0及更高版本,ActionBarSherlock可以自动使用本地ActionBar实现,而对于之前没有ActionBar功能的版本,基于Ice Cream Sandwich的自定义动作栏实现将自动围绕布局.能够让开发者轻松开发

第27篇 重复造轮子---模拟IIS服务器

在写程序的时候,重复造轮子是程序员的一个大忌,很多人对重复造轮子持有反对的态度,但是我觉得这个造轮子的过程,是对于现有的知识的一个深入的探索的过程,虽然我们不可能把轮子造的那么的完善,对于现在有的东西是一个更好的理解和使用.   当你打开一个网页时,你会看到一个html页面的呈现,当然这是一个完整的Http的请求和响应的过程,无非是对HTML+CSS+JS一个综合的产物,在这个过程中浏览器请求数据的过程中会发出一个有一个格式的字符串(基于http协议生成的http请求报文),服务器在接收这样的一

论要不要重复造轮子

在程序界有一句话很流行,不要重复造轮子.然而,这句话被滥用了.已经渐渐沦为程序员懒惰的借口.甚至因此而盲目指责那些勤奋的人.    大多数情况下初学者很难分清楚自己是不是在重复造轮子.当我头一次听到这句忠告的时候,我变得异常敏感,在做什么之前都要判断一下是否在造轮子.我跟大多数普通人一样,容易受到他人只言片语的不良影响.事实上很多时候,避免造轮子并不是我的首要目标.我的目标是完成一项任务,任务完成的速度要尽量快,质量要尽量好.而不是去判断自己在不在造轮子.    使用他人的现成轮子是实现快速任务

重复造轮子感悟 – XLinq性能提升心得

曾经的两座大山 1.EF 刚接触linq那段时间,感觉这家伙好神奇,语法好优美,好厉害.后来经历了EF一些不如意的地方,就想去弥补,既然想弥补,就必须去了解原理.最开始甚至很长一段时间都搞不懂IQueryProvider(小声说,其实现在也没完全搞懂),好不容易把IQueryProvider搞懂了,然后才发现好戏才刚刚开始,这个时候尝试写了第一个ORM.那个时候不明白表达式树的原理,自然一开始的思路就是走一点算一点,走到后面就没法走了,因为思路太乱了.这个时候就感觉EF太牛了,那么复杂的linq

重复造轮子的概念

网上的概念: 1.圆形的轮子已经是最合适的形状,再造一次无疑是做无用的重复工作. 也指明知道自己做的不可能比前人已做的更好,还要坚持做: 2.轮子就是一种现成的通用函数,或已有的开源代码.库.框架等,能够重复使用,以减少不必要的重复工作. 不要发明轮子,但是重复制造轮子也有它的意义: 1.自己亲自实践一次,能力得到锻炼,明白具体原理算法: 2.有时甚至可能从中发现新的问题,加以改进,比前人做得更好. 原文地址:https://www.cnblogs.com/tuji-sjp/p/8325329.