Python3: RSA 非对称加密 - 秘钥对生成,加密/解密,签名/验签

本文链接: https://blog.csdn.net/xietansheng/article/details/115559295

Python3 学习笔记(目录)

1. pycryptodome/Crypto 模块

pycryptodome模块文档: https://pycryptodome.readthedocs.io/en/latest/

使用第三方模块pycryptodome中的Crypto.PublicKey.RSA实现 RSA 秘钥对生成、加密/解密、签名/验签。

安装pycryptodome模块:

pip3 install pycryptodome

1.1 生成 RSA 秘钥对

生成一对 RSA 密钥(公钥、私钥),并保持到文件:

from Crypto.PublicKey import RSA


# 生成一对长度为 2048 位的 RSA 秘钥对, 使用默认的随机数生成函数,
# 也可以手动指定一个随机数生成函数: randfunc=Crypto.Random.new().read
rsa_key = RSA.generate(2048)
print(rsa_key)                      # Private RSA key at 0x7FB241173748
print(type(rsa_key))                # <class 'Crypto.PublicKey.RSA.RsaKey'>


# 导出公钥, "PEM" 表示使用文本编码输出, 返回的是 bytes 类型, 格式如下:
# b'-----BEGIN PUBLIC KEY-----\n{Base64Text}\n-----END PUBLIC KEY-----'
# 输出格式可选: "PEM", "DER", "OpenSSH"
pub_key = rsa_key.publickey().export_key("PEM")

# 导出私钥, "PEM" 表示使用文本编码输出, 返回的是 bytes 类型, 格式如下:
# b'-----BEGIN RSA PRIVATE KEY-----\n{Base64Text}\n-----END RSA PRIVATE KEY-----'
pri_key = rsa_key.export_key("PEM")


# 转换为文本打印输出公钥和私钥
print(pub_key.decode())
print(pri_key.decode())


# 把公钥和私钥保存到文件
with open("pub.pem", "wb") as pub_fp:
    pub_fp.write(pub_key)

with open("pri.pem", "wb") as pri_fp:
    pri_fp.write(pri_key)

1.2 RSA 非对称加密/解密(公钥加密、私钥解密)


from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5


""" 1. 生成秘钥对, 创建 公钥/私钥 对象 """

# 生成一对长度为 2048 位的 RSA 秘钥对
rsa_key = RSA.generate(2048)

# 从秘钥对中获取 公钥 对象, 返回类型为: <class 'Crypto.PublicKey.RSA.RsaKey'>
pub_key = rsa_key.publickey()

# 秘钥对本身就是 私钥 对象, 类型为:    <class 'Crypto.PublicKey.RSA.RsaKey'>
pri_key = rsa_key


""" 2. 创建密码器, 加密/解密 """

# 创建 公钥 密码器, 返回类型为: <class 'Crypto.Cipher.PKCS1_v1_5.PKCS115_Cipher'>
pub_cipher = PKCS1_v1_5.new(pub_key)
# 加密内容(bytes), 返回加密后的密文(bytes类型)
ciphertext = pub_cipher.encrypt("Hello World".encode())


# 创建 私钥 密码器, 返回类型为: <class 'Crypto.Cipher.PKCS1_v1_5.PKCS115_Cipher'>
pri_cipher = PKCS1_v1_5.new(pri_key)
# 解密密文(bytes), 返回解密后的明文(bytes类型)
plaintext = pri_cipher.decrypt(ciphertext, sentinel=None)


""" 3. 查看结果 """

# 输出解密后的明文, 结果为: "Hello World"
print(plaintext.decode())

1.3 读取 RAS 秘钥对并进行非对称加密/解密

from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5


""" 1. 读取 秘钥对, 创建 公钥/私钥 对象 """

# 从 PEM 格式的 公钥 文件中读取数据
with open("pub.pem", "rb") as f:
    pub_bytes = f.read()
# 导入读取到的公钥数据, 生成 公钥对象, 返回类型为: <class 'Crypto.PublicKey.RSA.RsaKey'>
pub_key = RSA.import_key(pub_bytes)


# 从 PEM 格式的 私钥 文件中读取数据
with open("pri.pem", "rb") as f:
    pri_bytes = f.read()
