我一直在尝试让 xmllib 通过 合作并验证 xmldsig<Signature>元素DOMDocument,但无论我如何将元素扔给它,它都会不断产生虚假错误。显然,由于而无法<Signature>成为 root 。我无法正确设置根上的属性:尝试验证结果:DOMDocumentxmlns
Element 'Signature': No matching global declaration available for the validation root.
我认为这可能是因为模式旨在“包含”,您毕竟想要签署“某些东西”,而不仅仅是本身签名。因此,通过创建这个:
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
version="1.0"
elementFormDefault="qualified">
<xs:import namespace="http://www.w3.org/2000/09/xmldsig#" schemaLocation="xmldsig-core-schema.xsd" />
<xs:element name="root">
<xs:complexType>
<xs:sequence>
<xs:element ref="ds:Signature" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
我现在可以拥有虚拟元素的包含签名。
我意识到 PHP XML 处理相当糟糕,没有一个工具真正工作得那么好。然而,一旦它实际上正确地将事情交给 xmllint,这样做应该没有问题。其他答案建议也添加 XPath,但我想保持 KISS;尽可能少地使用 PHP 库。
通过几百行代码的欺骗,我让它配合并将<Signature>xml 文件的一部分包装到一个<root>元素内的普通测试文件中。
我认为它正在做一些事情来破坏文档中的名称空间。$myDocument->saveXML();失败后调用$myDocument->schemaValidate();会返回一个特殊的结果:
Element 'Signature': This element is not expected. Expected is ( {http://www.w3.org/2000/09/xmldsig#}Signature ).
当 xml 看起来像这样时(我已经添加了格式;实际情况是未格式化的;尽管空格不应该很重要):
<?xml version="1.0"?>
<root>
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
(... omitted crypto ...)
</Signature>
</root>
从我对它所做的阅读来看,该错误应该意味着<Signature> 元素上的命名空间是错误的。但在这里,它明确地明确指定为xmlns错误消息所期望的内容。那么,这里出了什么问题呢?
附录:准备签名进行验证的代码(在任意文档中)看起来像这样。这是一个复杂的版本,我添加了一个“根”元素,而不是直接使用模式,请参阅下面的我的答案,结果证明这是不必要的,尽管这是一个很好的测试,就像在您想要的更复杂的场景中一样要在对 libxml 的一次调用中验证签名的内容,这是一件有效的事情:
MM们