You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Python cryptography库实现带签名的RSA加密?

RSA实现带保密性、完整性、真实性的消息传输问题解答

核心问题与方案梳理

你需要用RSA实现Alice到Bob的消息传输,同时满足三个核心安全要求:

  • 保密性:仅Bob能解密消息
  • 真实性:Bob可确认消息来自Alice
  • 完整性:消息传输中未被篡改

你尝试过两种拼接式方案,遇到了RSA加密长度限制的问题,对Topaco提出的"密文+签名分离发送"方案存在疑惑,以下是具体分析和修正方案:

1. 你当前拼接方案的缺陷

你当前代码中用分隔符拼接消息与签名后加密,存在两个关键问题:

  • 长度限制:RSA单次加密的明文长度受密钥和填充算法约束(4096位RSA+OAEP-SHA256的最大明文长度为446字节左右),长消息+签名的组合很容易超出限制导致加密失败。
  • 拆分风险:如果消息本身包含分隔符|,拆分操作会直接出错,存在逻辑隐患。

2. Topaco方案的合理性解释

你觉得"发送两个内容奇怪"是多虑了,这种密文与签名分离的方式是业内标准做法,原因如下:

  • RSA签名针对的是哈希值,长度固定(4096位RSA的签名为512字节),不会受消息长度影响。
  • 先加密再签名的逻辑更清晰:签名保证密文未被篡改且来自Alice,解密保证只有Bob能获取原始消息。
  • 避免了拼接拆分的潜在风险,同时便于扩展(比如后续切换为更高效的混合加密方案)。

3. 修正后的代码实现

我们基于Topaco方案优化,同时用长度前缀的方式打包密文与签名(避免分隔符的缺陷):

from cryptography.exceptions import InvalidSignature
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding, rsa
import struct

# 生成密钥对
alice_private_key = rsa.generate_private_key(public_exponent=65537, key_size=4096)
alice_public_key = alice_private_key.public_key()
bob_private_key = rsa.generate_private_key(public_exponent=65537, key_size=4096)
bob_public_key = bob_private_key.public_key()

message = b"Hello, world! This is a longer message to test RSA length limits."

# Alice侧操作:先加密,再签名,最后打包
# 1. 用Bob公钥加密消息(保证保密性)
ciphertext = bob_public_key.encrypt(
    message,
    padding.OAEP(
        mgf=padding.MGF1(algorithm=hashes.SHA256()),
        algorithm=hashes.SHA256(),
        label=None
    )
)

# 2. 用Alice私钥对密文签名(保证真实性与完整性)
signature = alice_private_key.sign(
    ciphertext,
    padding.PSS(
        mgf=padding.MGF1(hashes.SHA256()),
        salt_length=padding.PSS.MAX_LENGTH
    ),
    hashes.SHA256()
)

# 3. 打包数据:4字节大端存储签名长度 + 签名 + 密文
packed_data = struct.pack('>I', len(signature)) + signature + ciphertext

# Bob侧操作:先解析,再验签,最后解密
# 1. 解析打包的数据
sig_len = struct.unpack('>I', packed_data[:4])[0]
received_signature = packed_data[4:4+sig_len]
received_ciphertext = packed_data[4+sig_len:]

# 2. 验证签名
try:
    alice_public_key.verify(
        received_signature,
        received_ciphertext,
        padding.PSS(
            mgf=padding.MGF1(hashes.SHA256()),
            salt_length=padding.PSS.MAX_LENGTH
        ),
        hashes.SHA256()
    )
    print("签名验证通过:消息来自Alice且未被篡改")
    # 3. 解密密文
    plaintext = bob_private_key.decrypt(
        received_ciphertext,
        padding.OAEP(
            mgf=padding.MGF1(algorithm=hashes.SHA256()),
            algorithm=hashes.SHA256(),
            label=None
        )
    )
    print("解密后的消息:", plaintext.decode('utf-8'))
except InvalidSignature as e:
    print("签名验证失败:消息可能被篡改或非Alice发送")

4. 生产环境最优方案:混合加密

RSA加密大消息效率极低,实际场景中会采用对称加密+RSA的混合方案:

  1. Alice生成随机对称密钥(如AES-256-GCM)
  2. 用对称密钥加密消息(高效处理大消息)
  3. 用Bob公钥加密对称密钥
  4. 用Alice私钥对「加密后的对称密钥+密文哈希」签名
  5. 发送:加密后的对称密钥 + 密文 + 签名
  6. Bob:先验签,再解密对称密钥,最后解密密文

该方案兼顾了安全性与效率,是工业界的标准实践。

关键知识点总结

  • 私钥用于签名(证明身份),公钥用于加密(保证仅对应私钥持有者可解密),切勿混淆用途。
  • RSA加密存在长度限制,无法直接处理大消息,优先考虑混合加密方案。
  • 签名应针对需要验证完整性的内容(如密文),而非原始消息,避免额外的加密/解密开销。
  • 二进制内容拼接优先用长度前缀替代分隔符,避免消息含分隔符导致的拆分错误。

内容的提问来源于stack exchange,提问作者BOSS_ladis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 13:35:20