Para verificar mis avances y llegar al firmado correcto me estoy respaldando en este validador https://tools.chilkat.io/xmlDsigVerify.cshtml y he abierto un repositorio donde comparto mi código en PHP hasta donde lo llevo de avanzado: https://gitlab.com/siegroupmx/xmlsinger
Voy al asunto....
>> Como se generan los DigestValue para las Referencias dentro de SignedInfo ??
Mi procedimiento para esto es simplemente tomar el Nodo (por ejemplo KeyInfo) canonizado a C14N y después lo paso por un Algoritmo (sha1, sha256, etc...), después lo convierto a Base64 y el resultado lo coloco sobre DigestValue..... mi proceso es correcto ???
Ejemplo simple y rápido:
Citar
Sobra mencionar que en el ejemplo de abajo estoy omitiendo el proceso donde creo la etiqueta Singature y sus elementos internos.
Código:
<?php
const XMLDSIGNS= 'http://www.w3.org/2000/09/xmldsig#';
$xmlSigned= 'mixml.xml';
$xml= new DOMDocument();
$xml->preserveWhiteSpace= FALSE;
$xml->formatOutput= true;
$xml->load($xmlSigned);
$xp= new DOMXPath($xml);
$xp->registerNamespace('secdsig', self::XMLDSIGNS);
$keyinfo= $xp->query('.//secdsig:Signature/secdsig:KeyInfo');
$hash= hash("sha256", $keyinfo->item(0)->C14N(), true);
$base64= base64_encode($hash);
echo $base64; # imprime LcOJdpKtT7sgjbblkmGyYrSUslXMlw0TyCc8SOUBJQM=
?>
Y en el XML:
Código:
<ds:Reference URI="#xmldsig-a837805e-9235-a8bb-7ab4-688282608259-keyinfo">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
<ds:DigestValue>LcOJdpKtT7sgjbblkmGyYrSUslXMlw0TyCc8SOUBJQM=</ds:DigestValue>
</ds:Reference>
....
....
<ds:KeyInfo Id="xmldsig-a837805e-9235-a8bb-7ab4-688282608259-keyinfo">
... todas las etiquetas internas....
</ds:KeyInfo>
>> Como se genera el SignatureValue ???
En mi procedimiento tomo el nodo de SignedInfo canonizado a C14N, los firmo con openssl_sign() y el resultado lo convierto a Base64 y coloco dentro de SignatureValue. Es correcto esto que hago??
Ejemplo rápido:
Código:
<?php
const XMLDSIGNS= 'http://www.w3.org/2000/09/xmldsig#';
$xmlOut= 'mixml.xml';
$xml= new DOMDocument();
$xml->preserveWhiteSpace= FALSE;
$xml->formatOutput= true;
$xml->load($xmlOut);
$xp= new DOMXPath($xml);
$xp->registerNamespace('secdsig', self::XMLDSIGNS);
$si= $xp->query('.//secdsig:Signature/secdsig:SignedInfo'); # signedinfo
openssl_sign($si->item(0)->C14N(), $signature, $this->privateKey, OPENSSL_ALGO_SHA256);
$dato= base64_encode($signature); # esto va en SignatureValue
$sv= $xp->query('.//secdsig:Signature/secdsig:SignatureValue'); # signaturevalue
$sv->item(0)->nodeValue= $dato;
?>
Y el SignatureValue dentro del XML esta:
Código:
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Id="xmldsig-bfcdf0f0-2655-b952-9c85-77493d9f241f">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
<ds:Reference Id="xmldsig-bfcdf0f0-2655-b952-9c85-77493d9f241f-ref0" URI="">
<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>KWOvQ3tWaygQXkkvfI6s9UO0azjQgc0YGp9JANDXYis=</ds:DigestValue>
</ds:Reference>
<ds:Reference URI="#xmldsig-a837805e-9235-a8bb-7ab4-688282608259-keyinfo">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
<ds:DigestValue>LcOJdpKtT7sgjbblkmGyYrSUslXMlw0TyCc8SOUBJQM=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue Id="xmldsig-bfcdf0f0-2655-b952-9c85-77493d9f241f-sigvalue">
ZGcaOhKK3Uzp64T11LHFKAy1eOkKeMpvKNNAeBFapJxbyCr8iQDkGQ2B+VQFYLWZnDneK6Cuc6uDtUw14q4mlYoarlIRVvLlsiQK0OmFrdWEM4sd62WPP2N0GpUOOh/I/BjggsqNV1OOWG2xutZNbdh4maJzxEbcLuU8SrdPuU6q38bTAw/QJyQ5F4eiRr++28sR9G3yV0nTzkZXR5QNPScdrbwrMtH/vkBx0FfV8ErzubwKyPdvQSbugmLMk8hd7Rnn5SRg8JaxQhCC5TDPC3KOmj5Nh1zHmzATZaRAbP0XNoYsDLnQtmteo5/RL2NHGvHYbP0teUF43nHXu/KAVg==
</ds:SignatureValue>
>> CONCLUSIÓN
El validador me dice que la Firma esta mal, y que también esta mal el firmado de las referencias
Enlace a un ejemplo https://gitlab.com/siegroupmx/xmlsinger/blob/master/examples/ejemplo_out.xml
Certificado: https://gitlab.com/siegroupmx/xmlsinger/blob/master/tmp/certificado.pem
Firma: https://gitlab.com/siegroupmx/xmlsinger/blob/master/tmp/firma.pem
Clave: persona_juridica_pruebas