前言

RSA公钥加密算法是1977年由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的。RSA就是他们三人姓氏开头字母拼在一起组成的。
RSA是目前最有影响力的公钥加密算法,它能够抵抗到目前为止已知的绝大多数密码攻击,RSA算法基于一个十分简单的数论事实:将两个大质数相乘十分容易,但是想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥。

RSA算法的原理,目前网络上有许多优秀的文章,特别推荐阅读阮一峰老师的文章:

本文主要描述如何使用RSA来对文件进行不对称加密。

安装

crypto这个模块的安装比较特殊,可能会有点小坑,安装时需要注意。

crypto,pycrypto,pycryptodome的功能是一样的。crypto与pycrypto已经没有维护了,后面可以使用pycryptodome。

但是,三个名字,再分Linux和Windows操作系统,再分Python2和Python3,叠加起来就有12种情况了,非常复杂。

在 Windows 中,不管是 Python2 和 Python3 ,都不能用 crypto 和 pycrypto ,可以用 pycryptodome 。

在 Linux 中,不管是 Python2 和 Python3 ,都不能用 crypto ,可以用 pycrypto 和 pycryptodome 。

所以,总结一句话,直接都用 pycryptodome 就行了,(保证pip正常能用的情况下)安装命令如下:

pip install pycryptodome

安装之前,最好先把 crypto 和 pycrypto 卸载了(uninstall),避免不必要的麻烦。

生成RSA公钥和私钥

from Crypto import Random
from Crypto.PublicKey import RSA


def generate_Key():

    random_generator = Random.new().read
    rsa = RSA.generate(2048, random_generator)
    private_key = rsa.exportKey()
    # 写入私钥文件
    with open('private_rsa_key.bin', 'wb') as f:
        f.write(private_key)

    public_key = rsa.publickey().exportKey()
    # 写入公钥文件
    with open('rsa_public.pem', 'wb') as f:
        f.write(public_key)

上面的代码中,生成了一对公钥和私钥。

导入了 RSA ,通过 RSA 的 generate() 方法实例化一个对象 rsa 。再通过 rsa 的 exportKey() 方法和 publickey() 方法生成公钥和私钥。

执行这个函数,可以看到,生成了一对公钥和私钥

当然每次运行的结果都不一定,公钥是公开的,任何人都可以看到,但是私钥一定要保存好,否则一旦泄露,意味着你的信息也不安全了。

进行加密和解密

from Crypto import Random
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5 as PKCS1_cipher
import base64


# 加密
def encryption(keys):
    with open('rsa_public.pem') as f:
        key = f.read()
        pub_key = RSA.importKey(str(key))
        cipher = PKCS1_cipher.new(pub_key)
        rsa_text = base64.b64encode(cipher.encrypt(bytes(keys.encode("utf8"))))
        return rsa_text.decode('utf-8')

# 解密
def decrypt(keys):
    with open('private_rsa_key.bin') as f:
        key = f.read()
        pri_key = RSA.importKey(key)
        cipher = PKCS1_cipher.new(pri_key)
        back_text = cipher.decrypt(base64.b64decode(keys),0)
        return back_text.decode('utf-8')

上面的函数,我们将保存的公钥和私钥读出来,然后进行加密和解密的过程,不过千万要注意的是,私钥不要泄露。

签名和验签

RSA还可以用来签名和验签,正好与加密相反的是,他是使用私钥来签名,公钥来验签

废话不多说,上代码

from Crypto.PublicKey import RSA
from Crypto.Hash import SHA
import base64
from Crypto.Signature import PKCS1_v1_5 as PKCS1_signature

message = "需要加密的信息"
# 使用私钥生成签名
with open('private_rsa_key.bin') as f:
    key = f.read()
    pri_key = RSA.importKey(key)
    signer = PKCS1_signature.new(pri_key)
    digest = SHA.new()
    digest.update(message.encode("utf8"))
    sign = signer.sign(digest)
    signature = base64.b64encode(sign)
    print(signature.decode('utf-8'))

# 使用公钥验证签名
with open('rsa_public.pem') as f:
    key = f.read()
    pub_key = RSA.importKey(key)
    verifier = PKCS1_signature.new(pub_key)
    digest = SHA.new()
    digest.update(message.encode("utf8"))
    print(verifier.verify(digest, base64.b64decode(signature)))

继续使用之前写入文件中的私钥和公钥,使用私钥来生成信息的签名,然后使用公钥来验证签名。

生成签名时,使用 RSA 的 importKey() 方法对(从文件中读取的)私钥字符串进行处理,处理成可用的私钥用于生成签名。

从 Crypto.Signature 中导入 PKCS1_v1_5 ,重命名为 PKCS1_signature 。然后实例化一个签名对象 signer ,传入的参数是私钥,通过的 signer 的 sign() 方法对信息生成签名。

信息需要先转换成 sha 字符串,使用 Crypto.Hash 中的 SHA 来转换。生成的签名是字节串,为了显示得更友好,可以将结果转换成 base64 字符串。

验证签名时,使用 RSA 的 importKey() 方法对(从文件中读取的)公钥字符串进行处理,处理成可用的公钥用于验证签名。

实例化一个验证对象 verifier ,传入的参数是公钥,通过的 verifier 的 verify() 方法对签名进行验证。验证结果是一个布尔值,验证成功返回 True , 不成功返回 False 。