1

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

我向 xmlseclibs 添加了一些调试代码以了解它在做什么,并且我意识到它提供的签名密钥和提供的验证密钥不同的原因是因为它在两种情况下对事物进行了不同的规范化。当我告诉它签署<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" 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>

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

4

2 回答 2

3

也不是正确的规范形式!

签名 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,然后用普通的 old 序列化它saveXML()。由于没有承诺遵循的关于属性顺序和字符转义的 C14N 序列化规则saveXML,因此这不可能起作用。

于 2010-02-04T16:28:07.140 回答
2

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

于 2010-02-04T18:55:50.410 回答