[ 
https://issues.apache.org/jira/browse/PDFBOX-5568?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Piyush updated PDFBOX-5568:
---------------------------
    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.

!https://i.stack.imgur.com/KKgRh.png!

 

*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);

> Document getting corrupted on adding Signed Attributes
> ------------------------------------------------------
>
>                 Key: PDFBOX-5568
>                 URL: https://issues.apache.org/jira/browse/PDFBOX-5568
>             Project: PDFBox
>          Issue Type: Bug
>            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:*
> 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);



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

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to