【问题标题】:Which is the proper XML exclusive canonicalization?哪个是正确的 XML 专有规范化?
【发布时间】:2010-02-04 15:46:28
【问题描述】:

我正在使用 xmlseclibs 尝试签署 SOAP 文档,但它似乎并没有以相同的方式规范化事物,具体取决于我是在签名还是验证。

我给你举个例子。这是我要签名的 XML:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header/>
<soapenv:Body>
<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:1.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion" MajorVersion="1" MinorVersion="1" IssueInstant="2010-02-04T15:27:43Z" ResponseID="pfxe85313e6-e688-299a-df06-30f55e24f65a">
<samlp:Status>
<samlp:StatusCode Value="samlp:Requester"/>
</samlp:Status>
</samlp:Response>
</soapenv:Body>
</soapenv:Envelope>

我得到了一些在 PHP 中工作的代码,以使用公钥和私钥证书的组合对其进行签名,并且它似乎可以工作。它添加了 &lt;ds:Signature&gt; 元素和所有适当的东西,看起来很棒。但后来我在签名后立即尝试验证它,再次使用 xmlseclibs(和公钥证书)对其进行了测试,但验证失败。因此,完全相同的代码库正在执行签名和验证,但是由于某种原因这两个进程不同意。

我在 xmlseclibs 中添加了一些调试代码以了解它在做什么,我意识到它提供的签名密钥和验证密钥不同的原因是因为它在两种情况下对事物进行了不同的规范化.当我告诉它签署 &lt;samlp:Response&gt; 元素时,这是它签署的规范形式(为了便于阅读,我在此处添加了换行符):

<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:1.0:protocol" IssueInstant="2010-02-04T15:27:43Z" MajorVersion="1" MinorVersion="1" ResponseID="pfxe85313e6-e688-299a-df06-30f55e24f65a" xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion">
<samlp:Status>
<samlp:StatusCode Value="samlp:Requester">
</samlp:StatusCode>
</samlp:Status>
</samlp:Response>

但是,当它验证签名时,这是它计算验证的规范形式(再次,我在这里添加了换行符):

<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:1.0:protocol" IssueInstant="2010-02-04T15:27:43Z" MajorVersion="1" MinorVersion="1" ResponseID="pfxe85313e6-e688-299a-df06-30f55e24f65a">
<samlp:Status>
<samlp:StatusCode Value="samlp:Requester">
</samlp:StatusCode>
</samlp:Status>
</samlp:Response>

如您所见,这个版本省略了&lt;samlp:Response&gt; 元素中的xmlns:saml 属性,而第一个版本没有。 (请注意,这与 xmlns:samlp 属性不同,后者包含在两者中。)这看起来很明显就像 xmlseclibs 中的一个错误,但尽管如此,如果我知道哪种规范形式是,我很乐意自己修复它正确的。是否应该通过排他规范化省略该属性?还是应该包括在内?哪一种是正确的排他规范形式?

【问题讨论】:

  • 它看起来确实像一个错误,您应该将它发布到 xmlseclibs 的问题跟踪器。

标签: php xml canonicalization canonical-form xmlseclibs


【解决方案1】:

两者都不是正确的规范形式!

签名 XML 在非命名空间属性之后有一个命名空间声明,这违反了文档顺序规则:

命名空间节点的文档顺序位置低于属性节点。

验证 XML 完全缺少 saml 命名空间节点。规范化不会仅仅因为没有引用它们的子内容而删除命名空间节点。它只会删除多余的命名空间节点(即已经在父节点上生效的命名空间)。

我对 xmlseclibs 的了解还不够,无法说明为什么会发生这种情况,但这在这两个方面都绝对是错误的。 FWIW 我的 DOM 上的 c14n 函数在这里说:

<samlp:Response xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion" xmlns:samlp="urn:oasis:names:tc:SAML:1.0:protocol" IssueInstant="2010-02-04T15:27:43Z" MajorVersion="1" MinorVersion="1" ResponseID="pfxe85313e6-e688-299a-df06-30f55e24f65a">
<samlp:Status>
<samlp:StatusCode Value="samlp:Requester"></samlp:StatusCode>
</samlp:Status>
</samlp:Response>

eta:我刚刚查看了 SVN 中的 xmlseclibs.php,并且没有简单的解决方法,因为它目前的方法存在根本缺陷。它尝试创建一个“规范化”的 DOM,然后用普通的旧 saveXML() 序列化它。由于存在saveXML 不承诺遵循的关于属性顺序和字符转义的 C14N 序列化规则,因此这不可能起作用。

【讨论】:

  • 你知道有什么替代代码库可以进行 XML 签名吗?它不一定必须是 PHP 本身;它可能是一个 COM 对象,也可能是我可以与之交互的完全其他东西。
  • 不知道 PHP(我的是 Python)... 不过,为 DOMDocument 编写符合 c14n 的序列化器函数可能并不难,规则实际上并不是非常复杂(XML 序列化比解析容易得多)。对于 Windows,有 WWSAPI msdn.microsoft.com/en-us/library/dd430435%28VS.85%29.aspx,但这只是默认安装在 Win7+ 上。还有用于命令行的 XMLStarlet。
  • @SoaperGEM PHP DOM 扩展有一个(最近才记录,但从 5.2.0 开始就有)c14n 方法:php.net/manual/en/domnode.c14n.php
【解决方案2】:

您正在不正确地创建 DOM 文档并尝试使用无效的内存树。序列化并使用序列化结果,或者在尝试签名之前在树中正确创建命名空间声明。有关更多信息,请参阅错误报告:http://code.google.com/p/xmlseclibs/issues/detail?id=6

【讨论】:

    猜你喜欢
    • 2014-05-22
    • 2015-03-24
    • 2013-12-25
    • 2022-09-28
    • 2018-01-02
    • 1970-01-01
    • 1970-01-01
    • 2011-07-20
    • 1970-01-01
    相关资源
    最近更新 更多