[ 
https://issues.apache.org/jira/browse/PDFBOX-5568?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17691309#comment-17691309
 ] 

Michael Klink commented on PDFBOX-5568:
---------------------------------------

As already mentioned in a comment to your stack overflow question, you 
completely ignore in your code that the _signed attributes_ shall be 
{_}*signed* attributes{_}. Your code simply signs the plain document hash, not 
the to-be-signed attributes.

To fix this, you first need to make sure that the {{attrGen}} creates a 
message-digest attribute with the value of {{hashBytes}} and that you replace 
your {{ContentSigner nonSigner}} by a {{ContentSigner}} that actually does sign 
the bytes it retrieves to sign.

Reading [RFC 5652|https://www.rfc-editor.org/rfc/rfc5652] may help you 
understand what needs to be done...

> Document getting corrupted on adding Signed Attributes
> ------------------------------------------------------
>
>                 Key: PDFBOX-5568
>                 URL: https://issues.apache.org/jira/browse/PDFBOX-5568
>             Project: PDFBox
>          Issue Type: Bug
>          Components: Signing
>            Reporter: Piyush
>            Priority: Major
>
> 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.
> !https://i.stack.imgur.com/KKgRh.png!
>  
> *Code snippet for reference:*
> {code:java}
> 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);
> {code}
> 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.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@pdfbox.apache.org
For additional commands, e-mail: dev-h...@pdfbox.apache.org

Reply via email to