python实现公开密钥密码(内含:模重复平方算法(6)、Miller-Rabin素数测试(8)、广义欧几里得算法(10))

在这里插入图片描述
先来一个小练习:
在这里插入图片描述
一行代码解决它:

print("密文为:{}".format(pow(int(input("请输入明文M:")),int(input("请输入e:")),int(input("请输入n:")))))

结果如下:
在这里插入图片描述
下面通过十个小实验慢慢熟悉RSA算法:

  • 实验(1)令 p=3,q=11,d=7,m=5, 编程计算密文 C 。
def isPrime(a,b):
    while a != 0:           #辗转相除法求最大公约数
        a,b = b % a,a
    if b == 1:
        flag = 1
    else :
        flag = 0
    return flag

p = 3 
q = 11
d = 7 
m = 5
n = p * q
un = (p -1) * (q - 1)
for e in range(2,un):
    if isPrime(e,un):
        print("e取{:>2d}时,密文C为:{}".format(e,pow(m,e,n)))

结果如下:
在这里插入图片描述

  • 实验(2)设 RSA 密码的 e=3,n=33,C=9, 编程计算明文 M 。
def isPrime(a,b):
    while a != 0:           #辗转相除法求最大公约数
        a,b = b % a,a
    if b == 1:
        flag = 1
    else :
        flag = 0
    return flag
def U(n):                   #求欧拉函数值
    un = 0
    for i in range(1,n+1):
        if isPrime(i,n):
            un += 1
    return un

e = 3
n = 33 
c = 9
for d in range(20):
    if isPrime(d*e,U(n)):
        print("d取{:>2d}时,明文M为:{}".format(d,pow(c,d,n)))

运行结果:
在这里插入图片描述

  • 实验(3)令 p=17,q=11, e=7,试计算 RSA 密码其余参数 。进一步对于m=88, 计算密文 C 。
def isPrime(a,b):
    while a != 0:           #辗转相除法求最大公约数
        a,b = b % a,a
    if b == 1:
        flag = 1
    else :
        flag = 0
    return flag
def U(n):                   #求欧拉函数值
    un = 0
    for i in range(1,n+1):
        if isPrime(i,n):
            un += 1
    return un

p = 17
q = 11
e = 7
n = p * q
print("n为:{}".format(n))
un = (p -1) * (q - 1)
m = 88
for e in range(1,un):
    if isPrime(e,un):
        print("e取{:<3d}时,密文C为:{}".format(e,pow(m,e,n)))

结果如下:
在这里插入图片描述

  • 实验(4)p=47,q=71,e=79,编程计算d.
def isPrime1(n):            #判断素数
    flag = 1
    if n>1:
        for i in range(2,n):
            if n % i == 0:
                flag = 0
                break;
    else:
        flag = 0
    return flag

def isPrime2(a,b):
    while a != 0:           #辗转相除法求最大公约数
        a,b = b % a,a
    if b == 1:              #如果最大公约数为1,则互素,反之
        flag = 1
    else :
        flag = 0
    return flag
def U(n):                   #求欧拉函数值
    un = 0
    for i in range(1,n+1):
        if isPrime2(i,n):
            un += 1
    return un

p = 47
q = 71
e = 79
n = p * q
un = (p - 1) * (q - 1)
for d in range(10000):
    if (e * d) % un ==1:
        print("d = {:<3d}".format(d))
        break

运行结果:
在这里插入图片描述

  • 实验(5)随机生成两个互素的数,随机生成e的值,求d.
import random

def isPrime1(n):            #判断素数
    flag = 1
    if n>1:
        for i in range(2,n):
            if n % i == 0:
                flag = 0
                break;
    else:
        flag = 0
    return flag

def isPrime2(a,b):
    while a != 0:           #辗转相除法求最大公约数
        a,b = b % a,a
    if b == 1:              #如果最大公约数为1,则互素,反之
        flag = 1
    else :
        flag = 0
    return flag
def U(n):                   #求欧拉函数值
    un = 0
    for i in range(1,n+1):
        if isPrime2(i,n):
            un += 1
    return un

while True:
    p = random.randint(100,200)
    if isPrime1(p):
        print("当p = {:<3d}".format(p),end = ' ')
        break
while True:
    q = random.randint(100,200)
    if isPrime1(q) and p != q:
        print("q = {:<3d}".format(q),end = ' ')
        break 
n = p * q 
un = (p - 1) * (q - 1)
while True:
    e = random.randint(2,un)
    if isPrime2(e,un):
        print("e = {:<3d}".format(e))
        break
d =2
while True:
    if (e * d) % un !=1:
        d += 1
    else:
        print("此时d = {:<3d}".format(d))
        break

