Ejemplo n.º 1
0
function valida_sello()
{
    /*
     * Todos los archivos que se requieren para generar la cadena original
     * fueron descargados del portal del SAT pero los tengo localmente
     * almacenados en mi maquina para que el proceso sea mas rapido.
     *
     * Todos los archivos estan modificacion por el numero de version 2 a 1,
     * para que no mande warning PHP
     *
     * */
    global $data, $xml;
    $xsl = new DOMDocument();
    if ($data['tipo'] == "retenciones") {
        switch ($data['version']) {
            case "1.0":
                $xsl->load('xslt/retenciones.xslt');
                $algo = OPENSSL_ALGO_SHA1;
                break;
            default:
                echo "version incorrecta " . $data['tipo'] . " " . $data['version'] . "\n";
                break;
        }
    } else {
        switch ($data['version']) {
            case "2.0":
                $xsl->load('xslt/cadenaoriginal_2_0.xslt');
                if (substr($data['fecha'], 0, 4) < 2011) {
                    echo "md5 \n";
                    $algo = OPENSSL_ALGO_MD5;
                } else {
                    echo "sha1 \n";
                    $algo = OPENSSL_ALGO_SHA1;
                }
                break;
            case "2.2":
                echo "2.2\n";
                $xsl->load('xslt/cadenaoriginal_2_2.xslt');
                echo "sha1 \n";
                $algo = OPENSSL_ALGO_SHA1;
                break;
            case "3.0":
                $xsl->load('xslt/cadenaoriginal_3_0.xslt');
                if (substr($data['fecha'], 0, 4) < 2011) {
                    echo "md5 \n";
                    $algo = OPENSSL_ALGO_MD5;
                } else {
                    echo "sha1 \n";
                    $algo = OPENSSL_ALGO_SHA1;
                }
                break;
            case "3.2":
                echo "3.2\n";
                $xsl->load('xslt/cadenaoriginal_3_2.xslt');
                echo "sha1 \n";
                $algo = OPENSSL_ALGO_SHA1;
                break;
            default:
                echo "version incorrecta " . $data['tipo'] . " " . $data['version'] . "\n";
                break;
        }
    }
    $proc = new XSLTProcessor();
    $proc->importStyleSheet($xsl);
    $cadena = $proc->transformToXML($xml);
    echo "Cadena Original<br><p align=left>{$cadena}</p><br>";
    if ($algo == OPENSSL_ALGO_SHA1) {
        $sha1 = sha1($cadena);
        echo "hash sha1={$sha1}<br>";
    } else {
        $md5 = md5($cadena);
        echo "hash md5={$md5}<br>";
    }
    if (!mb_check_encoding($cadena, "utf-8")) {
        echo "<h3>Error no esta en UTF-8!</h3>";
    }
    /* 
     * El domicilio es opcional, pero si no lo ponemos el xslt del SAT genera 
     * doble pip en el pais ..., dice que el sello es correcto pero los PACs 
     * que validan bien lo rechazan ... 
     * */
    $doble = preg_match('/.\\|\\|./', $cadena);
    if ($doble === 1) {
        echo "<h3><font color=red>La cadena tiene doble pipes en medio ...</font></h3>";
    }
    // Primer certificado (o unico) del emisor
    // Los demas certificados es del PAC, Timbre, etc.
    $pem = sizeof($data['cert']) <= 1 ? $data['cert'] : $data['cert'][0];
    $pem = eregi_replace("[\n|\r|\n\r]", '', $pem);
    $pem = preg_replace('/\\s\\s+/', '', $pem);
    // Si no incluye el certificado bajarlo del FTP del sat ....
    if (strlen($pem) == 0) {
        echo "No incluye certificado interno, descargarlo del FTP del sat ...<br>";
        $pem = get_sat_cert($data['no_cert']);
    }
    $cert = "-----BEGIN CERTIFICATE-----\n" . chunk_split($pem, 64) . "-----END CERTIFICATE-----\n";
    $pubkeyid = openssl_get_publickey(openssl_x509_read($cert));
    if (!$pubkeyid) {
        echo "Certificado interno Incorrecto, descargarlo del FTP del sat ...<br>";
        $pem = get_sat_cert($data['no_cert']);
        $cert = "-----BEGIN CERTIFICATE-----\n" . chunk_split($pem, 64) . "-----END CERTIFICATE-----\n";
        $pubkeyid = openssl_get_publickey(openssl_x509_read($cert));
    }
    valida_ca($pubkeyid);
    $ok = openssl_verify($cadena, base64_decode($data['sell']), $pubkeyid, $algo);
    if ($ok == 1) {
        echo "<h3>Sello ok</h3>";
    } else {
        echo "<h3>Sello incorrecto</h3>";
        while ($msg = openssl_error_string()) {
            echo $msg . "\n";
        }
    }
    openssl_free_key($pubkeyid);
    echo "<hr>";
    $paso = openssl_x509_parse($cert);
    $serial = convierte($paso['serialNumber']);
    if ($serial != $data['no_cert']) {
        echo "Serie reportada " . $data['no_cert'] . " serie usada {$serial}<br>";
    }
}
Ejemplo n.º 2
0
function checa_sello($texto, $xslt, $nodo)
{
    $xml = new DOMDocument("1.0", "UTF-8");
    $xml->loadXML($texto);
    $root = $xml->getElementsByTagName($nodo)->item(0);
    $sello = $root->getAttribute("Sello");
    $no_cert = $root->getAttribute("noCertificado");
    $cert = $root->getAttribute("Certificado");
    if ($sello == "" && $no_cert == "" && $cert == "") {
        echo "No tiene datos de sello, NO valida<br>";
        return;
    }
    if ($sello == "" || $no_cert == "" && $cert == "") {
        echo "<h3>No tiene datos de sello completo, ignorando</h3>";
        return;
    }
    $paso = new DOMDocument("1.0", "UTF-8");
    $paso->loadXML($texto);
    $xsl = new DOMDocument("1.0", "UTF-8");
    $xsl->load($xslt);
    $proc = new XSLTProcessor();
    $proc->importStyleSheet($xsl);
    $cadena_original = $proc->transformToXML($paso);
    $pem = "-----BEGIN CERTIFICATE-----\n" . chunk_split($cert, 64) . "-----END CERTIFICATE-----\n";
    $paso = openssl_x509_parse($pem);
    $serial = convierte($paso['serialNumber']);
    if ($serial != $no_cert) {
        echo "Numero de certificado reportado {$no_cert} serie del certificado {$serial}<br>";
    }
    $pubkeyid = openssl_get_publickey(openssl_x509_read($pem));
    if ($pubkeyid === FALSE) {
        echo "<h3>El atributo 'Certificado' no contiene un certificado x509 valido </h3>";
        return;
    }
    $algo = OPENSSL_ALGO_SHA1;
    $ok = openssl_verify($cadena_original, base64_decode($sello), $pubkeyid, $algo);
    if ($ok == 1) {
        echo "<h3>Sello ok, sha1</h3>";
    } else {
        $algo = OPENSSL_ALGO_SHA256;
        $ok = openssl_verify($cadena_original, base64_decode($sello), $pubkeyid, $algo);
        if ($ok == 1) {
            echo "<h3>Sello ok, sha256</h3>";
            echo "<h3>OJO el SAT no lo acepta, usa SHA1</h3>";
        } else {
            echo "<h3>Sello incorrecto, ni sha1 ni sha256</h3>";
            echo "{$cadena_original}<br>";
            while ($msg = openssl_error_string()) {
                echo $msg . "\n";
            }
        }
    }
    openssl_free_key($pubkeyid);
}