RSA算法中的大素数-素性测试

版权声明:本文为博主原创文章,转载需添加原文链接。 https://blog.csdn.net/makenothing/article/details/90318351

0 前言

RSA算法基于一个十分简单的数论事实:将两个大素数相乘十分容易,但是想要对其乘积进行因式分解却极其困难。
本文讨论关于素数的相关知识。

1 素性测试

问题1: 如何判断一个大整数是否为素数

1.1 试除法

试除法: 判定n是否是素数,写一个循环从2到sqrt(n)判断其能否整除n,若都不能则n为素数。

如果n比较小的话,采用试除法当然是非常高效快捷的。但是当n很大的时候,这个算法可就行不通了
以RSA1024为例,当公钥为

0x890e23101a542913da8a4350672c9ef8e7b34c2687ce8cd8db3fb34244a791d60c9dc0a53172a56dcc8a66f553c0ae51e9e2e2ce9486fa6b00a6c556bfed139001133cdfe5921c425eb8823b1bd0a4c00920d24bee2633256328502eadbfac1420f9a5f47139de6f14d8eb7c2b7c0cec42530c0a71dadb80c7214f5cd19a3f2f

时,两个质因数分别为

0xe5a111a219c64f841669400f51a54dd4e75184004f0f4d21c6ae182cfb528652a02d6d677a72b564c505b1ed42a0c648dbfe14eb66b04c0d60ba3872826c32e7

0x98cb760764484e29245521be08e7f38edeebfca8427149524ba7f4735e1d5f3a45d585cb3722ff4c07c19165be738311dc346a914966f5b311416fed3b425079

转换为十进制分别为

12026655772210679470465581609002525329245773732132014742758935511187863487919026457076252932048619706498126046597130520643092209728783224795661331197604583

8002511426596424351829267099531651390448054153452321185350746845306277585856673898048740413439442356860630765545600353049345324913056448174487017235828857

这是一个155位数和一个154位数,都在2的511次方左右,这是无法进行常规计算的!
当然,并不是没有办法的,数学家们总有一些歪门邪道来给我们指明道路。

1.2 费马小定理

费马小定理是数论中的一个定理:假如a是一个整数,p是一个质数,那么ap−a是p的倍数,可以表示为 ap ≡a(modp) 如果a不是p的倍数,这个定理也可以写成 ap−1≡1(modp)

需要注意的是,费马小定理是判定一个数是否为素数的必要条件,并非充分条件,因为存在着一些伪素数满足费马小定理却不是素数,如2340≡1(mod341),但是341=11×31

1.3 Fermat素性测试

我们只考虑了a=2的情况,如果我们考虑a=3的情况,一个合数可能在a=2时通过了测试,但a=3时的计算结果却排除了素数的可能。于是,人们扩展了伪素数的定义,称满足an−1modn=1的合数n叫做以a为底的伪素数(pseudoprime to base a)。前10亿个自然数中同时以2和3为底的伪素数只有1272个,这个数目不到刚才的1/4。这告诉我们如果同时验证a=2和a=3两种情况,算法出错的概率降到了0.000025。容易想到,选择用来测试的a越多,算法越准确。通常我们的做法是,随机选择若干个小于待测数的正整数作为底数a进行若干次测试,只要有一次没有通过测试就可以判定这个数为合数。这就是Fermat素性测试。

1.4 Miller-Rabin素性测试

要测试N是否为素数,首先将N−1分解为2sd。在每次测试开始时,先随机选一个介于[1,N−1]的整数a,之后如果对所有的r∈[0,s−1],若admodN≠1且a2rdmodN≠−1,则N是合数。否则,N有3/4的概率为素数。

Fermat素性测试一样,Miller-Rabin素性测试依然只能判定一个数可能是素数,但是这个方法却以它的快速、高效而广为使用。

决定型素数测试

一个确定性的判断一个大整数是否为素数的方法—AKS素数测试

AKS素数测试(又被称为Agrawal–Kayal–Saxena素数测试和Cyclotomic AKS test)是一个决定型素数测试算法,由三个来自Indian Institute of Technology Kanpur的计算机科学家,Manindra Agrawal、Neeraj Kayal和Nitin Saxena,在2002年8月6日发表于一篇题为PRIMES is in P(素数属于P)的论文。作者们因此获得了许多奖项,包含了2006年的哥德尔奖和2006年的Fulkerson Prize。这个算法可以在多项式时间之内,决定一个给定整数是素数或者合数。

2 生成大素数

最直观的方法就是随机搜索,例如要生成一个100位的大素数,我们先随机生成一个数字序列,然后用Miller-Rabin素性测试对其进行测试即可,如果不是素数的话再随机生成一个,如此循环下去。
当然我们可以采用随机搜索法(每次生成一个完全不一样的随机数),也可以采用随机递增搜索法(生成一个随机数之后,每次对其加2)
生成一个n位十进制大素数的步骤如下:

  1. 产生一个n位的随机数p,且最高位不能为0
  2. 若最低位为偶数,则将它加1,保证该数为奇数以节省时间
  3. 测试该数能否被10000以下的素数(共1228个)整除,这样可以快速排除许多合数,节省时间
  4. 2p-1这间随机生成一个数a,以a为底对p进行Miller-Rabin素性测试,若不通过说明p为合数。若通过则再选取一个a对p进行测试。选取a时应该选取尽可能小的素数,以提高运算速度。大概进行5次Miller-Rabin素性测试后,精确性就比较高了
  5. p每次测试都通过,则认为p是素数。否则p←p+2,再次对p进行测试

大素数生成过程有两个关键点,一个是素性测试,另一个是随机数的生成。前者要保证正确性和高效性,后者则一定要保证安全性,即生成一个真随机数

大部分程序和语言中的随机数(比如C和MATLAB中的),确实都只是伪随机。是由可确定的函数(比如线性同余),通过一个种子(比如时钟),产生的伪随机数。不过UNIX内核中的随机数发生器(/dev/random),它在理论上能产生真随机。即这个随机数的生成,独立于生成函数,或者说这个产生器是非确定的。所以,计算机理论上可以产生统计意义上的真随机数。

参考: 开源Javascript加密函数库

后续

棱镜计划

据NSA前通讯员斯诺登所提供的机密文件显示,NSA跟RSA达成了一份价值1000万美元的合同,前者通过在后者的加密软件中植入一个缺陷公式,为自己留了一道“后门”。据悉,RSA存有缺陷公式的软件叫做Bsafe,而该缺陷公式的名字为Dual Elliptic Curve,它由NSA开发而出。文件内容指出,RSA自2004年起就开始在自己的软件中使用了这一缺陷公式。
RSA Security是由RSA算法的发明者Ron Rivest, Adi Shamir和Len Adleman在1982年创立,随后在2006年以21亿美元的价格被EMC公司收购。其中该算法最为有名的一个缺陷就是DUAL_EC_DRBG,密码学家早在几年前就发现了这个问题。这个加密算法可以看作是随机数生成器,但是有些数字是固定的,密码学家能够将其作为万能钥匙通过一些内置的算法进行破解。

RSA算法本身没什么问题,因为只要你的密钥是真正随机产生的,猜对这个密钥就如同大海捞针一般难,现有计算机肯定无法在密码更换周期内攻破你的加密档案。但是,如果这个随机算法是假的呢?如果它仅仅是在一个很小的集合中产生的密钥呢?你的加密档案瞬间就被查看了,这就是NSA干的事情。

猜你喜欢

转载自blog.csdn.net/makenothing/article/details/90318351