# 导入读取到的私钥数据, 生成 私钥对象, 返回类型为: <class 'Crypto.PublicKey.RSA.RsaKey'>
pri_key = RSA.import_key(pri_bytes)


# 私钥中包含了公钥, 公钥也可以从私钥中获取(PS: 公钥中不包含私钥)
# pub_key = pri_key.publickey()


""" 2. 创建密码器, 加密/解密 """

# 创建 公钥 密码器, 返回类型为: <class 'Crypto.Cipher.PKCS1_v1_5.PKCS115_Cipher'>
pub_cipher = PKCS1_v1_5.new(pub_key)
# 加密内容(bytes), 返回加密后的密文(bytes类型)
ciphertext = pub_cipher.encrypt("Hello World".encode())


# 创建 私钥 密码器, 返回类型为: <class 'Crypto.Cipher.PKCS1_v1_5.PKCS115_Cipher'>
pri_cipher = PKCS1_v1_5.new(pri_key)
# 解密密文(bytes), 返回解密后的明文(bytes类型)
plaintext = pri_cipher.decrypt(ciphertext, sentinel=None)


""" 3. 查看结果 """

# 输出解密后的明文, 结果为: "Hello World"
print(plaintext.decode())

1.4 RSA 秘钥对的签名/验签(私钥签名、公钥验签)

import Crypto.PublicKey.RSA
import Crypto.Signature.PKCS1_v1_5
import Crypto.Hash.SHA256


""" 1. 生成秘钥对, 创建 公钥/私钥 对象 """

# 生成一对长度为 2048 位的 RSA 秘钥对
rsa_key = Crypto.PublicKey.RSA.generate(2048)

# 从秘钥对中获取 公钥 对象, 返回类型为: <class 'Crypto.PublicKey.RSA.RsaKey'>
pub_key = rsa_key.publickey()

# 秘钥对本身就是 私钥 对象, 类型为:    <class 'Crypto.PublicKey.RSA.RsaKey'>
pri_key = rsa_key


""" 2. 数据内容 """

# 要签名的数据内容(bytes类型)
data_content = "Hello World".encode()


""" 3. 创建 私钥 签名工具: 签名 """

# 创建 私钥 签名工具, 返回类型为: <class 'Crypto.Signature.pkcs1_15.PKCS115_SigScheme'>
pri_signer = Crypto.Signature.PKCS1_v1_5.new(pri_key)

# 创建 Hash 对象(使用 SHA256 算法), 返回类型为: <class 'Crypto.Hash.SHA256.SHA256Hash'>
msg_hash = Crypto.Hash.SHA256.new()
# 对 数据内容 进行 Hash
msg_hash.update(data_content)

# 使用 私钥 签名工具 对 数据 进行签名, 返回签名结果(bytes类型)
signature_result = pri_signer.sign(msg_hash)


""" 4. 创建 公钥 验签工具: 验签 """

# 创建 公钥 验签工具, 返回类型为: <class 'Crypto.Signature.pkcs1_15.PKCS115_SigScheme'>
pub_signer = Crypto.Signature.PKCS1_v1_5.new(pub_key)

# 创建 Hash 对象(使用 SHA256 算法), 返回类型为: <class 'Crypto.Hash.SHA256.SHA256Hash'>
msg_hash = Crypto.Hash.SHA256.new()
# 对 数据内容 进行 Hash
msg_hash.update(data_content)

# 使用公钥 验签工具 对 数据和签名 进行验签, 返回 True/False
verify = pub_signer.verify(msg_hash, signature_result)

# 校验结果为 True 表示通过验签
print(verify)


# 验签: 
#    验证「数据」、「签名」、「公钥」 三个可公开的数据是否匹配。
#    如果匹配,说明该「签名」是该「公钥」对应的「私钥」对该「数据」进行的正确签名;
#    如果不匹配,说明可能该「数据」被篡改。
#    如此可以用来验证公开发布的「数据」是否是官方(即「私钥」)发布的。

2. rsa 模块

第三方模块rsa以工具方法的形式实现 RSA 秘钥对生成、加密/解密、签名/验签。

安装rsa模块:

pip3 install rsa

ras模块中的主要函数:

