josemmo / Facturae-PHP

📝 Genera, firma, envía y recibe facturas electrónicas sin necesidad de ninguna librería adicional
https://josemmo.github.io/Facturae-PHP/
MIT License
219 stars 98 forks source link

KeyPairReader debería alimentarse con el contenido, no con la ruta del certificado #105

Closed Eseperio closed 1 year ago

Eseperio commented 2 years ago

Actualmente el lector de claves está vinculado a que los certificados estén almacenados en disco, lo que impide realizar implementaciones más seguras que no requieran la presencia de un archivo físico y que pueden obtener el contenido del certificado desde, entre otros:

El cambio hay que realizarlo en KeyPairReader. Quizás lo mejor sería implementar métodos para definir la clave privada y la pública de forma independiente y no en el constructor. Así, la construcción del lector de claves podría ser de la siguiente forma:

(new KeyPairReader())->setPrivateKey($pathOrContent, bool $isFile)->setPublicKey($pathOrContent, bool $isFile)

Los métodos setPrivateKey() y setPublicKey() aceptan dos argumentos. El primero, el contenido o path al archivo, el segundo indica el tipo de variable provisto. Una forma más sólida podría ser establecer un método para cada acción. Por ejemplo: setPrivateKeyFromStream() y setPrivateKeyFromFile().

Existen varios supuestos en los que disponer de un archivo local es un problema, ya que una parada repentina del ejecutable de PHP puede dar lugar a que no se eliminen archivos temporales y queden al descubierto en escenarios en los que no deberían encontrarse y un atacante podría hacerse con ellos.

Aprovecho para dar las gracias por esta librería 👏 y apoyar el código abierto

juanadamuzsimj commented 2 years ago

Yo no uso certificados físicos como tal, se puede añadir desde un formulario en la web de esta forma:

$factura->sign($request->file("certificado_formulario"));

En laravel por ejemplo puedes usar la entidad File creada con el binario de google drive para hacerlo funcionar.

Eseperio commented 2 years ago

Pero eso solo sucede en Laravel. En otros frameworks o en el caso de los microframeworks no existe un método que automáticamente convierta el binario, sin embargo sí hay métodos para trabajar con el stream o con el contenido. IMHO Lo mejor sería que fuera compatible con sistemas agnósticos, como Flysystem, que no dependen de un framework en particular.

josemmo commented 2 years ago

Hola @Eseperio,

He implementado los siguientes cambios para acomodar la funcionalidad:

  1. El método Facturae::sign($storeOrCertificate, $privateKey=null, $passphrase='') ahora admite rutas, bytes con el contenido de los ficheros e instancias/resources de OpenSSL. Se mantiene el mismo nombre y orden de los parámetros por retro-compatibilidad.
  2. Se añaden los métodos FacturaeSigner::addCertificate($certificate), FacturaeSigner::setPrivateKey($privateKey, $passphrase='') y FacturaeSigner::loadPkcs12($certificateStore, $passphrase).

Lo mismo para las clases FaceClient, FaceB2bClient y CustomFaceClient, y sus constructores.

Tienes la nueva documentación en este enlace. Puedes probarlo ya mismo descargando la última snapshot de la librería con Composer:

composer require josemmo/facturae-php:dev-develop