zoukankan      html  css  js  c++  java
  • RSA简介(三)——寻找质数

      版权申明:本文为博主窗户(Colin Cai)原创,欢迎转帖。如要转贴,必须注明原文网址
    
      http://www.cnblogs.com/Colin-Cai/p/7296163.html 
    
      作者:窗户
    
      QQ:6679072
    
      E-mail:6679072@qq.com
    

      要生成RSA的密钥,第一步就是要寻找质数,本节专讲如何寻找质数。

      

      我们的质数(又称素数)、合数一般是对正整数来讲,质数就是只有1和本身两个的正整数,合数至少有3个约数,而1既不是合数也不是质数。

      质数有无穷多个,这个早在古希腊时期就被证明了,使用反证法很容易证明:假设质数只有有限多,分别为a1.....an,则a1*a1....*an+1大于所有的质数,却不以任何质数为约数,推出矛盾,从而假设错误。

      

      在质数的分布上,有个定理:

      lim  ∏ (n)/(n/ln(n)) = 1

      n→

       其中∏ (n)是小与等于n的质数的个数。

      找质数的第一个门槛还是靠随机,上述公式,可以推导出质数的密度ρ (n)(因为∏ (n)并非连续函数,此处密度只是概率上的密度)为

      lim ρ (n)/(n/ln(n))‘ = 1

      n→

     (n/ln(n))' = (ln(n)-1)/ln2(n),

      从而

      

      lim ρ (n)/(1/ln(n)) = 1

       n→

       那么,在n附近寻找质数,大约平均每ln(n)次可以找到一个质数。

      涉及到密钥的生成,随机算法要小心了,用时间种子与伪随机算法一起当然是不安全的,最好以硬件随机为基础的随机数,这样无规律,难以从密钥生成机制直接下手破解。

      

      接下来就需要质数判定算法。

      最土的算法:判断p是不是质数,就从2开始,挨个整数判断到p-1,看看是否其中有p的约数,如果没有,就是质数。

      这个算法效率太低O(p),但输入的信息量是p的位数级别,所以此算法应为指数级算法。

      明显提高的算法:如果p是合数,那么必然有一个不为1的约数小于或等于sqrt(p),于是刚才从2挨个整数判断到p-1修整一下,只需要判断到sqrt(p)即可。

      这个算法效率比前面那个算法好太多了,可是依然是指数级算法,只是指数从线性下降到平方根级别。

      可是我们RSA这里的指数动辄几百个bits,甚至两千多个bits,此种算法一样不靠谱。虽然上述算法还可以继续优化,比如测试了一个整数不是p的约数,就尽量不要测试这个整数的整数倍,只是,算法依然很慢。实际上,的确存在多项式级别的确定质数判定算法,第一个这样的算法是AKS算法,2002年由印度人解决。但目前靠谱的算法都是如此的慢,我们需要基于概率的判定方法。

      前两节谈到了模乘群,对于质数p,所有的小于p的正整数在模乘下构成一个群,该群的阶为p-1,则p-1是所有小于p的正整数以p为模的模乘周期的整数倍,这就是著名的费马小定理:

      如果a和p互质,且p为质数,则ap-1%p=1

      费马小定理虽然没有给出一个质数的鉴定方法,但告诉了我们,如果右边等号不成立,则p一定是合数,而基于概率的判定方法一般都会以费马小定理作为基础零件。RSA中一般用Miller-Rabin算法。

      Miller-Rabin算法同时利用了另外一个定义:

      p是质数,x是正整数,x2%p=1,那么x%p=1或者x%p=p-1

      完整描述Miller-Rabin算法如下:(https://en.wikipedia.org/wiki/Miller–Rabin_primality_test) 

    write n − 1 as 2**r·d with d odd by factoring powers of 2 from n − 1
    WitnessLoop: repeat k times:
       pick a random integer a in the range [2, n − 2]
       x ← ad mod n
       if x = 1 or x = n − 1 then
          continue WitnessLoop
       repeat r − 1 times:
          x ← x·x mod n
          if x = 1 then
             return composite
          if x = n − 1 then
             continue WitnessLoop
       return composite
    return probably prime

      里面用到了第二节提到的模幂算法,用bc实现了一遍Miller-Rabin算法,因为bc里面无自带随机函数,就直接利用标准输入来输入随机数了,整个实现如下:

    #!/usr/bin/bc -q
    define mod_mul(a1,a2,n)
    {
            return a1*a2%n;
    }
    define mod_exp(a,b,n)/* a^b%n */
    {
            while(b%2==0) {
                    a = mod_mul(a,a,n);
                    b /= 2;
            }
            ret = a;
            b /= 2;
            while(b!=0) {
                    a = mod_mul(a,a,n);
                    if(b%2 == 1)
                            ret = mod_mul(a,ret,n);
                    b /= 2;
            }
            return ret;
    }
    define Miller_Rabin(p, t)
    {
            if(p==1) {
                    return 0;
            }
            if(p<3) {
                    return 1;
            }
            if(p%2==0) {
                    return 0;
            }
    
    
    }
    define get_rand_num()
    {
            return read();
    }
    
    define Miller_Rabin_test(n, k)
    {
            d = n-1;
            r = 0;
            while(d%2!=1) {
                    d /= 2;
                    r++;
            }
    
            for(i=0;i<k;i++) {
                    a = get_rand_num();
                    x = mod_exp(a,d,n);
                    if(x==1||x==n-1) {
                            continue;
                    }
                    for(j=1;j<r;j++) {
                            x = mod_mul(x,x,n);
                            if(x==1) {
                                    return 0;
                            } else if(x==n-1) {
                                    j = r;
                                    continue;
                            }
                    }
                    if(j==r) {
                            return 0;
                    }
            }
            return 1;
    }
    

      

     

  • 相关阅读:
    PHP学习—了解篇2
    PHP学习—了解篇
    德国山寨史
    Network client/server
    Linux (二) vi
    I2C 总线协议
    Verilog (二) multiplexer and decoder
    有限状态机HDL模板
    "德意志之歌"的历史
    【转】java与.net比较学习系列(3) 基本数据类型和类型转换
  • 原文地址:https://www.cnblogs.com/Colin-Cai/p/7296163.html
Copyright © 2011-2022 走看看