Canonical XML(C14N)是将逻辑等价XML文档转换为唯一字节序列的标准,用于确保数字签名一致性;其通过UTF-8编码、属性排序、空白规范化、实体展开、移除声明注释等规则实现确定性输出。

Canonical XML(简称 C14N)是一种将 XML 文档转换为唯一、确定性字节序列的标准方法,目的是让逻辑上等价的 XML 文档在签名和验证场景中产生完全一致的哈希值或数字签名。
为什么需要 XML 规范化
XML 允许大量词法等价但字面不同的写法:属性顺序可变、命名空间前缀可选、空白处理自由、引号类型不同(单/双)、换行与缩进不统一、CDATA 与文本等价、实体引用可展开或保留……这些差异不会影响解析结果,却会导致原始字节流完全不同。数字签名依赖字节级一致性,因此必须先“标准化”再签名。
C14N 的核心规范化规则
W3C Canonical XML 1.0(REC-xml-c14n-20010315)定义了以下关键处理:
- 使用 UTF-8 编码,换行统一为 0x0A
- 属性按名称字母序排序(如
a="1" c="3" b="2"→a="1" b="2" c="3") - 所有属性值中的空白字符被规范化(多个空格/制表符/换行归为单个空格,首尾截断)
- 展开所有字符实体(
&→&,→ 换行符等) - 移除 XML 声明(
)、DTD、注释、处理指令 - 空元素统一写为开始+结束标签对(
→) - 命名空间声明仅保留在最靠近使用它的元素上,冗余声明被剔除
Exclusive vs Inclusive 两种主流模式
实际应用中更常用的是带上下文感知的变体:
-
Exclusive C14N(URI:
http://www.w3.org/2001/10/xml-exc-c14n#):只保留当前子树显式使用的命名空间,忽略父级或外部作用域中未直接引用的命名空间声明——适合签名局部片段,避免因外部环境变化导致签名失效 -
Inclusive C14N(URI:
http://www.w3.org/TR/2001/REC-xml-c14n-20010315):保留所有在作用域内有效的命名空间声明(包括继承的),更严格但易受周边 XML 结构影响
两者都支持带/不带注释(exclusive_with_comments 等)的扩展版本,但生产环境普遍禁用注释以增强确定性。
它不是格式美化,而是签名前提
C14N 不是为了让人读得舒服,而是为了机器可验证。一次规范化是幂等的——对已规范的文档再次执行,输出不变。只要输入逻辑等价,输出必完全相同(字节级)。这也是它能支撑 XML Signature、SAML 断言、WS-Security 等安全协议的基础。










