Python cryptography库结合OpenSSL密钥进行加解密与签名实战
本文详细介绍如何使用Python的cryptography库结合OpenSSL生成的RSA密钥对进行安全通信。内容涵盖从Linux环境下使用yum安装openssl、生成私钥与公钥文件,到在Python中加载密钥、执行RSA签名与验证、以及公钥加密私钥解密的全过程。文中提供了具体的代码示例,包括处理大文件时的Prehashed用法及PSS填充方案,帮助开发者掌握完整的加解密与身份验证流程。
密钥的使用流程通常包含以下核心步骤:
首先,利用私钥对数据进行签名,并将签名后的数据发送出去,接收方使用对应的公钥进行验证。
其次,使用公钥对数据进行加密,发送加密后的密文,接收方使用私钥进行解密以获取原始信息。
在实际应用场景中,通常先通过OpenSSL工具生成密钥对,随后再在代码中进行调用。在Linux系统中生成密钥的操作相对简便。
通过yum命令安装openssl组件。
yum -y install openssl
执行命令以生成三个关键的密钥文件。
rsa_private_key.pem,即私钥文件。
rsa_private_key_pkcs8.pem,这是转换为PKCS8格式的私钥文件。
rsa_public_key.pem,即公钥文件。
openssl genrsa -out rsa_private_key.pem 1024
openssl pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt -out rsa_private_key_pkcs8.pem
openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
在代码中导入私钥。
序列化密钥时,可以选择使用密码对磁盘上的密钥进行加密。在本文示例中,我们加载的是未加密的密钥,因此未提供密码参数。若加载的是加密密钥,则需要传递一个bytes类型的对象作为password参数。
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization
# 已有sar私匙, 导入
with open('Key.pem', 'rb') as key_file:
private_key = serialization.load_pem_private_key(
key_file.read(),
password=None,
backend=default_backend()
)
接下来进行签名操作。
私钥可用于对消息进行签名,这使得任何持有公钥的人都能验证该消息确实由拥有相应私钥的一方创建。RSA签名需要指定特定的散列函数并使用填充机制。以下是使用RSA对message进行签名的示例,其中包含了安全散列函数和填充配置:
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding
# 已有sar私匙, 导入
with open('Key.pem', 'rb') as key_file:
private_key = serialization.load_pem_private_key(
key_file.read(),
password=None,
backend=default_backend()
)
message = b"aaaa, bbbb, cccc"
# 签名操作
signature = private_key.sign(
message,
padding.PSS(
mgf=padding.MGF1(hashes.SHA256()),
salt_length=padding.PSS.MAX_LENGTH
),
hashes.SHA256()
)
print('签名后数据: ', signature)
有效的签名填充方式包括PSS和PKCS1v15。对于任何新的协议或应用,推荐选择PSS;而PKCS1v15仅应用于需要支持传统协议的场景。
如果您的数据量过大,无法在一次调用中直接传递,可以先对数据进行散列处理,然后使用该散列值配合Prehashed参数进行签名。
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives.asymmetric import utils
# 已有sar私匙, 导入
with open('Key.pem', 'rb') as key_file:
private_key = serialization.load_pem_private_key(
key_file.read(),
password=None,
backend=default_backend()
)
# 如果您的数据太大而无法在单个调用中传递,则可以分别对其进行散列并使用该值 Prehashed。
chosen_hash = hashes.SHA256()
hasher = hashes.Hash(chosen_hash, default_backend())
hasher.update(b"data &")
hasher.update(b"more data")
digest = hasher.finalize()
sig = private_key.sign(
digest,
padding.PSS(
mgf=padding.MGF1(hashes.SHA256()),
salt_length=padding.PSS.MAX_LENGTH
),
utils.Prehashed(chosen_hash)
)
print('签名后数据: ', sig)
随后进行签名验证。
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding
# 已有sar私匙, 导入
with open('Key.pem', 'rb') as key_file:
private_key = serialization.load_pem_private_key(
key_file.read(),
password=None,
backend=default_backend()
)
message = b"123 xiao"
# 签名
signature = private_key.sign(
# 原始数据
message,
padding.PSS(
mgf=padding.MGF1(hashes.SHA256()),
salt_length=padding.PSS.MAX_LENGTH
),
hashes.SHA256()
)
print('签名后的数据: ', signature)
# 公匙导入
with open('Key_pub.pem', 'rb') as key_file:
public_key = serialization.load_pem_public_key(
key_file.read(),
backend=default_backend()
)
# 签名数据与原始数据不对,抛出异常
# 如果验证不匹配,verify()会引发 InvalidSignature异常。
public_key.verify(
# 签名数据
signature,
# 原始数据
message,
padding.PSS(
mgf=padding.MGF1(hashes.SHA256()),
salt_length=padding.PSS.MAX_LENGTH
),
hashes.SHA256()
)
同样地,若数据量过大无法单次传递,可先单独进行散列,并使用该值配合Prehashed参数进行验证。
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives.asymmetric import utils
# 已有sar私匙, 导入
with open('Key.pem', 'rb') as key_file:
private_key = serialization.load_pem_private_key(
key_file.read(),
password=None,
backend=default_backend()
)
chosen_hash = hashes.SHA256()
hasher = hashes.Hash(chosen_hash, default_backend())
hasher.update(b'data &')
hasher.update(b'more data')
digest = hasher.finalize()
sig = private_key.sign(
digest,
padding.PSS(
mgf=padding.MGF1(hashes.SHA256()),
salt_length=padding.PSS.MAX_LENGTH
),
utils.Prehashed(chosen_hash)
)
print('签名后的数据: ', sig)
# 公匙导入
with open('Key_pub.pem', 'rb') as key_file:
public_key = serialization.load_pem_public_key(
key_file.read(),
backend=default_backend()
)
# 如果您的数据太大而无法在单个调用中传递,则可以分别对其进行散列并使用该值 Prehashed。
public_key.verify(
sig,
digest,
padding.PSS(
mgf=padding.MGF1(hashes.SHA256()),
salt_length=padding.PSS.MAX_LENGTH
),
utils.Prehashed(chosen_hash)
)
接着使用公钥进行加密操作。
由于使用的是公钥进行加密,这一机制的特点是任何人都可以对数据进行加密。加密后的数据随后使用私钥进行解密。
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding
# 公匙导入
with open('Key_pub.pem', 'rb') as key_file:
public_key = serialization.load_pem_public_key(
key_file.read(),
backend=default_backend()
)
message = b'test data'
ciphertext = public_key.encrypt(
message,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
print('加密数据: ', ciphertext)
使用私钥对通过公钥加密的信息进行解密。
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding
# 已有sar私匙, 导入
with open('Key.pem', 'rb') as key_file:
private_key = serialization.load_pem_private_key(
key_file.read(),
password=None,
backend=default_backend()
)
plaintext = private_key.decrypt(
# 加密的信息
ciphertext,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
print('解密数据: ', plaintext)
完整流程展示了公钥加密、私钥解密以获取原始信息的过程。
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding
# 公匙导入
with open('Key_pub.pem', 'rb') as key_file:
public_key = serialization.load_pem_public_key(
key_file.read(),
backend=default_backend()
)
message = b'test data'
ciphertext = public_key.encrypt(
message,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
print('加密数据: ', ciphertext)
# 已有sar私匙, 导入
with open('Key.pem', 'rb') as key_file:
private_key = serialization.load_pem_private_key(
key_file.read(),
password=None,
backend=default_backend()
)
plaintext = private_key.decrypt(
# 加密的信息
ciphertext,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
print('解密数据: ', plaintext)
关于Python加密解密库cryptography的更多使用方法,请参阅下方的相关链接。
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













