Uploaded image for project: 'PDFBox'
  1. PDFBox
  2. PDFBOX-5568

Document getting corrupted on adding Signed Attributes

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Closed
    • Major
    • Resolution: Not A Bug
    • None
    • None
    • Signing

    Description

      While trying to digitally sign document using filter as FILTER_ADOBE_PPKLITE and subfilter as SUBFILTER_ETSI_CADES_DETACHED. For ETSI_CADES_Detached, a signing attribute is needs to be added. I am fetching signed hash and certificates from CSC. But after adding signing attribute, it is making the document corrupt. Below is the screenshot for the reference . Seems like hash is getting changed.

       

      Code snippet for reference:

      PDDocument document = PDDocument.load(inputStream);
      outFile = File.createTempFile("signedFIle", ".pdf");
      Certificate[] certificateChain = //retrieve certificate chain from CSC integration
      setCertificateChain(certificateChain);
      // sign
      FileOutputStream output = new FileOutputStream(outFile);
      IOUtils.copy(inputStream, output);
      // create signature dictionary
      PDSignature signature = new PDSignature();
      int accessPermissions = SigUtils.getMDPPermission(document);
      if (accessPermissions == 1)
      {
      throw new IllegalStateException("No changes to the document are permitted due to DocMDP transform parameters dictionary");
      }
      signature.setFilter(PDSignature.FILTER_ADOBE_PPKLITE);
      signature.setSubFilter(PDSignature.SUBFILTER_ETSI_CADES_DETACHED);
      signature.setName("Test Name");
      signature.setLocation("Bucharest, RO");
      signature.setReason("PDFBox Signing");
      signature.setSignDate(Calendar.getInstance());
      Rectangle2D humanRect = new Rectangle2D.Float(location.getLeft(), location.getBottom(), location.getRight(), location.getTop());
      PDRectangle rect = createSignatureRectangle(document, humanRect);
      SignatureOptions signatureOptions = new SignatureOptions();
      signatureOptions.setVisualSignature(createVisualSignatureTemplate(document, 0, rect, signature));
      signatureOptions.setPage(0);
      document.addSignature(signature, signatureOptions);
      ExternalSigningSupport externalSigning =
      document.saveIncrementalForExternalSigning(output);
      InputStream content = externalSigning.getContent();
      CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
      X509Certificate cert = (X509Certificate) certificateChain[0];
      gen.addCertificates(new JcaCertStore(Arrays.asList(certificateChain)));
      MessageDigest digest = MessageDigest.getInstance("SHA-256");
      // Use a buffer to read the input stream in chunks
      byte[] buffer = new byte[4096];
      int bytesRead;
      while ((bytesRead = content.read(buffer)) != -1) {
      digest.update(buffer, 0, bytesRead);
      }
      byte[] hashBytes = digest.digest();
      ESSCertIDv2 certid = new ESSCertIDv2(
      new AlgorithmIdentifier(new ASN1ObjectIdentifier("*****")),
      MessageDigest.getInstance("SHA-256").digest(cert.getEncoded())
      );
      SigningCertificateV2 sigcert = new SigningCertificateV2(certid);
      final DERSet attrValues = new DERSet(sigcert);
      Attribute attr = new Attribute(PKCSObjectIdentifiers.id_aa_signingCertificateV2, attrValues);
      ASN1EncodableVector v = new ASN1EncodableVector();
      v.add(attr);
      AttributeTable atttributeTable = new AttributeTable(v);
      //Create a standard attribute table from the passed in parameters - certhash
      CMSAttributeTableGenerator attrGen = new DefaultSignedAttributeTableGenerator(atttributeTable);
      final byte[] signedHash = // Retrieve signed hash from CSC.
      ContentSigner nonSigner = new ContentSigner() {
      @Override
      public byte[] getSignature()
      { return signedHash; }
      @Override
      public OutputStream getOutputStream() {
      return new ByteArrayOutputStream();
      }
      @Override
      public AlgorithmIdentifier getAlgorithmIdentifier() {
      return new DefaultSignatureAlgorithmIdentifierFinder().find( "SHA256WithRSA" );
      }
      };
      org.bouncycastle.asn1.x509.Certificate cert2 = org.bouncycastle.asn1.x509.Certificate.getInstance(ASN1Primitive.fromByteArray(cert.getEncoded()));
      JcaSignerInfoGeneratorBuilder sigb = new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().build());
      sigb.setSignedAttributeGenerator(attrGen);
      gen.addSignerInfoGenerator(sigb.build(nonSigner, new X509CertificateHolder(cert2)));
      CMSTypedData msg = new CMSProcessableInputStream( inputStream);
      CMSSignedData signedData = gen.generate((CMSTypedData)msg, false);
      byte[] cmsSignature = signedData.getEncoded();
      inputStream.close();
      externalSigning.setSignature(cmsSignature);
      IOUtils.closeQuietly(signatureOptions);
      return new FileInputStream(outFile);
      

      If I use subfilter as SUBFILTER_ADBE_PKCS7_DETACHED and don’t add addtibutesTable, then it works fine. But for SUBFILTER_ETSI_CADES_DETACHED, attributes needs to be added.

      Attachments

        Activity

          People

            Unassigned Unassigned
            piyu1993 Piyush
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: