/** * Método que indica si la firma del DTE es o no válida * @return =true si la firma del DTE es válida, =null si no se pudo determinar * @warning No se está verificando el valor del DigestValue del documento (sólo la firma de ese DigestValue) * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) * @version 2015-09-08 */ public function checkFirma() { if (!$this->xml) { return null; } // obtener firma $Signature = $this->xml->documentElement->getElementsByTagName('Signature')->item(0); // preparar documento a validar $D = $this->xml->documentElement->getElementsByTagName('Documento')->item(0); $Documento = new \sasco\LibreDTE\XML(); $Documento->loadXML($D->C14N()); $Documento->documentElement->removeAttributeNS('http://www.w3.org/2001/XMLSchema-instance', 'xsi'); $Documento->documentElement->removeAttributeNS('http://www.sii.cl/SiiDte', ''); $SignedInfo = new \sasco\LibreDTE\XML(); $SignedInfo->loadXML($Signature->getElementsByTagName('SignedInfo')->item(0)->C14N()); $SignedInfo->documentElement->removeAttributeNS('http://www.w3.org/2001/XMLSchema-instance', 'xsi'); $DigestValue = $Signature->getElementsByTagName('DigestValue')->item(0)->nodeValue; $SignatureValue = $Signature->getElementsByTagName('SignatureValue')->item(0)->nodeValue; $X509Certificate = $Signature->getElementsByTagName('X509Certificate')->item(0)->nodeValue; $X509Certificate = '-----BEGIN CERTIFICATE-----' . "\n" . wordwrap(trim($X509Certificate), 64, "\n", true) . "\n" . '-----END CERTIFICATE----- '; $valid = openssl_verify($SignedInfo->C14N(), base64_decode($SignatureValue), $X509Certificate) === 1 ? true : false; return $valid; //return $valid and $DigestValue===base64_encode(sha1($Documento->C14N(), true)); }
$Documento->loadXML($D->C14N()); $Documento->documentElement->removeAttributeNS('http://www.w3.org/2001/XMLSchema-instance', 'xsi'); $Documento->documentElement->removeAttributeNS('http://www.sii.cl/SiiDte', ''); $SignedInfo = new \sasco\LibreDTE\XML(); $SignedInfo->loadXML($Signatures->item($i)->getElementsByTagName('SignedInfo')->item(0)->C14N()); $SignedInfo->documentElement->removeAttributeNS('http://www.w3.org/2001/XMLSchema-instance', 'xsi'); $DigestValue = $Signatures->item($i)->getElementsByTagName('DigestValue')->item(0)->nodeValue; $SignatureValue = $Signatures->item($i)->getElementsByTagName('SignatureValue')->item(0)->nodeValue; $X509Certificate = $Signatures->item($i)->getElementsByTagName('X509Certificate')->item(0)->nodeValue; $X509Certificate = '-----BEGIN CERTIFICATE-----' . "\n" . wordwrap(trim($X509Certificate), 64, "\n", true) . "\n" . '-----END CERTIFICATE----- '; //$pub_key = openssl_pkey_get_details(openssl_pkey_get_public($X509Certificate))['key']; /*$pub_key = getPublicKey( $Signatures->item($i)->getElementsByTagName('Modulus')->item(0)->nodeValue, $Signatures->item($i)->getElementsByTagName('Exponent')->item(0)->nodeValue );*/ $valid = openssl_verify($SignedInfo->C14N(), base64_decode($SignatureValue), $X509Certificate) === 1 ? true : false; echo 'Verificando Documento:', "\n"; echo ' Digest Documento: ', base64_encode(sha1($Documento->C14N(), true)), "\n"; echo ' Digest SignedInfo: ', base64_encode(sha1($SignedInfo->C14N(), true)), "\n"; echo ' Digest Documento valido: ', $DigestValue === base64_encode(sha1($Documento->C14N(), true)) ? 'si' : 'no', "\n"; echo ' Digest SignedInfo valido: ', $valid ? 'si' : 'no', "\n\n"; $i++; } // si hubo errores mostrar foreach (\sasco\LibreDTE\Log::readAll() as $error) { echo $error, "\n"; } // para el XML de ejemplo del SII la clave pública obtenida desde el certificado // no sirvió para validar las firmas del documento, se probó obteniendo la clave // desde el módulo y exponente y ahí si funcionó. Sin embargo para otros DTEs // revisados (generados por otras bibliotecas y por LibreDTE) el certificado