title: digital signature using pdfbox
body: <p>I am trying to add multiple signatures to my pdf using pdfbox, I am trying with two signatures and second signature always turns to be invalid.Please advice,
  Can a be  PDF be signed digitally several times?    Adobe livecycle forums says yes.</p>
  
  <pre class="lang-java prettyprint-override"><code>import java.io.File;
  import java.io.FileInputStream;
  import java.io.FileNotFoundException;
  import java.io.FileOutputStream;
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.OutputStream;
  import java.security.KeyStore;
  import java.security.KeyStoreException;
  import java.security.NoSuchAlgorithmException;
  import java.security.PrivateKey;
  import java.security.UnrecoverableKeyException;
  import java.security.cert.CertStore;
  import java.security.cert.Certificate;
  import java.security.cert.CertificateException;
  import java.security.cert.CollectionCertStoreParameters;
  import java.security.cert.X509Certificate;
  import java.util.Arrays;
  import java.util.Calendar;
  import java.util.Enumeration;
  import java.util.List;
  
  import org.apache.pdfbox.exceptions.COSVisitorException;
  import org.apache.pdfbox.exceptions.SignatureException;
  import org.apache.pdfbox.pdmodel.PDDocument;
  import org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature;
  import org.apache.pdfbox.pdmodel.interactive.digitalsignature.SignatureInterface;
  import org.bouncycastle.cms.CMSException;
  import org.bouncycastle.cms.CMSProcessable;
  import org.bouncycastle.cms.CMSSignedData;
  import org.bouncycastle.cms.CMSSignedDataGenerator;
  import org.bouncycastle.cms.CMSSignedGenerator;
  import org.bouncycastle.jce.provider.BouncyCastleProvider;
  
  public class SigningTest implements SignatureInterface {
  
      private static BouncyCastleProvider provider = new BouncyCastleProvider();
  
      private PrivateKey privKey;
  
      private Certificate[] cert;
  
      public SigningTest(KeyStore keystore, char[] pin) {
          try {
              Enumeration&lt;String&gt; aliases = keystore.aliases();
              String alias = null;
              if (aliases.hasMoreElements())
                  alias = aliases.nextElement();
              else
                  throw new RuntimeException("Could not find Key");
              privKey = (PrivateKey) keystore.getKey(alias, pin);
              cert = keystore.getCertificateChain(alias);
          } catch (KeyStoreException e) {
              // TODO Auto-generated catch block
              e.printStackTrace();
          } catch (UnrecoverableKeyException e) {
              // TODO Auto-generated catch block
              e.printStackTrace();
          } catch (NoSuchAlgorithmException e) {
              // TODO Auto-generated catch block
              e.printStackTrace();
          }
      }
  
      public byte[] sign(InputStream content) throws SignatureException,
              IOException {
          CMSProcessableInputStream input = new CMSProcessableInputStream(content);
          CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
          // CertificateChain
          List&lt;Certificate&gt; certList = Arrays.asList(cert);
  
          CertStore certStore = null;
          try {
              certStore = CertStore.getInstance("Collection",
                      new CollectionCertStoreParameters(certList), provider);
              gen.addSigner(privKey, (X509Certificate) certList.get(0),
                      CMSSignedGenerator.DIGEST_SHA256);
              gen.addCertificatesAndCRLs(certStore);
              CMSSignedData signedData = gen.generate(input, false, provider);
              return signedData.getEncoded();
          } catch (Exception e) {
              // should be handled
              e.printStackTrace();
          }
          throw new RuntimeException("Problem while preparing signature");
      }
  
      public static void main(String[] args) throws KeyStoreException,
              NoSuchAlgorithmException, CertificateException,
              FileNotFoundException, IOException, COSVisitorException,
              SignatureException, Exception {
          File document = new File("resources/OCD.pdf");
          PDDocument pdDocument = PDDocument.load(document);
  
          addSignature(pdDocument, "resources/j4l_test.p12", "test");
          addSignature(pdDocument, "resources/my.p12", "123456");
  
          File outputDocument = new File("resources/signed" + document.getName());
          FileInputStream fis = new FileInputStream(document);
          FileOutputStream fos = new FileOutputStream(outputDocument);
          byte[] buffer = new byte[8 * 1024];
          int c;
          while ((c = fis.read(buffer)) != -1)
          {
            fos.write(buffer, 0, c);
          }
          fis.close();
          fis = new FileInputStream(outputDocument);
  
          pdDocument.saveIncremental(fis, fos);
          //pdDocument.close();
  
      }
  
  
  
  
      static void addSignature(PDDocument  pdDocument,  String filePath,String pwd)  throws Exception{
          File ksFile = new File(filePath);
          KeyStore keystore = KeyStore.getInstance("PKCS12", provider);
          char[] pin = pwd.toCharArray();
          keystore.load(new FileInputStream(ksFile), pin);
          SigningTest signing = new SigningTest(keystore, pin.clone());
          //signing.signPDF(document);
  
          // create signature dictionary
          PDSignature signature = new PDSignature();
          signature.setFilter(PDSignature.FILTER_ADOBE_PPKLITE); // default filter
          // subfilter for basic and PAdES Part 2 signatures
          signature.setSubFilter(PDSignature.SUBFILTER_ADBE_PKCS7_DETACHED);
          signature.setName("signer name");
          signature.setLocation("signer location");
          signature.setReason("reason for signature");
  
          // the signing date, needed for valid signature
          signature.setSignDate(Calendar.getInstance());
  //      SignatureOptions signatureOptions= new SignatureOptions();
  //      signatureOptions.setVisualSignature();
          // register signature dictionary and sign interface
          pdDocument.addSignature(signature, signing);
  
      }
  }
  
  class CMSProcessableInputStream implements CMSProcessable {
  
      InputStream in;
  
      public CMSProcessableInputStream(InputStream is) {
          in = is;
      }
  
      public Object getContent() {
          return null;
      }
  
      public void write(OutputStream out) throws IOException, CMSException {
          // read the content only one time
          byte[] buffer = new byte[8 * 1024];
          int read;
          while ((read = in.read(buffer)) != -1) {
              out.write(buffer, 0, read);
          }
          in.close();
      }
  }
  </code></pre>