Generar Sello CFDI v3.3 en PHP (sin .key.pem)

Hola tyros, yo de nuevo!

Hace apenas unas dos horas que logré generar el Sello Digital del XML sin necesidad de convertir el archivo .KEY en .PEM. Tardé varios días leyendo y leyendo la documentación OpenSSL de PHP tratando de Generar el Sello, sin éxito. Ayer, como a eso de las 23:50 me dí por vencido y convertí el archivo .KEY a .PEM con la siguiente instrucción:


openssl pkcs8 -inform DER -in /Users/gabriel.castillo/Downloads/includes-sat/ACO560518KW7-20001000000300005692.key -passin pass:12345678a -out /Users/gabriel.castillo/Downloads/includes-sat/ACO560518KW7-20001000000300005692.key.pem


Luego de eso, fué fácil generar el sello con el siguiente código PHP:

//Sellar
$fileKey = Principal::$AppPath . "docs/sat/ACO560518KW7-20001000000300005692.key.pem"; // Ruta al archivo key
$private = openssl_pkey_get_private(file_get_contents($fileKey));
$sig = "";
openssl_sign($this->CadenaOriginal, $sig, $private, OPENSSL_ALGO_SHA256);
$sello = base64_encode($sig);
$this->Comprobante->Sello = $sello;


Pero eso no es lo que yo quería!


En la aplicación que estoy creando, mis clientes deben hacer el mínimo esfuerzo para generar sus facturas electrónicas. Mi aplicación debe poder configurarse para que el usuario utilice los archivos (.cer y .key) y contraseña que el SAT le entregó. Así que seguí intentando todo el día de hoy, desde las 07:50 que llegué al trabajo, sin parar, mas que para almorzar, como a eso de las 11:00.

Dí con una librería llamada PHP Secure Communications Library. Luego de leer la documentación varias veces, y con lo que ya había leido de openssl, logré descifrar el misterio. Todo el esfuerzo se reduce al siguiente código:



//Sellar
$fileKey = Principal::$AppPath . "docs/sat/ACO560518KW7-20001000000300005692.key"; // Ruta al archivo key
$rsa = new RSA();
$rsa->setPassword("12345678a");//Clave 
$rsa->load(file_get_contents($fileKey));
$private = openssl_pkey_get_private($rsa->getPrivateKey(), "12345678a");//Otra vez la clave
$sig = "";
openssl_sign($this->CadenaOriginal, $sig, $private, OPENSSL_ALGO_SHA256);
$sello = base64_encode($sig);
$this->Comprobante->Sello = $sello;


Nota Importante: Es un tanto complicado hacer funcionar esta librería. Ese trabajo te lo dejo a ti. La semana entrante haré una publicación sobre ese tema.

Tip: Debes descargar, además, otra librería llamada: "Constant-Time Encoding"

Aquí les dejo una imagen de mis archivos (Usando NetBans):



Si te ha sido de utilidad este tutorial, haz G+, me ayudarás a seguir publicando, gracias.

4 comentarios:

  1. Respuestas
    1. Es un string que se construye con la ayuda del CFDI ya completo, dicha cadena representa al CFDI, su contenido de forma muy resumida y es indispensable ya que con esta cadena origina se construye el sello.

      Eliminar
  2. con esto puedo generar el archivo pem de la llave para la descarga masiva del sat?

    ResponderEliminar