什么是Canonical XML (C14N) XML规范化方法

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

Canonical XML(简称 C14N)是一种将 XML 文档转换为唯一、确定性字节序列的标准方法,目的是让逻辑上等价的 XM

L 文档在签名和验证场景中产生完全一致的哈希值或数字签名。

为什么需要 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 等安全协议的基础。