Firmando con Sinadura desde consola

(Publicado en Kriptopolis en octubre de 2011

Recientemente le pedí consejo a Fernando Acero, con quien comparto afición por los passer domesticus o gorriones, Linux y firma electrónica, por una solución libre a la hora de integrarlo dentro de una aplicación Java. Yo ya había echado un vistazo a Portable Signer y aunque cumplía mis requisitos, había cosas mejorables. Y fue así como me metí con Sinadura. 
Sinadura es una solución de ESLE que permite firmar con certificado software y hardware. Actualmente van por la versión 3. Fernando ha publicado un tutorial de cómo instalarlo y configurarlo en Kriptopolis (I y II). También tenemos el propio manual de sus creadores (hay de la versión 2 y la 3).
 
Si recordáis, hace ya algún tiempo, cuando me puse a meterle mano a Meneame, una de mis principales quejas sobre dicho software es que el control de errores de la instalación y puesta en marcha era básicamente ninguno con ningún feedback hacia el usuario. La instalación era parca en información, así como la documentación,

y básicamente era un prueba-ensayo-error que desesperaba al más pintado (o te motiva, como es mi caso). A Sinadura le pasa parecido, ya que al intentar firmar veremos un desfile interesante de errores y volcados en Java puro por consola, que generalmente no aportan demasiada información y hace imprescindible disponer del código fuente para saber qué está pasando. Supongo que para versiones posteriores es posible que haya un feedback más desarrollado.
 
Sinadura se puede usar de dos maneras: desde escritorio/aplicación gráfica o desde consola. También puedes integrar cualquiera de las dos en tu aplicación, ya que disponemos del código fuente.
 
 
Firmando desde la aplicación gráfica
 
Mi recomendación si te vas a meter con Sinadura es que primero intentes firmar con la versión de escritorio.  Así podremos ver los errores que va escupiendo a consola, y aprender de ellos. Dado que por la aplicación gráfica lo único que veremos es que no se ha podido hacer la operación, es importante recurrir a la consola. Para lanzar desde consola debes hacerlo tal que:

 

Linux:

 
/ruta-donde-este-sinadura/bin/sinadura
 
Windows:
 
c:\ruta-sinadura\> bin/sinadura.exe
c:\ruta-sinadura\> bin/sinadura-gui.bat
 
Dependiendo de si tienes la versión 2 o la 3.
 
Es decir, que no debes lanzarlo desde la carpeta bin directamente, sino un nivel más arriba. Si no lo haces así, tendrás problemas y no sabrás de dónde te vienen (casi todos serán del tipo de que no encuentra esto o lo otro, una librería, el properties de configuración o lo que sea).
 
Con decía antes, es complicado usar la llamada por consola hasta que te hagas con la aplicación. Una vez que lances el GUI, verás una pantalla muy sencillita. Aparece una lista vacía, donde tienes que insertar los PDF a firmar y ya está. La gracia de Sinadura es por partida doble: por un lado se come un lote de PDFs para firmar, y por otro, es capaz de meter varias firmas en el mismo pdf.
 
Lo primero que debes hacer es saber si vas a firmar con certificado software o con tarjeta. Esto es importante, porque si es el primer caso, antes de firmar nada debes ajustar las preferencias de Sinadura e indicarle que vas a usar un certificado software e instalarlo. Si no lo instalas previamente, tendrás un error cada vez que intentes firmar. 
 
Una vez que obtengas un pdf firmado, ya estás en condiciones de pasar al nivel 2 … La Consola.
 
Firmando desde consola
 
Si has llegado hasta aquí, ya estás en camino. Lo que viene ahora será depurar un problema tras otro. Yo no tengo la respuesta a todos los problemas, sólo los que me han surgido a mí sobre la marcha. A ti puede que te surjan otros o que estos que comento ni te aparezcan. Yo estoy ejecutando bajo Windows 7, aunque todo lo que comento aquí se puede extrapolar directamente a Windows Vista o XP, e incluso cualquier sabor de Linux.
 
Consideraciones previas y cosas a tener en cuenta
 
– Si las rutas que usas tienen espacios o caracteres raros, intenta obtener el nombre corto de dichas rutas, ya que te simplificarán bastante la vida.
– Todas las rutas tal que "c:\mi-ruta\fichero" se deben transformar a "c\:\\mi-ruta\\fichero". 
– Para estas pruebas se ha utilizado Sinadura 3. En la versión 2 no es distinto sustancialmente.
– El servidor OCSP de la FNMT no es de libre acceso.
 
Con estas premisas, ya puedes lanzarte a firmar desde consola. 
 
La llamada que hagas tiene que ser más o menos como esta:
 
 
# C:\sinadura3>bin\sinadura-console.bat –sign –pdf –input c:\ruta-entrada\carta.pdf –output c:\ruta-salida\carta.pdf –preferences c:\ruta-properties\fichero.properties
 
Es importante que pases  los parámetros –sign y –pdf. Con el primero le dices que vas a firmar (la alternativa es verificar) y con el segundo le dices que la salida es a pdf (en lugar de a Xades). 
 
Si no lo ponemos o lo ponemos mal, no pasa nada, porque este es el único control de errores que tiene Sinadura. A partir de aquí se estrellará cada vez que algo no le guste.
 
 
  1. FileNotFoundException: Lo primero que hace Sinadura al ser invocado es revisar los parámetros de entrada e intentar cargar el properties. Si no lo encuentra, te lanzará esto. Si el properties existe, casi seguro que la ruta no la tienes bien puesta (con el formato que he escrito antes).
  2. Class.forname: Cuando lee el properties, lo siguiente que hace es intentar cargar la clase adecuada por reflexión (forname)  bien usando  la consola o fichero para recabar datos (por ejemplo, el pin del certificado). Nosotros queremos usar consola, así que en el properties dejaremos comentada la línea de FileCallbackHandler y mantenemos la de ConsoleCallbackHandler. La de CertificatePassword también la dejamos comentada porque queremos que la contraseña nos la pida cada vez.
  3. NumberFormaException: esta excepción nos la puede dar por varios motivos (tantos como parámetros tiene el properties) pero por su naturaleza está claro que se trata de un parámetro que espera recibir un número y lleva algo que no lo es. Los valores donde ir un número en el properties son dónde se coloca la imagen visible del pdf (pdf.stamp.*) y en preferencias (preferencias.radioCertType.active=). Este último parámetro debe ir a 0.
  4. NullPointerException: Aquí ya es la fiesta. Esto puede ser cualquier cosa, así que no tendrás otro remedio que ver en qué línea da, bajarte el código fuente de Sinadura y buscar dentro de la clase en cuestión a ver qué hace el código en ese punto. Por ejemplo:
     
    Exception in thread "main" java.lang.NullPointerException
      at net.esle.sinadura.core.service.PdfService.sign(PdfService.java:99)
      at net.esle.sinadura.core.console.SignController.signPdf(SignController.
    java:152)
      at net.esle.sinadura.core.Sinadura.main(Sinadura.java:55)
     
    La gracia en este caso está en el método "sign" de PdfService. Ya con esto nos hacemos una idea de lo que puede estar pasando. En este caso, se trata de que el alias del certificado no está bien escrito. Para sacar el alias de un certificado hay muchas maneras, desde ver las propiedades del certificado hasta usar herramientas como keytool. Con keytool y un certificado de la FNMT de persona física sería:
     
        keytool -list -storetype pkcs12 -keystore c:\certificado.pfx
     
    El alias del certificado será algo parecido a:
     
        nombre apellido1 apellido2 nombre – nif 01234567A's fnmt id
     
    El alias abarca hasta donde pone id incluido. Eso será lo que debas colocar en el parámetro "certificate.alias" del properties. Si te falta una letra, te sobra un espacio o cualquier cosa que no sea el alias, obtendrás un bonito NullPointerException.
  5. OCSPIssuerRequiredException: Si estás usando un certificado de la FNMT, debes tener en cuenta que estos certificados no pueden validarse por OCSP, así que debes colocar en el properties:
        sign.ocsp.enable=false 
  6. java.net.UnknownHostException: Te puede aparecer donde haya una url, por ejemplo, al colocar el TimeStamp. Si te aparece, verifica la url que has escrito en "sign.ts.tsa".
  7.  ERROR net.esle.sinadura.core.console.SignController: Para usar un certificado, previamente debe estar guardado en un keystore, y dicho keystore debe estar referenciado en el properties. Verifica los path, y verifica que el user y la password son correctas. Para los keystores creados por Sinadura, el login y la password es "sinadura".
  8. INFO  net.esle.sinadura.core.util.ProxyUtil Este es un aviso informativo, por lo que si se da, intentará continuar la firma. En este caso lo único que nos dice es que no puede usar el proxy del properties (quizá simplemente porque no lo hay). Dejamos proxy.http.system=false.
  9. PKCS11: Si te da un error con esto y estás usando certificados en fichero tipo p12 o p7, el problema lo tienes en que no se lo has dicho y Sinadura está buscando el manejador para entender los certificados que suelen ir en formato tarjeta como dnie. Sinadura firma usando los p12 y p11. Consulta los drivers soportados por Sinadura.
  10. log4j:ERROR Precision option (0) isn't a positive integer: Ni caso. Es un error del log4j, ajeno a Sinadura. Zylk dijo que para la versión 3 ya estaría solucionado pero se ve que no es así, porque lo sigue mostrando.
  11. WARN  net.esle.sinadura.core.validate.CertPathUtil – Incomplete chain: El alias del certificado no se corresponde [1].
 
Bueno, espero que a estas alturas ya seáis capaces de firmar sin problemas con Sinadura. Como habréis podido ver si habéis conseguido ejecutar Sinadura y firma, Sinadura es una excelente solución para firmar documentos pdf y para integrarlo en vuestras soluciones. Es una suerte que Zylk lo haya liberado de forma que ahora todos podemos disfrutar de esta herramienta.
 
Si veis otros problemas y dais con la solución, sería bueno que añadierais un comentario para que pueda añadirlos a este tutorial y enriquecer este documento.

Otros enlaces | Manual Sinadura |
Relacionado: Certificados digitales en España
Artículo también publicado en:  Kriptopolis

Un pensamiento en “Firmando con Sinadura desde consola

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *