Firma electrónica
Aunque es posible exportar las facturas sin firmarlas, es un paso obligatorio para prácticamente cualquier trámite relacionado con la Administración Pública. Para firmar facturas se necesita un certificado electrónico (generalmente expedido por la FNMT) del que extraer su clave pública y su clave privada.
Firmado con PKCS#12 (recomendado)
Desde la versión 1.0.5 de Facturae-PHP ya es posible cargar un banco de certificados desde un archivo .pfx
o .p12
:
$fac->sign("certificado.pfx", null, "passphrase");
También se pueden pasar como parámetro los bytes del banco PKCS#12:
$encryptedStore = file_get_contents("certificado.pfx");
$fac->sign($encryptedStore, null, "passphrase");
NOTA
Al utilizar un banco PKCS#12, Facturae-PHP incluirá la cadena completa de certificados en la factura al firmarla.
Aunque en la mayoría de los casos esto no supone ninguna diferencia con respecto a firmar desde ficheros PEM, los validadores presentan problemas con algunos certificados expedidos recientemente por la FNMT. Dicho problema se soluciona cuando se incluyen los certificados raíz e intermedios de la Entidad de Certificación, por lo que es recomendable usar este método de firma con Facturae-PHP.
NOTA
A partir de OpenSSL v3.0.0, algunos algoritmos de digest como RC4 fueron marcados como obsoletos. Esto puede suponer un problema para bancos de certificados exportados desde el Gestor de Certificados de Windows. Se recomienda validar estos ficheros antes de usarlos en la librería:
openssl pkcs12 -in certificado.pfx -info -nokeys -nocerts
Firmado con clave pública y privada X.509
Si se tiene la clave pública (un certificado) y la clave privada en archivos independientes, se debe utilizar este método con los siguientes argumentos:
$fac->sign("clave_publica.pem", "clave_privada.pem", "passphrase");
También se pueden pasar como parámetros los bytes de ambos ficheros en vez de sus rutas, o instancias de OpenSSLCertificate
y OpenSSLAsymmetricKey
, respectivamente:
$publicKey = openssl_x509_read("clave_publica.pem");
$encryptedPrivateKey = file_get_contents("clave_privada.pem");
$fac->sign($publicKey, $encryptedPrivateKey, "passphrase");
Este método de firma no añade la cadena completa de certificados a la factura y, por tanto, no se recomienda.
NOTA
Los siguientes comandos permiten extraer el certificado (clave pública) y la clave privada de un archivo PFX:
openssl pkcs12 -in certificado_de_entrada.pfx -clcerts -nokeys -out clave_publica.pem openssl pkcs12 -in certificado_de_entrada.pfx -nocerts -out clave_privada.pem
Fecha de la firma
Por defecto, al firmar una factura se utilizan la fecha y hora actuales como sello de tiempo. Si se quiere indicar otro valor, se debe utilizar el siguiente método:
$fac->setSigningTime("2017-01-01T12:34:56+02:00");
NOTA
Cambiar manualmente la fecha de la firma puede entrar en conflicto con el sellado de tiempo.