XML数字签名是W3C制定的开放标准,用于保障XML数据的完整性、身份认证和不可否认性;它通过Signature元素封装SignedInfo、SignatureValue、KeyInfo等组件,支持Enveloped、Enveloping和Detached三种形式,并依赖规范化(C14N)确保逻辑等价XML生成一致摘要。

XML数字签名(XML Signature,也称XML-DSig或XML-Sig)是一种由W3C制定的开放标准,用于对任意数据(尤其是XML文档或其片段)进行数字签名,以保障完整性、身份认证和不可否认性。它不是新发明密码算法,而是定义了一套可扩展、结构清晰的XML语法与处理规则,把签名过程标准化、可验证、可嵌入。
核心语法结构:Signature元素及其关键子元素
一个XML数字签名封装在根元素中,主要包含以下必需或可选部分:
-
SignedInfo:签名运算的核心输入,必须存在。它描述“签了什么”和“怎么签”,含:
-
:指定规范化算法(如http://www.w3.org/2001/10/xml-exc-c14n#),确保不同格式但语义相同的XML产生一致字节流; -
:声明签名算法(如http://www.w3.org/2001/04/xmldsig-more#rsa-sha256); -
(可多个):通过URI引用被签名资源(如#id123指向某),每个Reference还可含(如XPath筛选、Enveloped签名变换)和/(摘要算法与结果)。
-
-
SignatureValue:Base64编码的签名值,即用私钥对规范化后
SignedInfo的摘要加密所得; - KeyInfo(可选):提供验签所需的公钥信息,常见为X.509证书;若省略,则接收方需从上下文(如配置、SAML元数据)获取密钥;
- Object(可选):仅在enveloping签名中使用,内嵌被签名的原始数据。
三种签名形式:适配不同场景
XML签名不强制绑定数据位置,按签名与被签名内容的关系分为:
-
Enveloped signature:签名嵌在被签名的XML文档内部(如SOAP消息体中),且签名本身不参与自身计算——需用
XmlDsigEnvelopedSignatureTransform排除节点,否则验证会死循环; -
Enveloping signature:签名包裹数据,
子元素内直接包含被签名内容,适合打包传输; -
Detached signature:签名与原始数据完全分离(如签名文件
doc.xml.sig独立于doc.xml),常用于签署外部资源、二进制文件(JPEG)、HTML或跨系统交换。
处理流程:签名与验证的关键步骤
签名生成和验证都依赖严格顺序,缺一不可:
-
签名时:
① 确定目标资源并构造Reference(URI+可选Transform);
② 对每个引用资源执行指定Transform(如XPath过滤、C14N);
③ 计算规范化后数据的摘要(DigestValue);
④ 规范化整个SignedInfo(用CanonicalizationMethod);
⑤ 用私钥对规范化SignedInfo签名,填入SignatureValue。 -
验证时(Core Validation):
① 引用验证:按Reference重取资源→执行相同Transform→计算Digest→比对DigestValue;
② 签名验证:规范化SignedInfo→用公钥(来自KeyInfo或外部)解密SignatureValue→比对解出摘要与本地计算摘要。
为什么必须做规范化(Canonicalization)?
XML允许等价内容有多种物理表示(属性顺序不同、空格增减、命名空间前缀变化、编码差异等)。例如:
二者逻辑完全相同,但字符串不等。若不规范化,同一文档在不同系统序列化后哈希值不同,签名必然失败。规范XML(C14N)强制统一字节输出,是XML签名可靠性的基石。










