如何正确对XML中指定xades:SignedProperties标签进行SHA256哈希?
问题分析与解决方案
你的核心问题出在XML节点提取方式错误和哈希编码流程错误两点:
错误点拆解
- 用字符串分割提取XML节点完全不可靠:XML的属性顺序、空格、命名空间前缀可能和你写的分割字符串不一致,导致提取的内容并非目标节点的完整规范内容。
- 哈希后处理错误:你先把SHA256的二进制哈希转成了十六进制字符串,再对这个字符串做Base64编码,而正确流程是直接对哈希的二进制结果做Base64编码。
- 未针对目标节点单独做XML规范化(C14N):你对整个文档做了C14N,再分割节点,这不符合要求的「仅对指定SignedProperties节点做规范化后哈希」的逻辑。
修正后的代码
import lxml.etree as ET import hashlib import base64 # 解析XML文档 tree = ET.parse("sample_Invoice.xml") ns = {"xades": "http://uri.etsi.org/01903/v1.3.2#"} # 用XPath定位目标节点:ID为xadesSignedProperties的SignedProperties target_node = tree.xpath('//xades:SignedProperties[@Id="xadesSignedProperties"]', namespaces=ns)[0] # 对目标节点单独执行C14N规范化(XML-Canonicalization) canonicalized_node = target_node.encode_c14n() # 计算SHA256哈希(直接用二进制结果) hash_result = hashlib.sha256(canonicalized_node).digest() # 对二进制哈希结果做Base64编码 base64_result = base64.b64encode(hash_result).decode() print(base64_result)
关键说明
- 用XPath准确定位节点:通过命名空间和属性ID精准找到目标节点,避免字符串分割的不确定性。
- 节点级C14N:仅对目标SignedProperties节点执行规范化,确保符合政府要求的处理范围。
- 正确的哈希编码流程:
digest()返回二进制哈希值,直接对其做Base64编码,而非先转十六进制再编码。
内容的提问来源于stack exchange,提问作者Mohammed almalki
相关产品推荐
相关产品推荐

