Python中ECDSA签名验证失败的原因排查
ECDSA签名验证失败的原因分析
问题背景
尝试构建并验证ECDSA签名时遇到失败:
- 第一段代码中的
sign函数生成的签名,用同一段代码的validate函数验证失败; - 第二段代码的
singmessage和validatemessage能正常互操作,但用singmessage生成的签名,用第一段的validate函数验证仍然失败。
已确认使用配对的公私钥和相同的payload/消息,仍无法通过验证。
核心原因:哈希处理逻辑不匹配
两段代码的签名/验证流程中,哈希的处理方式不一致,导致签名与验证的内容不匹配:
1. 第一段代码的逻辑矛盾
sign函数:手动计算payload的SHA256哈希,再用私钥对哈希值签名:payload_hash = hashlib.sha256(payload).digest() signature = key.sign(payload_hash)validate函数:调用verify时传入hashfunc=hashlib.sha256,此时ecdsa库会自动对传入的payload计算SHA256哈希,再验证签名是否匹配这个新哈希值:
相当于签名的是「payload的哈希」,但验证的是「payload的哈希的哈希」,自然不匹配。isvalid = key.verify(signature, payload, hashfunc=hashlib.sha256)
2. 第二段代码的逻辑自洽
singmessage函数:手动计算payload的SHA256哈希,对哈希值签名;validatemessage函数:同样手动计算payload的SHA256哈希,调用verify时直接传入这个哈希值,且不指定hashfunc参数,验证签名是否匹配该哈希值。
两者逻辑一致,所以能正常验证。
3. 跨代码验证失败的原因
用singmessage生成的签名是基于「payload的哈希值」,但用validate验证时,会自动对payload再做一次哈希,相当于验证的是「payload哈希的哈希」,与签名的原始内容不匹配,因此验证失败。
修复方案
只需让签名和验证的哈希处理逻辑保持一致,二选一即可:
方案一:修改签名逻辑,让库自动处理哈希
修改第一段代码的sign函数,去掉手动哈希步骤,直接让ecdsa库处理哈希:
def sign(payload, certid): print("payload used to build sig") print(payload) path = os.path.join(os.path.expanduser('~'), 'Dokumente', 'privKeys', certid + '.pem') key_file = open(path, "rb") key = ecdsa.SigningKey.from_pem(key_file.read()) # 去掉手动哈希,让库自动用SHA256处理payload signature = key.sign(payload, hashfunc=hashlib.sha256) print(validate(signature, payload, certid)) return signature
方案二:修改验证逻辑,手动处理哈希
修改第一段代码的validate函数,手动计算哈希后再验证:
def validate(signature, payload, certID): path = os.path.join(os.path.expanduser('~'), 'Dokumente', 'publiccerts', certID + '.pem') key_file = open(path, "rb") key = ecdsa.VerifyingKey.from_pem(key_file.read()) print("payload used for verify sig: ") print(payload) # 手动计算payload的SHA256哈希 payload_hash = hashlib.sha256(payload).digest() # 验证签名与哈希值是否匹配,不指定hashfunc isvalid = key.verify(signature, payload_hash) print(isvalid) return isvalid
内容的提问来源于stack exchange,提问作者Killrogg
相关产品推荐
相关产品推荐

