python实现RSA算法

#!/usr/bin/env python3
#coding:utf-8
#by spwpun
import random
import binascii
import argparse         #导入读取命令行参数的模块
import sys
sys.setrecursionlimit(100000)   #设置迭代次数限制

def main():
        Build_key()     #生成公钥、密钥
        parser = argparse.ArgumentParser(description="This is a description, it includes the whole file's loactions of RSA algorithm.")
        parser.add_argument('-p', required = True, type = argparse.FileType('r'), help = 'plainfile')
        parser.add_argument('-n', required = True, type = argparse.FileType('r'), help = 'nfile')
        parser.add_argument('-e', required = False, type = argparse.FileType('r'), help = 'efile')    #e,d文件不是都要的,只需一个
        parser.add_argument('-d', required = False, type = argparse.FileType('r'), help = 'dfile')
        parser.add_argument('-c', required = True, type = argparse.FileType('w+'), help = 'cipherfile')
        args = parser.parse_args()  #args里面的成员是一个文件对象,所以后面写入文件的形式和一般的一样
        n = int(args.n.read(),16)
        m = args.p.read()
        if m=='':
            print('No PlainText!')
        else:
            print("Encrypting......")
            e = int(args.e.read(),16)
            cipher = encrypt(m,e,n)
            with args.c as f:
                f.write(cipher)
            print("Encrypted!\r\nThe Cipher is:",cipher)

        c = cipher     #读取密文
        if c=='':
            print ("No Cipher!")
        else:
            print("Decrypting......")
            d = int(args.d.read(),16)
            plain = decrypt(c,d,n)
            print("Decrypted!\r\nThe PlainText is:",plain)

#平方—乘法,最后返回结果
def MRF(b,n,m):
    
        a=1
        x=b;y=n;z=m
        binstr = bin(n)[2:][::-1]	#通过切片去掉开头的0b,截取后面,然后反转
        for item in binstr:
                if item == '1':
                        a = (a*b)%m
                        b = (b**2)%m
                elif item == '0':
                        b = (b**2)%m
        return a

#素性检验
def MillerRabin(n):
    "利用Miller-Rabin算法检验生成的奇数是否为素数"
    m=n-1
    k=0
    while(m%2==0):
        m=m//2
        k=k+1
    a=random.randint(2,n)
    #b=a**m%n
    b = MRF(a,m,n)
    if(b==1):
        return 1
    for i in range(k):
        if(b==n-1):
            return 1
        else:
            b=b*b%n
    return 0

#生成大素数,20次MillerRabin算法缩小出错的概率
def BigPrime():
        Min = 10**11;Max = 10**15;p = 0
        while(1):
                p = random.randrange(Min,Max,1)
                for i in range(20):
                        if MillerRabin(p)==0:
                                break
                        elif i==19:
                                return p
                                
#加密,传入公钥,通过读取明文文件进行加密
def encrypt(m,e,n):
        cipher = ""
        nlength = len(str(hex(n))[2:])  #计算n的16进制长度,以便分组
        message = m             #读取明文
        for i in range(0,len(message),8):
            if i==len(message)//8*8:
                m = int(a2hex(message[i:]),16)  #最后一个分组
            m = int(a2hex(message[i:i+8]),16)
            c = MRF(m,e,n)
            cipher1 = str(hex(c))[2:]
            if len(cipher1)!=nlength:
                cipher1 = '0'*(nlength-len(cipher1))+cipher1    #每一个密文分组,长度不够,高位补0
            cipher += cipher1
        return cipher
#解密,传入私钥,通过文件读写进行解密
def decrypt(c,d,n):
        #加密之后每一个分组的长度和n的长度相同
        cipher = c
        message = ""
        nlength = len(str(hex(n))[2:])
        for i in range(0,len(cipher),nlength):
            c = int(cipher[i:i+nlength],16)     #得到一组密文的c
            m = MRF(c,d,n)
            info = hex2a(str(hex(m))[2:])
            message += info
        f_write("RSA_decrypted.txt",message)
        return message

#求最大公因子
def gcd(a,b):  
        if a%b == 0:
                return b
        else :
                return gcd(b,a%b)

#求逆元
def Ex_Euclid(x,n):
    r0=n
    r1=x%n
    if r1==1:
        y=1
    else:
        s0=1
        s1=0
        t0=0
        t1=1
        while (r0%r1!=0):
            q=r0//r1  
            r=r0%r1  
            r0=r1  
            r1=r  
            s=s0-q*s1 
            s0=s1 
            s1=s  
            t=t0-q*t1  
            t0=t1  
            t1=t  
            if r==1:
                y = (t+n)%n
    return y

#写入文件
def f_write(filename,message):
        f = open(filename,'w')
        f.write(message)
        f.close()
        return 0

#ascii_to_hex
def a2hex(raw_str):
        hex_str = ''
        for ch in raw_str:
                hex_str += hex(ord(ch))[2:]
        return hex_str

#hex_to_ascii
def hex2a(raw_str):
        asc_str = ''
        for i in range(0,len(raw_str),2):
                asc_str += chr(int(raw_str[i:i+2],16))
        return asc_str
def Build_key():
        #产生p,q,n,e,d
        p = BigPrime()
        q = BigPrime()
        n = p*q
        _n = (p-1)*(q-1)    #n的欧拉函数
        e = 0
        while(1):
                e = random.randint(1,_n+1)
                if gcd(e,_n)==1:
                        break
        d = Ex_Euclid(e,_n)
        #写入文件
        f_write('p.txt',str(hex(p))[2:])
        f_write('q.txt',str(hex(q))[2:])
        f_write('n.txt',str(hex(n))[2:])
        f_write('e.txt',str(hex(e))[2:])
        f_write('d.txt',str(hex(d))[2:])

if __name__ == "__main__":
        main()
每一次运行都会重新生成公钥、密钥参数,这些参数分别以16进制的格式写入文件中,代码中还加入了对命令行参数的使用,主要用到了python的argparse模块。一个简单的示例如下:

通过-h可以查看帮助信息:


  • 1
    点赞
  • 50
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值