RSA的数论基础及python实现

RSA的数论基础及python实现

一、裴蜀定理

1.内容:若a,b是整数,且gcd(a,b)=d,那么对于任意的整数x,y,ax+by都一定是d的倍数,特别地,一定存在整数x,y,使ax+by=d成立。

 

2.重要推论:a,b互质的充分必要条件是存在整数x,y使ax+by=1

二、欧拉定理

若正整数a,m互质,则 a ^(φ(p)) = 1 (mod p ) 

其中欧拉函数 φ(p)是小于 p 的正整数中和 p 互质的数的个数

三、费马小定理

如果p是一个质数,而整数a不是p的倍数,则有a^(p-1)≡1(mod p)。然而满足费马小定理检验的数未必是素数,这种合数叫做卡迈克尔数(Carmichael Number),最小的卡迈克尔数是561。

四、Miller-Rabin素性检测

如果p是一个奇素数,则(p-1)必定是一个偶数,可以被表示为 d*2^r 的形式,其中s、d均为正整数,d为奇数。

由费马小定理得知a^(p-1)≡1(mod p),则a^(d*2^s)≡1(mod p)。

我们可以对上式取平方根,得到的必然为平凡平方根1或-1。假如我们得到的平方根为1,则继续取平方根,如此循环,最后必然会得到下列两种情况之一:

1、得到某个r>=0&&r<=s-1,使得a^(d*2^r)≡-1(mod p)。

2、发现对于任意r>=0&&r<=s-1,都有a^(d*2^r)≡-1(mod p),即a^d ≡1(mod p)。

Miller-Rabin素性检测就是上述原理的逆否,如果能找到一个a,使得对任意r>=0&&r<=s-1都不满足a^(d*2^r)≡-1(mod p),那么p必然不是一个素数。

算法实现:

`def rabin_miller(num):

    s = num - 1

    t = 0

    while s % 2 == 0:

        s = s // 2

        t += 1

    for trials in range(5):

        a = random.randrange(2, num - 1)

        v = pow(a, s, num)

        if v != 1:

            i = 0

            while v != (num - 1):

                if i == t - 1:

                    return False

                else:

                    i = i + 1

                    v = (v ** 2) % num

    return True

    `

五、欧几里得算法

     两个整数的最大公约数等于其中较小的那个数和两数相除余数的最大公约数。即gcd(a,b) = gcd(b,a mod b) (不妨设a>b 且r=a mod b ,r不为0)

算法实现:

  `def gcd(a,b):

       if b == 0:

              return a

       else:

              return gcd(b,a%b)`

六、扩展欧几里得算法

扩展欧几里得算法(英语:Extended Euclidean algorithm)是欧几里得算法(又叫辗转相除法)的扩展。已知整数a、b,扩展欧几里得算法可以在求得a、b的最大公约数的同时,能找到整数x、y(其中一个很可能是负数),使它们满足贝祖等式ax+by=gcd(a,b)。

算法实现:

`def myojilide(a,b):

    if b == 0:

        return (1,0,a)

    x, y = myojilide(b,a%b)

    temp = x

    x = y

    y = temp - a//b * y

    return x,y`

七、快速幂算法

快速幂算法能帮我们算出指数非常大的幂,传统的求幂算法之所以时间复杂度非常高(为O(指数n)),就是因为当指数n非常大的时候,需要执行的循环操作次数也非常大。所以我们快速幂算法的核心思想就是每一步都把指数分成两半,而相应的底数做平方运算。这样不仅能把非常大的指数给不断变小,所需要执行的循环次数也变小,而最后表示的结果却一直不会变。

算法实现:

`long long fastPower(long long base, long long power) {

    long long result = 1;

    while (power > 0) {

        if (power & 1) {//此处等价于if(power%2==1)

            result = result * base % 1000;

        }

        power >>= 1;//此处等价于power=power/2

        base = (base * base) % 1000;

    }

    return result;

}

八、RSA

这个比较简单,直接上只用python实现RSA的代码(主要难在找大素数)

`import random

def myojilide(a,b):

    if b == 0:

        return (1,0,a)

    x, y = myojilide(b,a%b)

    temp = x

    x = y

    y = temp - a//b * y

    return x,y

def gcd(a,b):

       if b == 0:

              return a

       else:

              return gcd(b,a%b)

                  #检测大整数是否是素数,如果是素数,就返回True,否则返回False

def rabin_miller(num):

    s = num - 1

    t = 0

    while s % 2 == 0:

        s = s // 2

        t += 1

    for trials in range(5):

        a = random.randrange(2, num - 1)

        v = pow(a, s, num)

        if v != 1:

            i = 0

            while v != (num - 1):

                if i == t - 1:

                    return False

                else:

                    i = i + 1

                    v = (v ** 2) % num

    return True

    def is_prime(num):

    排除0,1和负数

    if num < 2:

        return False

        #创建小素数的列表,可以大幅加快速度

    #如果是小素数,那么直接返回true

    small_primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997]

    if num in small_primes:

        return True

        #如果大数是这些小素数的倍数,那么就是合数,返回false

    for prime in small_primes:

        if num % prime == 0:

            return False

            #如果这样没有分辨出来,就一定是大整数,那么就调用rabin算法

    return rabin_miller(num)

def ex(a):

       for i in range(1,a):

              if gcd(i,a)==1:

                     return i

#得到大整数,默认位数为1024

def get_prime(key_size=1024):

    while True:

        num = random.randrange(2**(key_size-1), 2**key_size)

        if is_prime(num):

            return num

p=get_prime()

q=get_prime()

n=p*q

r=(p-1)*(q-1)

e=ex(r)

m=int(input())

c=pow(m,e,n)

d,y=myojilide(e,r)

m=pow(c,e,d)

print(m,c)`

posted @ 2021-01-21 10:30  J0ker_ADN  阅读(465)  评论(0)    收藏  举报