我正在使用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>如您所见,这个版本省略了<samlp:Response>元素中的xmlns:saml属性,而第一个版本没有。(请注意,这与xmlns:samlp属性不同,后者都包含在这两个属性中。)这看起来很像是xmlseclibs中的一个bug,但尽管如此,如果我知道哪种规范形式是正确的,我很乐意自己修复它。排他性规范化应该省略该属性吗?还是应该把它包括在内?哪一种是正确的独占规范形式?
发布于 2010-02-05 02:55:50
您创建的DOM文档不正确,并试图使用无效的内存中树。序列化并使用序列化的结果,或者在尝试签名之前在树中正确创建命名空间声明。有关详细信息,请参阅错误报告:http://code.google.com/p/xmlseclibs/issues/detail?id=6
发布于 2010-02-05 00:28:07
也不是正确的规范形式!
签名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>埃塔:我刚刚研究了SVN中的xmlseclibs.php,并没有一个简单的修复方法,因为它目前的方法存在根本性的缺陷。它试图创建一个“规范化的”DOM,然后用普通的旧saveXML()序列化它。由于存在saveXML不承诺遵循的有关属性顺序和字符转义的C14N序列化规则,因此这是不可能实现的。
https://stackoverflow.com/questions/2200988
复制相似问题