PDF Widgets

En este tutorial, se verá el uso de widgets para firmar un documento PDF.

  • PDF.- Es un formato de almacenamiento para documentos digitales independiente de plataformas de software o hardware.
  • Widget.- Los widgets en documentos PDF son componentes que se pueden agregar al documento, estos pueden ser campos de texto, botones, o firmas entre otros.
  • Firma Digital.- La firma digital es un mecanismo criptográfico que permite garantizar los principios de autenticidad, no repudio e integridad.
  • itext.- Librería para la manipulación de archivos PDF desde java.

Uno de los problemas al momento de firmar un documento digitalmente es tener que transferir ese documento por internet, ya que si es grande puede demorar mucho tiempo.

A contiunación se detalla un ejemplo de código que agrega un widget para poder realizr la firma del documento PDF de forma aislada, haciendo uso de la librería itext.

Para poder lograr esto se requiere crear una clase que será la encargada de firmar el documento.

  1. public class ServerSignature implements IExternalSignature {
  2. protected String pin;
  3. protected String alias;
  4. protected Provider sunPKCS11;
  5. protected KeyStore keyStore;
  6. public ServerSignature(String pin, String alias) {
  7. this.pin = pin;
  8. this.alias = alias;
  9. sunPKCS11 = Security.getProvider("SunPKCS11");
  10. sunPKCS11 = sunPKCS11.configure("token.cfg");
  11. try {
  12. keyStore = KeyStore.getInstance("PKCS11", sunPKCS11);
  13. keyStore.load(null, pin.toCharArray());
  14. } catch (KeyStoreException | IOException | NoSuchAlgorithmException | CertificateException ex) {
  15. throw new RuntimeException(ex.getMessage());
  16. }
  17. }
  18. @Override
  19. public String getHashAlgorithm() {
  20. return DigestAlgorithms.getDigest(DigestAlgorithms.getAllowedDigest("SHA256"));
  21. }
  22. @Override
  23. public String getEncryptionAlgorithm() {
  24. try {
  25. PrivateKey pk = (PrivateKey)keyStore.getKey(alias, pin.toCharArray());
  26. return pk.getAlgorithm();
  27. } catch (KeyStoreException | NoSuchAlgorithmException | UnrecoverableKeyException ex) {
  28. throw new RuntimeException(ex.getMessage());
  29. }
  30. }
  31. public Certificate[] getChain() {
  32. try {
  33. return keyStore.getCertificateChain(alias);
  34. } catch (KeyStoreException ex) {
  35. throw new RuntimeException(ex.getMessage());
  36. }
  37. }
  38. @Override
  39. public byte[] sign(byte[] sh) throws GeneralSecurityException {
  40. PrivateKey pk = (PrivateKey)keyStore.getKey(alias, pin.toCharArray());
  41. String signMode = getHashAlgorithm();
  42. signMode += "with" + pk.getAlgorithm();
  43. Signature signature = Signature.getInstance(signMode, sunPKCS11);
  44. signature.initSign(pk);
  45. signature.update(sh);
  46. return signature.sign();
  47. }
  48. }

La clase anterior lo que permite es firmar un documento a través del token criptográfico y recibe de la ingeniería de iText el hash que debe ser firmado.

Para utilizar la clase anterior, simplemente se necesitaría las siguientes instrucciones:

  1. try {
  2. PdfReader reader = new PdfReader(new FileInputStream("prueba.pdf"));
  3. PdfSigner signer = new PdfSigner(reader, new FileOutputStream("prueba.signed.pdf"), new StampingProperties());
  4. Rectangle rect = new Rectangle(0, 0, 0, 0);
  5. PdfSignatureAppearance appearance = signer.getSignatureAppearance();
  6. appearance.setPageRect(rect);
  7. signer.setFieldName("sig");
  8. IExternalDigest digest = new BouncyCastleDigest();
  9. IExternalSignature signature = new ServerSignature("12345678", "355409121073");
  10. signer.signDetached(digest, signature, ((ServerSignature)signature).getChain(), null, null, null, 0, PdfSigner.CryptoStandard.CADES);
  11. } catch (FileNotFoundException ex) {
  12. Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
  13. } catch (IOException | GeneralSecurityException ex) {
  14. Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
  15. }

El documento prueba.pdf se firmará con el certificado asociado al alias 355409121073 disponible en el token criptográfico y accesible a través del pin de seguridad 12345678.

El documento firmado será guardado con el nombre prueba.signed.pdf

Si desea descargar el ejemplo puede hacerlo a través del siguiente link: Código de ejemplo

© ADSIB 2019 Bolivia