在 RSA 签名中,即使使用相同的私钥对同一条消息进行多次签名,生成的签名是否相同,取决于所使用的 填充方案(Padding Scheme)。以下是具体分析:
1. 如果使用 PKCS1v15
填充
每次签名结果相同
PKCS1v15
是确定性填充方案,对同一消息和密钥,生成的签名永远相同。
from cryptography.hazmat.primitives.asymmetric import padding
signature1 = private_key.sign(
message,
padding.PKCS1v15(),
hashes.SHA512()
)
signature2 = private_key.sign(
message,
padding.PKCS1v15(),
hashes.SHA512()
)
print(signature1 == signature2) # 输出 True
原因:PKCS1v15 的签名过程是纯数学计算,无随机性。
2. 如果使用 PSS
填充
每次签名结果不同,PSS
(Probabilistic Signature Scheme)是概率性填充方案,会引入随机盐值(salt),因此每次签名结果不同。
signature1 = private_key.sign(
message,
padding.PSS(
mgf=padding.MGF1(hashes.SHA512()),
salt_length=padding.PSS.MAX_LENGTH
),
hashes.SHA512()
)
signature2 = private_key.sign(
message,
padding.PSS(
mgf=padding.MGF1(hashes.SHA512()),
salt_length=padding.PSS.MAX_LENGTH
),
hashes.SHA512()
)
print(signature1 == signature2) # 输出 False
原因:PSS 会为每次签名生成不同的随机盐,导致签名结果不同,但所有结果均可通过验证。
3. 验证签名的关键点
无论签名是否相同,只要使用相同的填充方案和哈希算法,所有签名都能通过验证:
public_key.verify(
signature1, # 或 signature2
message,
padding.PSS(..., salt_length=padding.PSS.MAX_LENGTH),
hashes.SHA512()
) # 不会报错
4. 安全性和应用场景
填充方案 | 签名是否可变 | 安全性 | 典型用途 |
PKCS1v15 | ❌ 固定 | 较低(确定性) | 兼容旧系统 |
PSS | ✅ 变化 | 更高(抗碰撞) | 现代安全应用(推荐) |
5. 为什么 PSS 更安全?
- 抵抗重放攻击:相同消息的多次签名不同,防止签名被复用。
- 抵抗理论攻击:随机盐增加了破解难度(如避免数学上的共模攻击)。
总结
- PKCS1v15:相同输入 → 相同签名(确定性)。
- PSS:相同输入 → 不同签名(概率性,更安全)。
- 验证兼容性:两种方案的签名均可被正确验证,只要参数一致。
生产环境推荐使用 PSS,除非需要兼容旧系统。