[
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]