03 crypto模块实现RSA 加密解密
一. 使用 Crypto 库
Crypto库的安装比较费心,因为有好几种库可以安装,功能几乎一样,最终都叫Crypto,不同系统下可安装的库的名称还不一致,但总结下来,下面的安装方法在任何平台都可用
pip install pycryptodome
使用Crypto, 可以直接生成私钥和公钥
from Crypto import Random
from Crypto.PublicKey import RSA
random_generator = Random.new().read
rsa = RSA.generate(2048, random_generator)
# 生成私钥
private_key = rsa.exportKey()
print(private_key.decode('utf-8'))
# 生成公钥
public_key = rsa.publickey().exportKey()
print(public_key.decode('utf-8'))
with open('rsa_private_key.pem', 'wb')as f:
f.write(private_key)
with open('rsa_public_key.pem', 'wb')as f:
f.write(public_key)
生成的秘钥,需要写入到文件中,这样便于保存,毕竟,公钥是需要交给其他人使用,你自己手里同时拿着私钥和公钥是没有意义的,和你进行数据交互的人需要公钥来验证数据是否安全。
二. 公钥加密,私钥解密
使用公钥加密的数据,可以用私钥进行解密
import base64
from Crypto.PublicKey import RSA
from Crypto.Hash import SHA
from Crypto.Signature import PKCS1_v1_5 as PKCS1_signature
from Crypto.Cipher import PKCS1_v1_5 as PKCS1_cipher
def get_key(key_file):
with open(key_file) as f:
data = f.read()
key = RSA.importKey(data)
return key
def encrypt_data(msg):
public_key = get_key('rsa_public_key.pem')
cipher = PKCS1_cipher.new(public_key)
encrypt_text = base64.b64encode(cipher.encrypt(bytes(msg.encode("utf8"))))
return encrypt_text.decode('utf-8')
def decrypt_data(encrypt_msg):
private_key = get_key('rsa_private_key.pem')
cipher = PKCS1_cipher.new(private_key)
back_text = cipher.decrypt(base64.b64decode(encrypt_msg), 0)
return back_text.decode('utf-8')
def test_encrypt_decrypt():
msg = "coolpython.net"
encrypt_text = encrypt_data(msg)
decrypt_text = decrypt_data(encrypt_text)
print(msg == decrypt_text)
test_encrypt_decrypt() # True
公钥加密的数据,只有私钥才可以解密
三. 私钥制作签名,公钥验证签名
使用私钥生成签名,并没有对数据进行加密,另一方在获取数据后,可以利用签名进行验证,如果数据传输的过程中被篡改了,那么签名验证就会失败。你可能已经想到了一种可能性,原始数据被篡改了,签名也同时被篡改了,这样验证就通过了。如果这种情况真的发生了,就说明篡改数据的人已经获取了私钥并利用私钥对篡改后的数据生成新的签名,否则,绝没有可能在没有私钥的情况下准确的篡改签名还能通过验证。如果篡改者能够获取私钥这种高度机密的信息,那么,防篡改已经没有意义了,因为人家已经彻底攻破了你的系统。
import base64
from Crypto.PublicKey import RSA
from Crypto.Hash import SHA
from Crypto.Signature import PKCS1_v1_5 as PKCS1_signature
from Crypto.Cipher import PKCS1_v1_5 as PKCS1_cipher
def get_key(key_file):
with open(key_file) as f:
data = f.read()
key = RSA.importKey(data)
return key
def rsa_private_sign(data):
private_key = get_key('rsa_private_key.pem')
signer = PKCS1_signature.new(private_key)
digest = SHA.new()
digest.update(data.encode("utf8"))
sign = signer.sign(digest)
signature = base64.b64encode(sign)
signature = signature.decode('utf-8')
return signature
def rsa_public_check_sign(text, sign):
publick_key = get_key('rsa_public_key.pem')
verifier = PKCS1_signature.new(publick_key)
digest = SHA.new()
digest.update(text.encode("utf8"))
return verifier.verify(digest, base64.b64decode(sign))
def test_sign():
msg = 'coolpython.net'
sign = rsa_private_sign(msg)
print(rsa_public_check_sign(msg, sign)) # True
if __name__ == '__main__':
test_sign()