RSA (python)
what?
非对称的加密算法,能够保证加密数据的机密性
why?
RSA算法的难解性取决于大素数的分解难度,在有限算力的情况下是不能破解的。
how?
一、密钥的产生
1 选取两个保密的大素数 p 和 q
2 计算 n=pq , fai(n) = (p-1)(q-1)
3 选一整数 e, 满足 1<e<fai(n), gcd(fai(n),e)=1
4 计算d, 满足 d.e=1 mod fai(n)
二、加密
1 将明文比特串分组,使得每个分组对应的十进制数小于n(分组长度< \(log_2n\))
\[c=m^c mod n
\]
三、解密
解密运算 \(m=c^d mod n\)
填充模式
1、RSA_PKCS1_PADDING 填充模式(常用)
要求
INPUT:必须必模长(e)短至少11个字节,即 RSA_size(rsa) – 11。如果输入的明文过长,必须切割,然后进行填充。
OUTPUT: 与模(e)一样长
据此要求:
对于512bit的密钥, 填充的长度为 512/8-11=53字节
对于1024bit的密钥, 填充的长度为 1024/8-11=117字节
对于2048bit的密钥, 填充的长度为 2048/8-11=245字节
对于4096bit的密钥, 填充的长度为 4096/8-11=501字节
2、RSA_PKCS1_OAEP_PADDING
要求
INPUT:RSA_size(rsa) – 41
OUTPUT: 与模(e)一样长
3、for RSA_NO_PADDING 不填充
INPUT:可以和RSA钥模长一样长,如果输入的明文过长,必须切割, 然后填充
OUTPUT:和模(e)一样长
代码
#/usr/bin/env python
# -*- coding: utf-8 -*-
#----rsa 算法 ------#
"""
1 选取两个保密的大素数 p 和 q
2 计算 n=p*q , fai(n) = (p-1)*(q-1)
3 选一整数 e, 满足 1<e<fai(n), gcd(fai(n),e)=1
4 计算d, 满足 d.e=1 mod fai(n)
=> (e,n)为公钥 ; (d,n)为私钥
e : 模数默认情况下为65537(HEX:10001)
"""
import rsa
import sys
import base64
# 打印 python 版本 与 windows 系统编码
print("---- 1 ----")
print(sys.version)
print(sys.getdefaultencoding())
print(sys.getfilesystemencoding())
# 先生成一对密钥,然后保存.pem格式文件,当然也可以直接使用
print("---- 2 ----")
(pubkey, privkey) = rsa.newkeys(1024) # 随机生成1024bit的公私钥
pub = pubkey.save_pkcs1()
print(type(pub))
pubfile = open('public.pem','w+')
pubfile.write(pub.decode('utf-8'))
pubfile.close()
print("---- 3 ----")
pri = privkey.save_pkcs1()
print(type(pri))
prifile = open('private.pem','w+')
prifile.write(pri.decode('utf-8'))
prifile.close()
# load公钥和密钥
print("---- 4 ----")
message = 'helloxpp'
print('message:',type(message))
with open('public.pem') as publickfile:
p = publickfile.read()
print(type(p))
pubkey = rsa.PublicKey.load_pkcs1(p.encode('utf-8')) #pkcs1_padding
with open('private.pem') as privatefile:
p = privatefile.read()
print(type(p))
privkey = rsa.PrivateKey.load_pkcs1(p.encode('utf-8')) # pkcs1_padding
# 用公钥加密、再用私钥解密
crypto = rsa.encrypt(message.encode('utf-8'),pubkey)
print(crypto)
print("---- 5 ----")
print('crypto:',type(crypto))
print('cry_base64:',base64.encodebytes(crypto))
print('cry_base64_utf8:',base64.encodebytes(crypto).decode('utf-8'))
# 保存到本地文件
cry_file = open('cry_file.txt','w+')
cry_file.write(base64.encodebytes(crypto).decode('utf-8'))
cry_file.close()
print("---- 6 ----")
# 从本地文件读取
cry_file = open('cry_file.txt','r')
cry_text = ''
for i in cry_file.readlines():
cry_text += i
print('cry_text_type:',type(cry_text))
print('cry_text:',cry_text)
print('cry_base64:',cry_text.encode('utf-8'))
crypto_tra = base64.decodebytes(cry_text.encode('utf-8'))
print("---- 7 ----")
assert crypto == crypto_tra
print(crypto)
print("---- 8 ----")
plaintext = rsa.decrypt(crypto,privkey)
assert message == plaintext.decode('utf-8')
print(plaintext.decode('utf-8'))