title: External Signature with PDFBox 2.0.12
body: <p>Signing modified issue.</p>
  <p>Iam passing the doc hash and signing hash using a DSC token(External Signing).</p>
  <p>iam getting error like:&quot;The document has been altered or corrupted since it was signed&quot;
  Getting the Hash of Document:-</p>
  <pre><code>public String genrateDigitalCertificateSign() {
          try {
              src = new FileInputStream(inputFilePath);
              OutputStream dest = new FileOutputStream(new File(RESULT_FOLDER, &quot;Test.pdf&quot;));
              pdDocument = PDDocument.load(src);
  
              PDSignature pds = null;
              String hashdocument = null;
              File imgFile = new File(inputImgPath);
              PDAcroForm acroForm = pdDocument.getDocumentCatalog().getAcroForm();
              if (acroForm == null) {
                  pdDocument.getDocumentCatalog().setAcroForm(acroForm = new PDAcroForm(pdDocument));
              }
              acroForm.setSignaturesExist(true);
              acroForm.setAppendOnly(true);
              acroForm.getCOSObject().setDirect(true);
  
              pds = new PDSignature();
              pds.setFilter(PDSignature.FILTER_ADOBE_PPKLITE);
              pds.setSubFilter(PDSignature.SUBFILTER_ADBE_PKCS7_DETACHED);
              pds.setSignDate(Calendar.getInstance());
  
              PDPage pdPage = pdDocument.getPage(0);
              PDImageXObject pdImage = PDImageXObject.createFromFileByContent(imgFile, pdDocument);
  
              //visible signature rectangle
              rectangle = new PDRectangle(200.00, 200.00,150.00,50.00);
              
              List&lt;PDField&gt; acroFormFields = acroForm.getFields();
              PDSignatureField signatureField = new PDSignatureField(acroForm);
              acroForm.setSignaturesExist(true);
              acroForm.setAppendOnly(true);
              acroForm.getCOSObject().setDirect(true);
              signatureField.setValue(pds);
              acroFormFields.add(signatureField);
              pdDocument.addSignature(pds);
              
              //creating visible stamp
              createVisualSignatureTemplate(pdDocument, signatureField, pdPage, rectangle, pdImage, signDisplayInfo);
  
              externalSigning = pdDocument.saveIncrementalForExternalSigning(dest);
              InputStream dataToSign = externalSigning.getContent();
              hashdocument = DigestUtils.sha256Hex(dataToSign); // hash is generated
              return hashdocument;
          } catch (FileNotFoundException e) {
              e.printStackTrace();
          } catch (IOException e) {
              e.printStackTrace();
          } catch (Exception e) {
              e.printStackTrace();
          }
          return null;
      }
  </code></pre>
  <p>External signing Code:-</p>
  <pre><code>public byte[] sign(byte[] hash)
              throws IOException, NoSuchAlgorithmException, InvalidKeyException, SignatureException {
          PrivateKey privKey = pk;
          try {
              List&lt;Certificate&gt; certList = new ArrayList&lt;&gt;();
              certList.addAll(Arrays.asList(chain));
              Store certs = new JcaCertStore(certList);
              CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
              org.bouncycastle.asn1.x509.Certificate cert = org.bouncycastle.asn1.x509.Certificate
                      .getInstance(chain[0].getEncoded());
              ContentSigner sha1Signer = new JcaContentSignerBuilder(&quot;SHA256WithRSA&quot;).build(privKey);
              gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().build())
                              .build(sha1Signer, new X509CertificateHolder(cert)));
              gen.addCertificates(certs);
              CMSProcessableInputStream msg = new CMSProcessableInputStream(new ByteArrayInputStream(hash));
              CMSSignedData signedData = gen.generate(msg, false);
              return signedData.getEncoded();
          } catch (GeneralSecurityException e) {
              throw new IOException(e);
          } catch (CMSException e) {
              throw new IOException(e);
          } catch (OperatorCreationException e) {
              throw new IOException(e);
          }
      }
  </code></pre>
  <p>Signature appending code:-</p>
  <pre><code>public void signedPDF(byte[] hash)
              throws InvalidKeyException, NoSuchAlgorithmException, SignatureException, IOException {
          byte[] signedHash = sign(hash);
          externalSigning.setSignature(signedHash);
          IOUtils.closeQuietly(src);
          pdDocument.close();
      } 
  </code></pre>
  <p>After this signature is appending,but while opening the signed PDF getting the error like as shown in the below image.</p>
  <p><img src="https://i.stack.imgur.com/GzpCh.png" alt="" /></p>
  <p>PDF file Link:
  <a href="https://drive.google.com/file/d/1qRT2CVgET8Ds1fu0b5psii3j8ytPKaLH/view?usp=sharing" rel="nofollow noreferrer">https://drive.google.com/file/d/1qRT2CVgET8Ds1fu0b5psii3j8ytPKaLH/view?usp=sharing</a></p>
  <p>[EDITED]</p>
  <pre><code>public byte[] genrateDigitalCertificateSign() {
          try {
              src = new FileInputStream(inputFilePath);
              OutputStream dest = new FileOutputStream(new File(RESULT_FOLDER, &quot;Test.pdf&quot;));
              pdDocument = PDDocument.load(src);
  
              PDSignature pds = null;
              String hashdocument = null;
              File imgFile = new File(inputImgPath);
              PDAcroForm acroForm = pdDocument.getDocumentCatalog().getAcroForm();
              if (acroForm == null) {
                  pdDocument.getDocumentCatalog().setAcroForm(acroForm = new PDAcroForm(pdDocument));
              }
              acroForm.setSignaturesExist(true);
              acroForm.setAppendOnly(true);
              acroForm.getCOSObject().setDirect(true);
  
              pds = new PDSignature();
              pds.setFilter(PDSignature.FILTER_ADOBE_PPKLITE);
              pds.setSubFilter(PDSignature.SUBFILTER_ADBE_PKCS7_DETACHED);
              pds.setSignDate(Calendar.getInstance());
  
              PDPage pdPage = pdDocument.getPage(0);
              PDImageXObject pdImage = PDImageXObject.createFromFileByContent(imgFile, pdDocument);
  
              //visible signature rectangle
              rectangle = new PDRectangle(200.00, 200.00,150.00,50.00);
              
              List&lt;PDField&gt; acroFormFields = acroForm.getFields();
              PDSignatureField signatureField = new PDSignatureField(acroForm);
              acroForm.setSignaturesExist(true);
              acroForm.setAppendOnly(true);
              acroForm.getCOSObject().setDirect(true);
              signatureField.setValue(pds);
              acroFormFields.add(signatureField);
              pdDocument.addSignature(pds);
              
              //creating visible stamp
              createVisualSignatureTemplate(pdDocument, signatureField, pdPage, rectangle, pdImage, signDisplayInfo);
  
              externalSigning = pdDocument.saveIncrementalForExternalSigning(dest);
              InputStream dataToSign = externalSigning.getContent();
              hashdocument = DigestUtils.sha256(dataToSign); // hash is generated
              return hashdocument;
          } catch (FileNotFoundException e) {
              e.printStackTrace();
          } catch (IOException e) {
              e.printStackTrace();
          } catch (Exception e) {
              e.printStackTrace();
          }
          return null;
      }
  </code></pre>
  <p>Recently signed PDF file link:-
  <a href="https://drive.google.com/file/d/1mZ8Wqppx3EylI1aLYB9Fl8NzibBXZxzR/view?usp=sharing" rel="nofollow noreferrer">https://drive.google.com/file/d/1mZ8Wqppx3EylI1aLYB9Fl8NzibBXZxzR/view?usp=sharing</a></p>
  <p>[Edited 2] this is the flow i tried after your suggestions.<br />
  In this what is the 1st issue your pointing out? Iam unable to figure out, please help.</p>
  <pre><code>externalSigning = pdDocument.saveIncrementalForExternalSigning(dest);
              InputStream dataToSign = externalSigning.getContent();
              hashdocument = DigestUtils.sha256(dataToSign); // hash is generated 
              byte[] signedhash = sign(hashdocument);
              externalSigning.setSignature(signedhash);
              pdDocument.close();
  </code></pre>