结果如下:
在这里插入图片描述

  • 实验(6)编程计算12996**227(mod 37909)
  • 模重复平方算法:
    原理:
    在这里插入图片描述
a = 1
b,n,m = input("请输入底数b,指数n,和模数m(用空格隔开)\n").split(' ')
n = bin (int(n))[2::]
for ni in n[::-1]:
    if int(ni) == 1:
        a = (a * pow(int(b),int(ni))) % int(m)
    b = pow(int(b),2) % int(m)
print("运算结果是:{}".format(a))

结果如下:
在这里插入图片描述

  • 实验(7)求100至200之间的素数。
def isPrime1(n):            #判断素数
    flag = 1
    if n>1:
        for i in range(2,n):
            if n % i == 0:
                flag = 0
                break;
    else:
        flag = 0
    return flag

print("100--200之间的素数有:",end = '')
for i in range(100,201):
    if isPrime1(i):
        print(i,end = ' ')
print('')

结果如下:
在这里插入图片描述

  • 实验(8)利用Miller Babin素数筛法求出一个不小于1000的素数。(注:此题解法算法用错,以后更正)

费马小定理是初等数论四大定理(威尔逊定理,欧拉定理(数论中的欧拉定理,即欧拉函数),中国剩余定理和费马小定理)之一,在初等数论中有着非常广泛和重要的应用。实际上,它是欧拉定理的一个特殊情况。

内容为假如p是质数,且GCD(a,p)=1,那么 a^(p-1) ≡1(mod p)(假如p是质数,且a,p互质,那么 a的(p-1)次方除以p的余数恒等于1)

证明:大数取余的公式 (ab)%mod =(a%mod * b%mod) %mod, 设P为素数 那么 (ak) %p =(a%pk) % P [1<=k<=p-1] ;a%p=c是个定值,由于p是个素数,所以(a%pk) % P的值互不相同,如果存在 (ci) %p == (cj) %p (i<j) 那么 ci +pt == cj , 说明 c = a%p 可以被 p 整除 ,显然不成立; (ak) %p的值在[1,p-1]中取,既然互不相同,所以 (ak) %p的值覆盖了 [1,p-1] 中的所有数,则 (a1) %p * (a2) %p * (a3) %p * … * (a(p-1)) %p = 123*…(p-1) =(a^(p-1))%p 123*…(p-1) ==> (a^(p-1))%p=1 证毕。

使用用费马小定理的逆命题可以来判定素数,但是其逆命题不一定成立,所以有一定的概率,需要多次测试来减小出错的概率。每次测试随机取一个正整数a,要保证 GCD(a,p)=1; 用快速幂来计算a^(p-1) 看是否为 1,如果为1则通过这次测试。 但是这样也可能出错,因为存在称做Carmichael数的合数,使得对这些合数进行多次测试都能通过,但是它们不是素数。前3个Carmichael数是561,1105,1729。Carmichael数是非常少的。在1~100000000范围内的整数中,只有255个Carmichael数。利用二次探测定理可以对上面的素数判定算法作进一步改进,以避免将Carmichael数当作素数。
== 二次探测定理 如果p是一个素数,且0<x<p,则方程x^2≡1(mod p)的解必为 x=1或p-1。==

import random

n = 1000
k = int(input("请输入一个安全参数k:"))
while True:
    flag = 1
    for i in range(k):
        while True:
            a = random.randint(1,100)
            if isPrime2(a,n):
                break;
        if pow(a,n-1)%n != 1:
            n += 1
            flag = 0
            break;
    if flag ==1 :
        print("找到的数为:{}".format(n))
        break;

结果如下:
在这里插入图片描述

  • 实验(9)求如下整数对的最大公因数
    (55,85) (202,282)
a = int(input("请输入第一个数:"))
b = int(input("请输入第二个数:"))
print("{}和{}的最大公约数为:".format(a,b),end = '')
while a != 0:           #辗转相除法求最大公约数
    a,b = b % a,a
print(b)

在这里插入图片描述在这里插入图片描述

  • 实验(10)运用广义欧几里得除法求整数s,t,使得sa+tb=(a,b)
    (1)1613,3589 (2)2947,3772
def ext_euclid ( a , b ):
     if (b == 0):
        return 1, 0, a
     else:
         x1 , y1 , q = ext_euclid( b , a % b ) # q = GCD(a, b) = GCD(b, a%b)
         x , y = y1, ( x1 - (a // b) * y1 )
     return x, y, q

a = int(input("请输入第一个整数a:"))
b = int(input("请输入第二个整数b:"))
s,t,q = ext_euclid(a,b)
print("计算结果为:\n{}*{} + {}*{} = {}".format(s,a,t,b,q))

结果如下:
在这里插入图片描述
在这里插入图片描述

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值