使用ECDSA签名同一消息每次结果不同是否正常?
为什么ECDSA签名同一消息每次结果不同?
我编写了以下使用ecdsa库签名消息的Python代码,每次运行都会得到不同的签名结果:
import ecdsa from hashlib import sha256 random_number_for_private_key = 31334737451456268050498185842994455999554006395290392504114029053954839148697 private_key_hex = hex(random_number_for_private_key)[2:] private_key_bytes = bytes.fromhex(private_key_hex) private_key_object=ecdsa.SigningKey.from_string(private_key_bytes, curve=ecdsa.SECP256k1, hashfunc=sha256) public_key = private_key_object.get_verifying_key() sig = private_key_object.sign(b"message") print(sig.hex())
多次运行得到的结果如下:
91654d84e462a4f55429a9f8ea6458c6c11387859d6fa9c53e7376a131e49cd76ee8462c9e0ceb0ce7d1116609fe52d4c6c80d6fe84a0f72ffdde4223152a262
2b96a77ee8fe1058c97c32c2146999f7e0b0305d449de81a3ee9ce0c7d909c65d42f2d7eabfd02b214ca591a19760f69e47ca7b7331547cda2d5d759d09e8106
fb41a7b8fd59b60035f4f4d66ee7aac41a62376b78885d8df3bcce95b3a4de1161cdd5029a5cf1e9dae67aaa792e1d0b79e32663d7c3bfcb82892443c7abde91
当我使用以下代码验证时,所有结果均返回True:
import ecdsa from hashlib import sha256 message = b"message" public_key = '46454399998223bdb3771f08341844c485cd6b0e35383635cbc56940a755e5b6986ef0dbd1381267575bf290843540d3061f089fbab1b8f60cfe3d3d0d6aef52' sig = '91654d84e462a4f55429a9f8ea6458c6c11387859d6fa9c53e7376a131e49cd76ee8462c9e0ceb0ce7d1116609fe52d4c6c80d6fe84a0f72ffdde4223152a262' vk = ecdsa.VerifyingKey.from_string(bytes.fromhex(public_key), curve=ecdsa.SECP256k1, hashfunc=sha256) vk.verify(bytes.fromhex(sig), message)
请问这种每次得到不同签名结果的情况是预期的吗?
注:私钥和公钥为真实密钥,但未用于任何生产环境。
回答
这是完全符合预期的行为,核心原因如下:
- ECDSA签名算法本身依赖一个随机生成的临时值
k(称为nonce),每次签名时都会生成全新的随机k,最终生成的签名是(r, s)对,会随k的变化而不同。 - 这种随机化设计是安全要求:如果重复使用相同的
k签名不同消息,攻击者可以通过计算推导出你的私钥,随机化k就是为了避免这个风险。 - 你使用的ecdsa库默认采用了安全的随机化签名实现,所以每次输出不同签名是正常且安全的表现,所有合法签名都能被对应公钥验证通过。
内容的提问来源于stack exchange,提问作者Mahsum Akbas
相关产品推荐
相关产品推荐