# 生成秘钥对, 返回元祖: (公钥, 私钥)
pub_key, pri_key = rsa.newkeys(2048, ...)

# 保存密钥
pub_key.save_pkcs1(...)
pri_key.save_pkcs1(...)

# 读取密钥
rsa.PublicKey.load_pkcs1(...)
rsa.PrivateKey.load_pkcs1(...)

# 加密/解密
rsa.encrypt(...)
rsa.decrypt(...)

# 签名/验签
rsa.sign(...)
rsa.verify(...)

2.1 生成 RSA 秘钥对

生成一对 RSA 密钥(公钥、私钥),并保持到文件:

import rsa

# 生成长度为 2048 位的 RSA 秘钥对, 返回一个元祖: (公钥, 私钥)
pub_key, pri_key = rsa.newkeys(2048)


# 公钥对象类型为: <class 'rsa.key.PublicKey'>
print(type(pub_key))
# 私钥对象类型为: <class 'rsa.key.PrivateKey'>
print(type(pri_key))


# 把公钥和私钥保存到文件
with open("pub.pem", "wb") as pub_fp:
    # 保存为 PEM 格式, format = "PEM" 或 "DER"
    key_content = pub_key.save_pkcs1(format="PEM")
    pub_fp.write(key_content)

with open("pri.pem", "wb") as pri_fp:
    key_content = pri_key.save_pkcs1(format="PEM")
    pri_fp.write(key_content)

2.2 RSA 非对称加密/解密(公钥加密、私钥解密)

import rsa

# 生成长度为 2048 位的 RSA 秘钥对, 返回一个元祖: (公钥, 私钥)
pub_key, pri_key = rsa.newkeys(2048)

# 加密: 第一个参数为加密内容(bytes), 第二个参数为公钥, 返回加密后的密文(bytes)
ciphertext = rsa.encrypt(message="Hello World".encode(), pub_key=pub_key)

# 解密: 第一个参数是密文(bytes), 第二个参数为私钥, 返回解密后的明文(bytes)
plaintext = rsa.decrypt(crypto=ciphertext, priv_key=pri_key)

# 解密后的明文为原文: "Hello World"
print(plaintext.decode())

2.3 读取 RAS 秘钥对并进行非对称加密/解密

import rsa


# 从 PEM 格式公钥文件中读取公钥
with open("pub.pem", "rb") as f:
    pub_key = rsa.PublicKey.load_pkcs1(f.read(), format="PEM")
# 从 PEM 格式私钥文件中读取私钥
with open("pri.pem", "rb") as f:
    pri_key = rsa.PrivateKey.load_pkcs1(f.read(), format="PEM")


# 公钥对象类型为: <class 'rsa.key.PublicKey'>
print(type(pub_key))
# 私钥对象类型为: <class 'rsa.key.PrivateKey'>
print(type(pri_key))


# 加密: 第一个参数为加密内容(bytes), 第二个参数为公钥, 返回加密后的密文(bytes)
ciphertext = rsa.encrypt(message="Hello World".encode(), pub_key=pub_key)
# 解密: 第一个参数是密文(bytes), 第二个参数为私钥, 返回解密后的明文(bytes)
plaintext = rsa.decrypt(crypto=ciphertext, priv_key=pri_key)

# 解密后的明文为原文: "Hello World"
print(plaintext.decode())

2.4 RSA 秘钥对的签名/验签(私钥签名、公钥验签)

import rsa

# 生成长度为 2048 位的 RSA 秘钥对, 返回一个元祖: (公钥, 私钥)
pub_key, pri_key = rsa.newkeys(2048)

# 需要签名/验签的内容
content = "Hello World".encode()

# 签名:
#     第一个参数为签名的内容(bytes), 第二个参数为私钥, 第三个参数为使用的HASH算法。
#     返回签名结果(bytes)
sign = rsa.sign(message=content, priv_key=pri_key, hash_method="SHA-256")

# 验签:
#     第一个参数为验签的内容(bytes), 第二个参数为签名(bytes), 第三个参数为公钥。
#     验签通过, 返回签名算法名称(str); 验签失败, 抛出异常。
verify = rsa.verify(message=content, signature=sign, pub_key=pub_key)

# 结果为: "SHA-256"
print(verify)
  • 10
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

谢TS

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值