ctt-gob-es / clienteafirma

Cliente @firma
http://administracionelectronica.gob.es/ctt/clienteafirma
248 stars 120 forks source link

No puedo crear un PDF correcto desde la cadena Base64 devuelta por el clienteFirma #301

Closed manucera closed 1 year ago

manucera commented 1 year ago

El objetivo de la tarea en la que tengo este problema es firmar un archivo PDF que se descarga por el cliente @firma desde el servidor (ASP.NET) indicando la localización relativa en el parámetro "url" de la función downloadRemoteData. Cuando esta función se ejecuta, si ha tenido éxito llama a otra en la que incluyo la ejecución de la función MiniApplet.sign con el parámetro de los datos a firmar que devuelve la anterior. La operación se realiza correctamente y llama a otra función en la que mediante javascript realizo un envío ajax a la página actual con un parámetro que contiene la firma, es decir, el valor devuelto en la anterior función y que lo necesito en el servidor para que una vez procesado se guarde el archivo PDF en una localización especificada. Todo funciona correctamente y el PDF se guarda donde debe. El problema es que no se puede abrir porque no tiene un formato PDF correcto o está corrupto (eso es lo que dan como mensaje al cargarlo en los distintos programas). Examinando las cadenas resultantes en cada punto del proceso en la parte cliente y en la de servidor la conclusión es que la cadena de caracteres en Base64 que tomo en el cliente ya tiene unas características que pueden ser las que producen ese resultado. Esto lo baso en que la cadena final que termina en el servidor es idéntica a la que se envió desde el cliente. Lo que estoy haciendo con la cadena Base64 antes de enviarla al servidor es lo siguiente:

  1. La incluyo como parámetro en una cadena de consulta o URL y la codifico con EncodeURIComponente para que no dé problemas en el envío al servidor mediante Ajax (con Feth).
  2. En el servidor se recibe correctamente y la decodifico con las utilidades de C#.
  3. Convierto la cadena en texto plano UTF8 con las funciones y bibliotecas adecuadas en c#.
  4. La cadena resultante la convierto en una matriz de bytes.
  5. Creo un nuevo archivo PDF con la biblioteca iText o con System utilizando esa matriz de bytes.

Las cadenas de los pasos 1 y tras ejecutar el 3 son coincidentes, luego la transferencia desde el cliente ha sido correcta. El archivo PDF se crea pero no se puede abrir por las razones que anteriormente dije.

También he probado a convertir la cadena recibida en Base64 en cadena normal usando varias codificaciones (UTF-8, UNICODE, etc.) y con ninguna funcionó. De igual modo y en el cliente he probado a descodificar la base64 con la función atob() y después suprimir este paso en el servidor. De ninguna de las maneras ha sido posible que el PDF se abriera correctamente.

Cuando realizo una firma simple desde el servidor, eligiendo y guardando el archivo por diálogo, el PDF resultante es correcto y se puede abrir perfectamente. Usando el mismo certificado X509. Esto es lo que me hace pensar en que hay una operación interna sobre la cadena Base64 que ignoro y que sería necesaria para que el formato de la cadena sea correcta de cara a la creación del PDF. Todo parece apuntar a que el cliente @firma cuando realiza normalmente las operaciones de guardado de un archivo PDF (no en este caso concreto, ya que me encargo yo de hacerlo en el servidor) debe aplicar algunos cambios o procesos a la cadena Base64 previamente a la creación del PDF, y que al tomar yo la cadena Base64 sin estas modificaciones desde el cliente todo el proceso posterior conduce al PDF corrupto.

He probado a descodificar en el cliente esta cadena con la función incorporada en el Autoscript.js base64.decode pasando el parámetro SAF como true y como false también, y en ambas ocasiones tampoco se generaba un PDF correcto.

He verificado el procedimiento que uso para crear el PDF con la matriz de bytes y la conversión inversa, es decir, la obtención de una matriz de bytes de un PDF cualquiera y la creación de un nuevo PDF y los resultados son siempre correctos.

En fin, perdonad la extensión de la pregunta y agradecería si alguien pudiera aportar alguna solución o idea.

Gracias

manucera commented 1 year ago

He resuelto la primera parte de la consulta al comprobar que la cadena en Base64 devuelta por el cliente @firma es correcta y genera un PDF sin problemas. Esto lo he comprobado en una web donde se presta el servicio de generación de archivos PDF desde una cadena Base64. Esto descarta la sospecha acerca del origen del problema desde el cliente y el problema solo puede generarse cuando recupero una cadena normal a partir de la cadena Base64 , el paso a Byte[] de la misma y la creación del archivo PDF pasándole el Byte[] como parámetro. Como esa es una cuestión de programación (en mi caso de c#) doy por concluida mi petición de ayuda en esta comunidad. Muchas gracias.