在XML和电子签名的世界中,我是新手。我正在尝试使用xmlseclibs库对XML文档进行签名。
在签署更为复杂的文档时,也许有人遇到过这种方法。在我的XML文档中,该标签没有任何值,因此必须在本节中对文档进行签名:
<ext:UBLExtension>
<ext:ExtensionContent/>
</ext:UBLExtension>
并使用此代码对生成的文档进行签名:
PHP
function sign()
{
// Load the XML to be signed
$doc = new DOMDocument();
// Open XML
if ($doc->load('file.xml'))
{
echo "<p><b>3. XML loaded.</b></p><br/>";
// 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 (!$pfx = file_get_contents('keys/private.pem'))
{
echo "Error: The private key could not be opened!\n";
exit;
}
else
{
/*
If key has a passphrase, set it using
$objKey->passphrase = '<passphrase>';
*/
// Load the private key
$prueba = $objKey->loadKey('keys/private.pem', TRUE);
echo "<p><b>4.Private key has been loaded!</b></p><br/>";
// Sign the XML file
$objDSig->sign($objKey);
}
if (!$pfx = file_get_contents('keys/public.crt'))
{
echo "Error: The public key could not be opened!\n";
exit;
}
else
{
$objDSig->add509Cert(file_get_contents('keys/public.crt'));
echo "<p><b>5. Public key has been loaded.</b></p><br/>";
// Append the signature to the XML
$objDSig->appendSignature($doc->documentElement);
// Save the signed XML
$doc->save('signed.xml');
}
}
else
{
echo "XML could not be opened!";
}
}
结果
<?xml version="1.0" encoding="UTF-8"?>
<fe:Invoice xmlns:fe="http://www.dian.gov.co/contratos/facturaelectronica/v1" xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2" xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2" xmlns:clm54217="urn:un:unece:uncefact:codelist:specification:54217:2001" xmlns:clm66411="urn:un:unece:uncefact:codelist:specification:66411:2001" xmlns:clmIANAMIMEMediaType="urn:un:unece:uncefact:codelist:specification:IANAMIMEMediaType:2003" xmlns:ext="urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2" xmlns:qdt="urn:oasis:names:specification:ubl:schema:xsd:QualifiedDatatypes-2" xmlns:sts="http://www.dian.gov.co/contratos/facturaelectronica/v1/Structure" xmlns:udt="urn:un:unece:uncefact:data:specification:UnqualifiedDataTypesSchemaModule:2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.dian.gov.co/contratos/facturaelectronica/v1 ../xsd/DIAN_UBL.xsd urn:un:unece:uncefact:data:specification:UnqualifiedDataTypesSchemaModule:2 ../../ubl2/common/UnqualifiedDataTypeSchemaModule-2.0.xsd urn:oasis:names:specification:ubl:schema:xsd:QualifiedDatatypes-2 ../../ubl2/common/UBL-QualifiedDatatypes-2.0.xsd">
<ext:UBLExtensions>
<ext:UBLExtension>
<ext:ExtensionContent>
<sts:DianExtensions>
<sts:InvoiceControl>
<sts:InvoiceAuthorization>9000000107023546</sts:InvoiceAuthorization>
<sts:AuthorizationPeriod>
<cbc:StartDate>2018-04-20</cbc:StartDate>
<cbc:EndDate>2026-12-21</cbc:EndDate>
</sts:AuthorizationPeriod>
<sts:AuthorizedInvoices>
<sts:Prefix>PRUE</sts:Prefix>
<sts:From>980000000</sts:From>
<sts:To>985000000</sts:To>
</sts:AuthorizedInvoices>
</sts:InvoiceControl>
<sts:InvoiceSource>
<cbc:IdentificationCode listAgencyID="6" listAgencyName="United Nations Economic Commission for Europe" listSchemeURI="urn:oasis:names:specification:ubl:codelist:gc:CountryIdentificationCode-2.0">CO</cbc:IdentificationCode>
</sts:InvoiceSource>
<sts:SoftwareProvider>
<sts:ProviderID schemeAgencyID="195" schemeAgencyName="CO, DIAN (Direccion de Impuestos y Aduanas Nacionales)">900411455</sts:ProviderID>
<sts:SoftwareID schemeAgencyID="195" schemeAgencyName="CO, DIAN (Direccion de Impuestos y Aduanas Nacionales)">3e82b097-fed0-44e0-8fbc-370fa4bbe718</sts:SoftwareID>
</sts:SoftwareProvider>
<sts:SoftwareSecurityCode schemeAgencyID="195" schemeAgencyName="CO, DIAN (Direccion de Impuestos y Aduanas Nacionales)">8f86d8751e4cb9c9c6107bc3d95f727796ad5401e55859cab92c8e28d380f2f4e6bbfe66ded0f2c22344d23661c86da7</sts:SoftwareSecurityCode>
</sts:DianExtensions>
</ext:ExtensionContent>
</ext:UBLExtension>
<ext:UBLExtension>
<ext:ExtensionContent/>
</ext:UBLExtension>
</ext:UBLExtensions>
<cbc:UBLVersionID>UBL 2.0</cbc:UBLVersionID>
<cbc:ProfileID>DIAN 1.0</cbc:ProfileID>
<cbc:ID>PRUE980000007</cbc:ID>
<cbc:UUID schemeAgencyID="195" schemeAgencyName="CO, DIAN (Direccion de Impuestos y Aduanas Nacionales)">b1f15bbfbd3743c5a43aa60f6e6fe79467719153</cbc:UUID>
<cbc:IssueDate>2018-07-06</cbc:IssueDate>
<cbc:IssueTime>08:04:19</cbc:IssueTime>
<cbc:InvoiceTypeCode listAgencyID="195" listAgencyName="CO, DIAN (Direccion de Impuestos y Aduanas Nacionales)" listSchemeURI="http://www.dian.gov.co/contratos/facturaelectronica/v1/InvoiceType">1</cbc:InvoiceTypeCode>
<cbc:Note>FACTURA DE PRUEBA</cbc:Note>
<cbc:DocumentCurrencyCode>COP</cbc:DocumentCurrencyCode>
<fe:AccountingSupplierParty>
<cbc:AdditionalAccountID>1</cbc:AdditionalAccountID>
<fe:Party>
<cac:PartyIdentification>
<cbc:ID schemeAgencyID="195" schemeAgencyName="CO, DIAN (Direccion de Impuestos y Aduanas Nacionales)" schemeID="31">900411455</cbc:ID>
</cac:PartyIdentification>
<cac:PartyName>
<cbc:Name>EMPRESA DE PRUEBA</cbc:Name>
</cac:PartyName>
<fe:PhysicalLocation>
<fe:Address>
<cbc:Department>BOGOTA, DC</cbc:Department>
<cbc:CitySubdivisionName>BOGOTA, DC</cbc:CitySubdivisionName>
<cbc:CityName>BOGOTA, DC</cbc:CityName>
<cac:AddressLine>
<cbc:Line>DIRECCION DEL CLIENTE</cbc:Line>
</cac:AddressLine>
<cac:Country>
<cbc:IdentificationCode>CO</cbc:IdentificationCode>
</cac:Country>
</fe:Address>
</fe:PhysicalLocation>
<fe:PartyTaxScheme>
<cbc:TaxLevelCode>2</cbc:TaxLevelCode>
<cac:TaxScheme/>
</fe:PartyTaxScheme>
<fe:PartyLegalEntity>
<cbc:RegistrationName>EMPRESA DE PRUEBA</cbc:RegistrationName>
</fe:PartyLegalEntity>
</fe:Party>
</fe:AccountingSupplierParty>
<fe:AccountingCustomerParty>
<cbc:AdditionalAccountID>2</cbc:AdditionalAccountID>
<fe:Party>
<cac:PartyIdentification>
<cbc:ID schemeAgencyID="195" schemeAgencyName="CO, DIAN (Direccion de Impuestos y Aduanas Nacionales)" schemeID="31">830507412</cbc:ID>
</cac:PartyIdentification>
<fe:PhysicalLocation>
<fe:Address>
<cbc:Department>BOGOTA DC</cbc:Department>
<cbc:CitySubdivisionName>BOGOTA</cbc:CitySubdivisionName>
<cbc:CityName>CITY</cbc:CityName>
<cac:AddressLine>
<cbc:Line>DIRECCION</cbc:Line>
</cac:AddressLine>
<cac:Country>
<cbc:IdentificationCode>CO</cbc:IdentificationCode>
</cac:Country>
</fe:Address>
</fe:PhysicalLocation>
<fe:PartyTaxScheme>
<cbc:TaxLevelCode>2</cbc:TaxLevelCode>
<cac:TaxScheme/>
</fe:PartyTaxScheme>
<fe:Person>
<cbc:FirstName>NOMBRE DE EMPRESA</cbc:FirstName>
<cbc:FamilyName>APELLIDO</cbc:FamilyName>
<cbc:MiddleName>NOMBRE</cbc:MiddleName>
</fe:Person>
</fe:Party>
</fe:AccountingCustomerParty>
<fe:TaxTotal>
<cbc:TaxAmount currencyID="COP">0.00</cbc:TaxAmount>
<cbc:TaxEvidenceIndicator>false</cbc:TaxEvidenceIndicator>
<fe:TaxSubtotal>
<cbc:TaxableAmount currencyID="COP">0.00</cbc:TaxableAmount>
<cbc:TaxAmount currencyID="COP">0.00</cbc:TaxAmount>
<cbc:Percent>19.00</cbc:Percent>
<cac:TaxCategory>
<cac:TaxScheme>
<cbc:ID>01</cbc:ID>
</cac:TaxScheme>
</cac:TaxCategory>
</fe:TaxSubtotal>
</fe:TaxTotal>
<fe:LegalMonetaryTotal>
<cbc:LineExtensionAmount currencyID="COP">0.00</cbc:LineExtensionAmount>
<cbc:TaxExclusiveAmount currencyID="COP">0.00</cbc:TaxExclusiveAmount>
<cbc:PayableAmount currencyID="COP">0.00</cbc:PayableAmount>
</fe:LegalMonetaryTotal>
<fe:InvoiceLine>
<cbc:ID>PV00000001</cbc:ID>
<cbc:InvoicedQuantity>1.00</cbc:InvoicedQuantity>
<cbc:LineExtensionAmount currencyID="COP">20.00</cbc:LineExtensionAmount>
<fe:Item>
<cbc:Description>PRODUCTOS VARIOS</cbc:Description>
</fe:Item>
<fe:Price>
<cbc:PriceAmount currencyID="COP">20.00</cbc:PriceAmount>
</fe:Price>
</fe:InvoiceLine>
<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:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
<ds:DigestValue>54iNdi7I+p1PnU0zXuXn89HUdlmkMK3ZoRPHpcaqlOQ=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>
WmZG4QHfKqBsjtoFjP3BNTLoZVV3+Bww/XjH4gXW+6FDm+J/fkGR1wnmt9C3t98nwFlpOAl5gaOyhC0DNHce3MYWobMNc08hcFES9EV13/tqNsXiCrXXwXVzmwY7CDge0wGa9jYVo6CaLj+t9+IbvgNVc6HdRuVeLzojmO+iyBOPTC5w5QWVVdRV4HeBsxYNsIRNIclp34TsljHYy1g7sMjMAm0SMHkduwgXNn96q+GX/v8pjckdxeZwAYKB+yW3US6mr5lzvyWr9e7pQ0LqZBgX3tT9b050rQHBE8t/H4sh665JyBjSafBSV8/NYRgEafhqBvL0SLVwOESvmvg98Q==
</ds:SignatureValue>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>
MIID0DCCArigAwIBAgIJAKRguh9Kxjd4MA0GCSqGSIb3DQEBCwUAMH0xCzAJBgNVBAYTAkJSMQswCQYDVQQIDAJTUDEMMAoGA1UEBwwDUmlvMQ4wDAYDVQQKDAVGSVJNUzEQMA4GA1UECwwHRkVSTUlOTzEQMA4GA1UEAwwHRkVSTUlOTzEfMB0GCSqGSIb3DQEJARYQZ3VpaGdmQGdtYWlsLmNvbTAeFw0xNzA2MjcxMzU2MTBaFw0yNzA2MjUxMzU2MTBaMH0xCzAJBgNVBAYTAkJSMQswCQYDVQQIDAJTUDEMMAoGA1UEBwwDUmlvMQ4wDAYDVQQKDAVGSVJNUzEQMA4GA1UECwwHRkVSTUlOTzEQMA4GA1UEAwwHRkVSTUlOTzEfMB0GCSqGSIb3DQEJARYQZ3VpaGdmQGdtYWlsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMxoXF67vmncyWwoJ3h3MK/foNuP7uvmSv1aiLgLgc0dH1SGQWqM33ocloBtHWs1QFpU7TGVVmyS9bf47fdVxa/75MLV7mSMdWDiK0cIBDwQFAhSu+ipQ3kpTJSmJWiXKd16Xtrxq9XtwdwC25kVMEws7ggZoMHzrmmKPtTUwvbaqy0xXw5IFFt/r9L6dzOQcfwdNhQACLlO7cEGdJQXbwvICn3VN6M5nwTXec6vlalppX3kmjTiVJURKi64hmih84Hf12loDbtyiuxYcc8rK0ceUAxhFtmekwDAcV+EAr7sXUrNDKZErpK6HZ/QDrhZVeXzVuKsHyRmYYn0RUGzNqMCAwEAAaNTMFEwHQYDVR0OBBYEFONdUpNRKv8PN9499PBw0zVD+025MB8GA1UdIwQYMBaAFONdUpNRKv8PN9499PBw0zVD+025MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAK5OwB/iVWDHEtGKkQCmMqXOcsVz7PvYJIaGtSUq1X6CWDGZoEtyCkfoMC/FYPz6V8JgSwDFENyw4VaH0HWggwz2vCDEA5Mg3iOobRG98gk9lLolk7DjXsfvHkCYI6ncvz7eIdawwzddhSaj+2LSUCB8UNONYsl6CPdioNGUVJix9QDSrf5gcMkWsWa8Sg3f6vjVCWdgl5mOnJeeXapxvg1VEjnmOLDb25hNKO44i4jVNKN4+jSKCcECCKw7fu7uD4PyVbTCZi037svPzMZ6dG7wlWLBWOopbj7G2sAMMVwCoHAJBoEV8lArRq4n1ZW3DAW9NQ8+OQcJMXWGWQhSmJk=
</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</ds:Signature>
</fe:Invoice>
如您所见,签名出现在文档的末尾,但是我需要在上述标签内生成签名。有人遇到这种不便吗?
答案 0 :(得分:3)
您的代码说:
$objDSig->appendSignature($doc->documentElement);
这显然将签名附加到文档元素上。如果您想将其附加到其他内容,建议您将其指定为参数。
一种执行此操作的方法可能是XPath查询,以查找要附加到其上的类型的空元素:
$xpath = new DomXPath($doc);
$nodes = $xpath->query("//ext:ExtensionContent[not(normalize-space())]");
if ($nodes->count()) {
$objDSig->appendSignature($nodes[0]);
}