Skip to content

Instantly share code, notes, and snippets.

@p4535992
Created February 2, 2018 15:35
Show Gist options
  • Save p4535992/f14870a9613c4f5730d859d7e827fbee to your computer and use it in GitHub Desktop.
Save p4535992/f14870a9613c4f5730d859d7e827fbee to your computer and use it in GitHub Desktop.
A static method for extract hash/digest from a pdfbox document object to sign and the static method to "insert" the new hash/digest signed to the pdf box object
public static byte[] createHashToSignFromPdfFile(InputStream pdf2sign, OutputStream fos, String sigName, String sigLocation,String sigReason,String contactInfo,Date forcedDate,Long revisionId) throws IOException {
File pdfFileToSigned = TempFileProvider.createTempFile("chars", ""+Calendar.getInstance().getTimeInMillis());
File pdfPreparedToBeSigned = TempFileProvider.createTempFile("chars", ""+Calendar.getInstance().getTimeInMillis());
File pdfHashPreparedToBeSigned = TempFileProvider.createTempFile("chars", ""+Calendar.getInstance().getTimeInMillis());
try{
if(fos == null) fos = new FileOutputStream(pdfPreparedToBeSigned);
FileUtils.copyInputStreamToFile(pdf2sign,pdfFileToSigned);
final byte[] signatureBytes = FileUtils.readFileToByteArray(pdfFileToSigned);
PDDocument doc = PDDocument.load(pdfFileToSigned);
if(sigName == null)
{
sigName = getFirmaSigName(doc);
}
// create signature dictionary
PDSignature signature = new PDSignature();
signature.setFilter(PDSignature.FILTER_ADOBE_PPKLITE); // default filter
// subfilter for basic and PAdES Part 2 signatures
//Utile link https://stackoverflow.com/questions/25957573/unable-to-verify-digital-signature-using-apache-pdfbox
signature.setSubFilter(PDSignature.SUBFILTER_ADBE_PKCS7_DETACHED);
//signature.setSubFilter(PDSignature.SUBFILTER_ETSI_CADES_DETACHED);
if (contactInfo!=null && !contactInfo.isEmpty()) {
signature.setContactInfo(contactInfo);
}
if (sigLocation!= null && !sigLocation.isEmpty()) {
signature.setLocation(sigLocation);
}
if (sigReason!=null && !sigReason.isEmpty()) {
signature.setReason(sigReason);
}
if (sigName!=null && !sigName.isEmpty()) {
signature.setName(sigName);
}
// the signing date, needed for valid signature
if(forcedDate != null){
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
Calendar cal = Calendar.getInstance();
cal.setTime(sdf.parse(sdf.format(forcedDate)));
signature.setSignDate(cal);
}
// register signature dictionary and sign interface
final OutputStream improntaNonFirmata = new FileOutputStream(pdfHashPreparedToBeSigned);
final MessageDigest digest = MessageDigest.getInstance("SHA-256");
SignatureInterface signatureInterface = new SignatureInterface() {
@Override
public byte[] sign(InputStream content) throws IOException {
try {
byte[] imp = getImprontaHash(content,"SHA-256");
IOUtils.copy(new ByteArrayInputStream(imp), improntaNonFirmata);
return new byte[0];
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
return new byte[0];
}
}
};
// register signature dictionary and sign interface
SignatureOptions signatureOptions = new SignatureOptions();
// Size can vary, but should be enough for purpose.
signatureOptions.setPreferredSignatureSize(SignatureOptions.DEFAULT_SIGNATURE_SIZE * 8);
doc.addSignature(signature, signatureInterface,signatureOptions);
//doc.addSignature(signature, signatureInterface);
if(revisionId !=null){
doc.setDocumentId(revisionId);
}else{
doc.setDocumentId(0L);
}
// write incremental (only for signing purpose)
doc.saveIncremental(fos);
//return FileUtils.readFileToByteArray(pdfPreparedToBeSigned);
return IOUtils.toByteArray(new FileInputStream(pdfHashPreparedToBeSigned));//getImprontaHash(pdfPreparedToBeSigned,"SHA-256");
}
catch (IOException | SignatureException | ParseException | NoSuchAlgorithmException e)
{
throw new IOException(e);
}finally
{
fos.close();
pdf2sign.close();
FileUtils.deleteQuietly(pdfPreparedToBeSigned);
FileUtils.deleteQuietly(pdfHashPreparedToBeSigned);
FileUtils.deleteQuietly(pdfFileToSigned);
}
}
public static File insertHashSignedToPdfFile(InputStream file, final byte[] signedBytes, OutputStream out,String signerName,String location,String reason,String contactInfo,Date forcedDate,Long forceRevisionId) throws IOException, NoSuchAlgorithmException, ParseException{
File pdfFileToSigned = TempFileProvider.createTempFile("chars", ""+Calendar.getInstance().getTimeInMillis());
FileUtils.writeByteArrayToFile(pdfFileToSigned, IOUtils.toByteArray(file));
logger.debug("Crea File PDF Firmato");
//byte[] buffer = new byte[8 * 1024];
// creating output document and prepare the IO streams.
//String name = pdfFileToSigned.getName();
//String substring = name.substring(0, name.lastIndexOf("."));
File outputDocument = TempFileProvider.createTempFile("chars", ""+Calendar.getInstance().getTimeInMillis());
//File outputDocument = new File(pdfFileToSigned.getParent(), substring+"_signed.pdf");
FileInputStream fis = new FileInputStream(pdfFileToSigned);
FileOutputStream fos = new FileOutputStream(outputDocument);
// load document
PDDocument doc = PDDocument.load(fis);
//https://stackoverflow.com/questions/30549830/attachment-damages-signature-part-2
doc.getDocument().getTrailer().removeItem(COSName.TYPE); // <<<<<<<<<< Remove misleading entry <<<<<<<<<<
//final MessageDigest digest = MessageDigest.getInstance("SHA-256");
//final OutputStream improntaNonFirmata = new FileOutputStream(outputDocument);
// register signature dictionary and sign interface
SignatureInterface signatureInterface = new SignatureInterface() {
@Override
public byte[] sign(InputStream content) throws IOException {
return signedBytes;
}
};
//Filling Image Parameters codice preso da dss
//https://stackoverflow.com/questions/27926407/visual-signature-with-pdfbox-1-8-8
/*
PDVisibleSignDesigner signatureDesigner = new PDVisibleSignDesigner(doc, image, doc.getNumberOfPages());
signatureDesigner.xAxis(250).yAxis(60).zoom(-90).signatureFieldName("signature");
PDVisibleSigProperties signatureProperties = new PDVisibleSigProperties();
signatureProperties
.signerName(name).signerLocation(location).signatureReason(reason).preferredSize(0).page(1)
.visualSignEnabled(true).setPdVisibleSignature(signatureDesigner)
.buildSignature();
doc.addSignature(pdSignature, signatureInterface, options);
options.setVisualSignature(signatureProperties);
*/
// create signature dictionary
PDSignature signature = new PDSignature();
signature.setFilter(PDSignature.FILTER_ADOBE_PPKLITE); // default filter
// subfilter for basic and PAdES Part 2 signatures
//Utile link https://stackoverflow.com/questions/25957573/unable-to-verify-digital-signature-using-apache-pdfbox
signature.setSubFilter(PDSignature.SUBFILTER_ADBE_PKCS7_DETACHED);
//signature.setSubFilter(PDSignature.SUBFILTER_ETSI_CADES_DETACHED);
if (contactInfo!=null && !contactInfo.isEmpty()) {
signature.setContactInfo(contactInfo);
}
if (location!= null && !location.isEmpty()) {
signature.setLocation(location);
}
if (reason!=null && !reason.isEmpty()) {
signature.setReason(reason);
}
if (signerName!=null && !signerName.isEmpty()) {
signature.setName(signerName);
}
// the signing date, needed for valid signature
/*
final Calendar cal = Calendar.getInstance();
final Date signingDate = new Date();
cal.setTime(signingDate);
signature.setSignDate(cal);
signature.setSignDate(Calendar.getInstance());
*/
// the signing date, needed for valid signature
if(forcedDate!=null){
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
Calendar cal = Calendar.getInstance();
cal.setTime(sdf.parse(sdf.format(forcedDate)));
signature.setSignDate(cal);
}
//signature.setContents(signedBytes);
boolean isExternalSigning = false;
if (isExternalSigning)
{
// logger.info("Sign externally...");
// doc.addSignature(signature);
// ExternalSigningSupport externalSigning = doc.saveIncrementalForExternalSigning(out);
// // invoke external signature service
// byte[] cmsSignature = null;//sign(externalSigning.getContent());
// // set signature bytes received from the service
// externalSigning.setSignature(cmsSignature);
}
else
{
SignatureOptions signatureOptions = new SignatureOptions();
// Size can vary, but should be enough for purpose.
signatureOptions.setPreferredSignatureSize(SignatureOptions.DEFAULT_SIGNATURE_SIZE * 8);
// register signature dictionary and sign interface
doc.addSignature(signature,signatureInterface,signatureOptions);
//doc.setDocumentId(0L);
if(forceRevisionId !=null){
doc.setDocumentId(forceRevisionId);
}else{
doc.setDocumentId(0L);
}
// write incremental (only for signing purpose)
doc.saveIncremental(fos);
}
//doc.addSignature(signature,signatureInterface,options);
//doc.saveIncremental(fos);
if(fis!=null)fis.close();
if(fos!=null)fos.close();
FileUtils.deleteQuietly(pdfFileToSigned);
IOUtils.copy(FileUtils.openInputStream(outputDocument),out);
return outputDocument;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment