XML 使用 xmldsig (RobRichards\XMLSecLibs) 签名的文件,但 XSD 验证失败
XML file signed with xmldsig (RobRichards\XMLSecLibs) but XSD validation fails
我安装了 RobRichards\XMLSecLibs PHP 库来签署我的 XML 文件。这些文件必须根据我们拥有的 XSD 文件生成
...
<xs:element name="Lote">
<xs:complexType>
<xs:sequence>
<xs:element name="Cabecera" type="LoteCabecera"/>
<xs:element name="Registro" type="RegistroCJD" minOccurs="0" maxOccurs="unbounded"/>
<xs:any namespace="http://www.w3.org/2000/09/xmldsig#" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
</xs:element>
...
所以,在我的 PHP 代码中,我这样写:
// Create a new Security object
$objDSig = new XMLSecurityDSig();
// Use the c14n exclusive canonicalization
$objDSig->setCanonicalMethod(XMLSecurityDSig::EXC_C14N);
// Sign using SHA-256
$objDSig->addReference(
$doc,
XMLSecurityDSig::SHA256,
array('http://www.w3.org/2000/09/xmldsig#enveloped-signature')
);
// Create a new (private) Security key
$objKey = new XMLSecurityKey(XMLSecurityKey::RSA_SHA256, array('type'=>'private'));
/*
If key has a passphrase, set it using
$objKey->passphrase = '<passphrase>';
*/
// Load the private key
$objKey->loadKey($key_path, TRUE);
// Sign the XML file
$objDSig->sign($objKey);
// Add the associated public key to the signature
$objDSig->add509Cert(file_get_contents($certificate_path));
// Append the signature to the XML
$objDSig->appendSignature($doc->documentElement);
生成的 XML 文件是:
<?xml version="1.0" encoding="UTF-8"?>
<ns1:Lote xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ns1="http://coljuegos.gov.co/Online/data/v1.0" xsi:schemaLocation="http://coljuegos.gov.co/Online/data/v1.0 copia_lavoro.xsd">
<ns1:Cabecera>
</ns1:Cabecera>
<ns1:Registro>
</ns1:Registro>
<ns1:Registro>
</ns1:Registro>
...
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
<ds:Reference>
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue>+LkHWYVOxJ48k/2TPizuFoHINBc=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>C/2buRFmei...66OpXg==</ds:SignatureValue>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>MIID9TCCAt2...gR0Nf1</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</ds:Signature>
</ns1:Lote>
当我尝试验证此文件时,出现以下错误:
XML error "Element '{http://www.w3.org/2000/09/xmldsig#}Signature': No matching global element declaration available, but demanded by the strict wildcard." [2] (Code 1845)
我该如何解决这个问题?我可以在我的代码中更改某些内容以使 XML 有效吗?因为,这个XSD是我从外部权威那里得到的,应该是碰不得的
我在另一个问题上找到了解决方案:
基本上,我的验证器无法到达远程 XSD,所以我要解决这个问题的唯一方法是下载那个 XSD 文件的副本并修改 XSD 文件以便在本地目录中查找模式定义,而不是在线查找。
我安装了 RobRichards\XMLSecLibs PHP 库来签署我的 XML 文件。这些文件必须根据我们拥有的 XSD 文件生成
...
<xs:element name="Lote">
<xs:complexType>
<xs:sequence>
<xs:element name="Cabecera" type="LoteCabecera"/>
<xs:element name="Registro" type="RegistroCJD" minOccurs="0" maxOccurs="unbounded"/>
<xs:any namespace="http://www.w3.org/2000/09/xmldsig#" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
</xs:element>
...
所以,在我的 PHP 代码中,我这样写:
// Create a new Security object
$objDSig = new XMLSecurityDSig();
// Use the c14n exclusive canonicalization
$objDSig->setCanonicalMethod(XMLSecurityDSig::EXC_C14N);
// Sign using SHA-256
$objDSig->addReference(
$doc,
XMLSecurityDSig::SHA256,
array('http://www.w3.org/2000/09/xmldsig#enveloped-signature')
);
// Create a new (private) Security key
$objKey = new XMLSecurityKey(XMLSecurityKey::RSA_SHA256, array('type'=>'private'));
/*
If key has a passphrase, set it using
$objKey->passphrase = '<passphrase>';
*/
// Load the private key
$objKey->loadKey($key_path, TRUE);
// Sign the XML file
$objDSig->sign($objKey);
// Add the associated public key to the signature
$objDSig->add509Cert(file_get_contents($certificate_path));
// Append the signature to the XML
$objDSig->appendSignature($doc->documentElement);
生成的 XML 文件是:
<?xml version="1.0" encoding="UTF-8"?>
<ns1:Lote xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ns1="http://coljuegos.gov.co/Online/data/v1.0" xsi:schemaLocation="http://coljuegos.gov.co/Online/data/v1.0 copia_lavoro.xsd">
<ns1:Cabecera>
</ns1:Cabecera>
<ns1:Registro>
</ns1:Registro>
<ns1:Registro>
</ns1:Registro>
...
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
<ds:Reference>
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue>+LkHWYVOxJ48k/2TPizuFoHINBc=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>C/2buRFmei...66OpXg==</ds:SignatureValue>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>MIID9TCCAt2...gR0Nf1</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</ds:Signature>
</ns1:Lote>
当我尝试验证此文件时,出现以下错误:
XML error "Element '{http://www.w3.org/2000/09/xmldsig#}Signature': No matching global element declaration available, but demanded by the strict wildcard." [2] (Code 1845)
我该如何解决这个问题?我可以在我的代码中更改某些内容以使 XML 有效吗?因为,这个XSD是我从外部权威那里得到的,应该是碰不得的
我在另一个问题上找到了解决方案:
基本上,我的验证器无法到达远程 XSD,所以我要解决这个问题的唯一方法是下载那个 XSD 文件的副本并修改 XSD 文件以便在本地目录中查找模式定义,而不是在线查找。