diff options
author | Andreas Fitzek <andreas.fitzek@iaik.tugraz.at> | 2014-10-16 13:32:35 +0200 |
---|---|---|
committer | Andreas Fitzek <andreas.fitzek@iaik.tugraz.at> | 2014-10-16 13:32:35 +0200 |
commit | c3e2b817615c9c2bbaf056e5547cd3f95f8905ea (patch) | |
tree | 6a7946f9ccead542eec2e5d0213fad2ea63f3973 /pdf-as-pdfbox/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox | |
parent | 63784f692a50606f34702706761edac052fdac60 (diff) | |
download | pdf-as-4-c3e2b817615c9c2bbaf056e5547cd3f95f8905ea.tar.gz pdf-as-4-c3e2b817615c9c2bbaf056e5547cd3f95f8905ea.tar.bz2 pdf-as-4-c3e2b817615c9c2bbaf056e5547cd3f95f8905ea.zip |
added PDFBOX specifc library
Diffstat (limited to 'pdf-as-pdfbox/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox')
5 files changed, 833 insertions, 0 deletions
diff --git a/pdf-as-pdfbox/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox/PADESPDFBOXSigner.java b/pdf-as-pdfbox/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox/PADESPDFBOXSigner.java new file mode 100644 index 00000000..ee9da479 --- /dev/null +++ b/pdf-as-pdfbox/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox/PADESPDFBOXSigner.java @@ -0,0 +1,626 @@ +/******************************************************************************* + * <copyright> Copyright 2014 by E-Government Innovation Center EGIZ, Graz, Austria </copyright> + * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a + * joint initiative of the Federal Chancellery Austria and Graz University of + * Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + ******************************************************************************/ +package at.gv.egiz.pdfas.lib.impl.signing.pdfbox; + +import iaik.x509.X509Certificate; + +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.image.BufferedImage; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.List; + +import org.apache.commons.io.IOUtils; +import org.apache.pdfbox.cos.COSBase; +import org.apache.pdfbox.cos.COSDictionary; +import org.apache.pdfbox.cos.COSName; +import org.apache.pdfbox.cos.COSString; +import org.apache.pdfbox.exceptions.COSVisitorException; +import org.apache.pdfbox.exceptions.SignatureException; +import org.apache.pdfbox.pdmodel.PDDocument; +import org.apache.pdfbox.pdmodel.PDDocumentCatalog; +import org.apache.pdfbox.pdmodel.PDPage; +import org.apache.pdfbox.pdmodel.PDPageNode; +import org.apache.pdfbox.pdmodel.PDResources; +import org.apache.pdfbox.pdmodel.graphics.color.PDOutputIntent; +import org.apache.pdfbox.pdmodel.graphics.xobject.PDJpeg; +import org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature; +import org.apache.pdfbox.pdmodel.interactive.digitalsignature.SignatureOptions; +import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm; +import org.apache.pdfbox.pdmodel.interactive.form.PDField; +import org.apache.pdfbox.pdmodel.interactive.form.PDSignatureField; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.gv.egiz.pdfas.common.exceptions.PDFASError; +import at.gv.egiz.pdfas.common.exceptions.PdfAsException; +import at.gv.egiz.pdfas.common.messages.MessageResolver; +import at.gv.egiz.pdfas.common.settings.SignatureProfileSettings; +import at.gv.egiz.pdfas.common.utils.StreamUtils; +import at.gv.egiz.pdfas.common.utils.TempFileHelper; +import at.gv.egiz.pdfas.lib.api.ByteArrayDataSource; +import at.gv.egiz.pdfas.lib.api.IConfigurationConstants; +import at.gv.egiz.pdfas.lib.api.sign.IPlainSigner; +import at.gv.egiz.pdfas.lib.api.sign.SignParameter; +import at.gv.egiz.pdfas.lib.impl.ErrorExtractor; +import at.gv.egiz.pdfas.lib.impl.SignaturePositionImpl; +import at.gv.egiz.pdfas.lib.impl.configuration.SignatureProfileConfiguration; +import at.gv.egiz.pdfas.lib.impl.pdfbox.PDFBOXObject; +import at.gv.egiz.pdfas.lib.impl.pdfbox.positioning.Positioning; +import at.gv.egiz.pdfas.lib.impl.pdfbox.utils.PdfBoxUtils; +import at.gv.egiz.pdfas.lib.impl.placeholder.PlaceholderFilter; +import at.gv.egiz.pdfas.lib.impl.placeholder.SignaturePlaceholderData; +import at.gv.egiz.pdfas.lib.impl.signing.IPdfSigner; +import at.gv.egiz.pdfas.lib.impl.signing.PDFASSignatureExtractor; +import at.gv.egiz.pdfas.lib.impl.signing.PDFASSignatureInterface; +import at.gv.egiz.pdfas.lib.impl.stamping.IPDFStamper; +import at.gv.egiz.pdfas.lib.impl.stamping.IPDFVisualObject; +import at.gv.egiz.pdfas.lib.impl.stamping.StamperFactory; +import at.gv.egiz.pdfas.lib.impl.stamping.TableFactory; +import at.gv.egiz.pdfas.lib.impl.stamping.ValueResolver; +import at.gv.egiz.pdfas.lib.impl.stamping.pdfbox.PDFAsVisualSignatureProperties; +import at.gv.egiz.pdfas.lib.impl.stamping.pdfbox.PdfBoxVisualObject; +import at.gv.egiz.pdfas.lib.impl.status.OperationStatus; +import at.gv.egiz.pdfas.lib.impl.status.PDFObject; +import at.gv.egiz.pdfas.lib.impl.status.RequestedSignature; +import at.knowcenter.wag.egov.egiz.pdf.PositioningInstruction; +import at.knowcenter.wag.egov.egiz.pdf.TablePos; +import at.knowcenter.wag.egov.egiz.table.Table; + +public class PADESPDFBOXSigner implements IPdfSigner, IConfigurationConstants { + + private static final Logger logger = LoggerFactory + .getLogger(PADESPDFBOXSigner.class); + + public void signPDF(PDFObject genericPdfObject, + RequestedSignature requestedSignature, + PDFASSignatureInterface genericSigner) throws PdfAsException { + String fisTmpFile = null; + + if (!(genericPdfObject instanceof PDFBOXObject)) { + // tODO: + throw new PdfAsException(); + } + + PDFBOXObject pdfObject = (PDFBOXObject) genericPdfObject; + + if (!(genericSigner instanceof PDFASPDFBOXSignatureInterface)) { + // tODO: + throw new PdfAsException(); + } + + PDFASPDFBOXSignatureInterface signer = (PDFASPDFBOXSignatureInterface) genericSigner; + + TempFileHelper helper = pdfObject.getStatus().getTempFileHelper(); + PDDocument doc = null; + try { + fisTmpFile = helper.getStaticFilename(); + + // write to temporary file + FileOutputStream fos = new FileOutputStream(new File(fisTmpFile)); + IOUtils.copy(pdfObject.getOriginalDocument().getInputStream(), fos); + + FileInputStream fis = new FileInputStream(new File(fisTmpFile)); + + doc = pdfObject.getDocument(); + + PDSignature signature = new PDSignature(); + signature.setFilter(COSName.getPDFName(signer.getPDFFilter())); // default + // filter + signature + .setSubFilter(COSName.getPDFName(signer.getPDFSubFilter())); + + SignatureProfileSettings signatureProfileSettings = TableFactory + .createProfile(requestedSignature.getSignatureProfileID(), + pdfObject.getStatus().getSettings()); + + ValueResolver resolver = new ValueResolver(requestedSignature, + pdfObject.getStatus()); + String signerName = resolver.resolve("SIG_SUBJECT", + signatureProfileSettings.getValue("SIG_SUBJECT"), + signatureProfileSettings); + + signature.setName(signerName); + signature.setSignDate(Calendar.getInstance()); + String signerReason = signatureProfileSettings.getSigningReason(); + + if (signerReason == null) { + signerReason = "PAdES Signature"; + } + + signature.setReason(signerReason); + logger.debug("Signing reason: " + signerReason); + + logger.debug("Signing @ " + + signer.getSigningDate().getTime().toString()); + // the signing date, needed for valid signature + // signature.setSignDate(signer.getSigningDate()); + + signer.setPDSignature(signature); + SignatureOptions options = new SignatureOptions(); + + // Is visible Signature + if (requestedSignature.isVisual()) { + logger.info("Creating visual siganture block"); + + SignatureProfileConfiguration signatureProfileConfiguration = pdfObject + .getStatus().getSignatureProfileConfiguration( + requestedSignature.getSignatureProfileID()); + + SignaturePlaceholderData signaturePlaceholderData = PlaceholderFilter + .checkPlaceholderSignature(pdfObject.getStatus(), + pdfObject.getStatus().getSettings()); + + TablePos tablePos = null; + + if (signaturePlaceholderData != null) { + // Placeholder found! + + if (signaturePlaceholderData.getProfile() != null) { + requestedSignature + .setSignatureProfileID(signaturePlaceholderData + .getProfile()); + } + + tablePos = signaturePlaceholderData.getTablePos(); + } + + if (tablePos == null) { + // ================================================================ + // PositioningStage (visual) -> find position or use fixed + // position + + String posString = pdfObject.getStatus().getSignParamter() + .getSignaturePosition(); + + TablePos signaturePos = null; + + String signaturePosString = signatureProfileConfiguration + .getDefaultPositioning(); + + if (signaturePosString != null) { + logger.debug("using signature Positioning: " + + signaturePos); + signaturePos = new TablePos(signaturePosString); + } + + logger.debug("using Positioning: " + posString); + + if (posString != null) { + // Merge Signature Position + tablePos = new TablePos(posString, signaturePos); + } else { + // Fallback to signature Position! + tablePos = signaturePos; + } + + if (tablePos == null) { + // Last Fallback default position + tablePos = new TablePos(); + } + } + boolean legacy32Position = signatureProfileConfiguration + .getLegacy32Positioning(); + + // create Table describtion + Table main = TableFactory.createSigTable( + signatureProfileSettings, MAIN, pdfObject.getStatus(), + requestedSignature); + + IPDFStamper stamper = StamperFactory + .createDefaultStamper(pdfObject.getStatus() + .getSettings()); + + IPDFVisualObject visualObject = stamper.createVisualPDFObject( + pdfObject, main); + + /* + * PDDocument originalDocument = PDDocument .load(new + * ByteArrayInputStream(pdfObject.getStatus() + * .getPdfObject().getOriginalDocument())); + */ + + PositioningInstruction positioningInstruction = Positioning + .determineTablePositioning(tablePos, "", doc, + visualObject, legacy32Position); + + SignaturePositionImpl position = new SignaturePositionImpl(); + position.setX(positioningInstruction.getX()); + position.setY(positioningInstruction.getY()); + position.setPage(positioningInstruction.getPage()); + position.setHeight(visualObject.getHeight()); + position.setWidth(visualObject.getWidth()); + + requestedSignature.setSignaturePosition(position); + + PDFAsVisualSignatureProperties properties = new PDFAsVisualSignatureProperties( + pdfObject.getStatus().getSettings(), pdfObject, + (PdfBoxVisualObject) visualObject, + positioningInstruction); + + properties.buildSignature(); + + /* + * ByteArrayOutputStream sigbos = new ByteArrayOutputStream(); + * sigbos.write(StreamUtils.inputStreamToByteArray(properties + * .getVisibleSignature())); sigbos.close(); + */ + + if (signaturePlaceholderData != null) { + // Placeholder found! + // replace placeholder + InputStream is = PADESPDFBOXSigner.class + .getResourceAsStream("/placeholder/empty.jpg"); + PDJpeg img = new PDJpeg(doc, is); + img.getCOSObject().setNeedToBeUpdate(true); + + PDDocumentCatalog root = doc.getDocumentCatalog(); + PDPageNode rootPages = root.getPages(); + List<PDPage> kids = new ArrayList<PDPage>(); + rootPages.getAllKids(kids); + int pageNumber = positioningInstruction.getPage(); + rootPages.getAllKids(kids); + PDPage page = kids.get(pageNumber); + + logger.info("Placeholder name: " + + signaturePlaceholderData.getPlaceholderName()); + COSDictionary xobjectsDictionary = (COSDictionary) page + .findResources().getCOSDictionary() + .getDictionaryObject(COSName.XOBJECT); + xobjectsDictionary.setItem( + signaturePlaceholderData.getPlaceholderName(), img); + xobjectsDictionary.setNeedToBeUpdate(true); + page.findResources().getCOSObject().setNeedToBeUpdate(true); + logger.info("Placeholder name: " + + signaturePlaceholderData.getPlaceholderName()); + } + + if (positioningInstruction.isMakeNewPage()) { + int last = doc.getNumberOfPages() - 1; + PDDocumentCatalog root = doc.getDocumentCatalog(); + PDPageNode rootPages = root.getPages(); + List<PDPage> kids = new ArrayList<PDPage>(); + rootPages.getAllKids(kids); + PDPage lastPage = kids.get(last); + rootPages.getCOSObject().setNeedToBeUpdate(true); + PDPage p = new PDPage(lastPage.findMediaBox()); + p.setResources(new PDResources()); + + doc.addPage(p); + } + + if (signatureProfileSettings.isPDFA()) { + PDDocumentCatalog root = doc.getDocumentCatalog(); + COSBase base = root.getCOSDictionary().getItem( + COSName.OUTPUT_INTENTS); + if (base == null) { + InputStream colorProfile = PDDocumentCatalog.class + .getResourceAsStream("/icm/sRGB Color Space Profile.icm"); + try { + PDOutputIntent oi = new PDOutputIntent(doc, + colorProfile); + oi.setInfo("sRGB IEC61966-2.1"); + oi.setOutputCondition("sRGB IEC61966-2.1"); + oi.setOutputConditionIdentifier("sRGB IEC61966-2.1"); + oi.setRegistryName("http://www.color.org"); + + root.addOutputIntent(oi); + root.getCOSObject().setNeedToBeUpdate(true); + logger.info("added Output Intent"); + } catch (Throwable e) { + e.printStackTrace(); + throw new PdfAsException( + "Failed to add Output Intent", e); + } + } + } + + // if (signatureProfileSettings.isPDFA()) { // Check for PDF-UA + // PDDocumentCatalog root = doc.getDocumentCatalog(); + // PDStructureTreeRoot treeRoot = root.getStructureTreeRoot(); + // if (treeRoot != null) { // Handle as PDF-UA + // logger.info("Tree Root: {}", treeRoot.toString()); + // PDStructureElement docElement = PDFBoxTaggingUtils + // .getDocumentElement(treeRoot); + // PDStructureElement sigBlock = new PDStructureElement( + // "Table", docElement); + // root.getCOSObject().setNeedToBeUpdate(true); + // docElement.getCOSObject().setNeedToBeUpdate(true); + // treeRoot.getCOSObject().setNeedToBeUpdate(true); + // sigBlock.setTitle("Signature Table"); + // } + // } + + options.setPreferedSignatureSize(0x1000); + options.setPage(positioningInstruction.getPage()); + options.setVisualSignature(properties.getVisibleSignature()); + } + + doc.addSignature(signature, signer, options); + + String sigFieldName = signatureProfileSettings.getSignFieldValue(); + + if (sigFieldName == null) { + sigFieldName = "PDF-AS Signatur"; + } + + int count = PdfBoxUtils.countSignatures(doc, sigFieldName); + + sigFieldName = sigFieldName + count; + + PDAcroForm acroFormm = doc.getDocumentCatalog().getAcroForm(); + if (acroFormm != null) { + @SuppressWarnings("unchecked") + List<PDField> fields = acroFormm.getFields(); + PDSignatureField signatureField = null; + + if (fields != null) { + for (PDField pdField : fields) { + if (pdField instanceof PDSignatureField) { + if (((PDSignatureField) pdField).getSignature() + .getDictionary() + .equals(signature.getDictionary())) { + signatureField = (PDSignatureField) pdField; + } + } + } + } else { + logger.warn("Failed to name Signature Field! [Cannot find Field list in acroForm!]"); + } + + if (signatureField != null) { + signatureField.setPartialName(sigFieldName); + } + } else { + logger.warn("Failed to name Signature Field! [Cannot find acroForm!]"); + } + + if (requestedSignature.isVisual()) { + + // if(requestedSignature.getSignaturePosition().) + /* + * PDAcroForm acroForm = doc.getDocumentCatalog().getAcroForm(); + * if (acroForm != null) { + * + * @SuppressWarnings("unchecked") List<PDField> fields = + * acroForm.getFields(); PDSignatureField signatureField = null; + * + * if (fields != null) { for (PDField pdField : fields) { if + * (pdField instanceof PDSignatureField) { if + * (((PDSignatureField) pdField).getSignature() .getDictionary() + * .equals(signature.getDictionary())) { signatureField = + * (PDSignatureField) pdField; } } } } else { logger.warn( + * "Failed to apply rotation! [Cannot find Field list in acroForm!]" + * ); } + * + * if (signatureField != null) { if (signatureField.getWidget() + * != null) { if (signatureField.getWidget() + * .getAppearanceCharacteristics() == null) { + * PDAppearanceCharacteristicsDictionary dict = new + * PDAppearanceCharacteristicsDictionary( new COSDictionary()); + * signatureField.getWidget() + * .setAppearanceCharacteristics(dict); } + * + * if (signatureField.getWidget() + * .getAppearanceCharacteristics() != null) { + * signatureField.getWidget() .getAppearanceCharacteristics() + * .setRotation(90); } } } else { logger.warn( + * "Failed to apply rotation! [Cannot find signature Field!]"); + * } } else { + * logger.warn("Failed to apply rotation! [Cannot find acroForm!]" + * ); } + */ + } + + // pdfbox patched (FIS -> IS) + doc.saveIncremental(fis, fos); + fis.close(); + fos.flush(); + fos.close(); + fos = null; + + fis = new FileInputStream(new File(fisTmpFile)); + + // write to resulting output stream + // ByteArrayOutputStream bos = new ByteArrayOutputStream(); + // bos.write(); + // bos.close(); + + pdfObject + .setSignedDocument(StreamUtils.inputStreamToByteArray(fis)); + fis.close(); + fis = null; + System.gc(); + + helper.deleteFile(fisTmpFile); + + } catch (IOException e) { + logger.error(MessageResolver.resolveMessage("error.pdf.sig.01"), e); + throw new PdfAsException("error.pdf.sig.01", e); + } catch (SignatureException e) { + logger.error(MessageResolver.resolveMessage("error.pdf.sig.01"), e); + throw new PdfAsException("error.pdf.sig.01", e); + } catch (COSVisitorException e) { + logger.error(MessageResolver.resolveMessage("error.pdf.sig.01"), e); + throw new PdfAsException("error.pdf.sig.01", e); + } finally { + if (doc != null) { + try { + doc.close(); + } catch (IOException e) { + logger.debug("Failed to close COS Doc!", e); + // Ignore + } + } + logger.debug("Signature done!"); + + } + } + + @Override + public PDFObject buildPDFObject(OperationStatus operationStatus) { + return new PDFBOXObject(operationStatus); + } + + @Override + public PDFASSignatureInterface buildSignaturInterface(IPlainSigner signer, + SignParameter parameters, RequestedSignature requestedSignature) { + return new PdfboxSignerWrapper(signer, parameters, requestedSignature); + } + + @Override + public PDFASSignatureExtractor buildBlindSignaturInterface( + X509Certificate certificate, String filter, String subfilter, + Calendar date) { + return new SignatureDataExtractor(certificate, filter, subfilter, date); + } + + @Override + public void checkPDFPermissions(PDFObject genericPdfObject) + throws PdfAsException { + if (!(genericPdfObject instanceof PDFBOXObject)) { + // tODO: + throw new PdfAsException(); + } + + PDFBOXObject pdfObject = (PDFBOXObject) genericPdfObject; + PdfBoxUtils.checkPDFPermissions(pdfObject.getDocument()); + } + + @Override + public byte[] rewritePlainSignature(byte[] plainSignature) { + String signature = new COSString(plainSignature).getHexString(); + byte[] pdfSignature = signature.getBytes(); + return pdfSignature; + } + + @Override + public Image generateVisibleSignaturePreview(SignParameter parameter, + java.security.cert.X509Certificate cert, int resolution, + OperationStatus status, RequestedSignature requestedSignature) + throws PDFASError { + try { + PDFBOXObject pdfObject = (PDFBOXObject) status.getPdfObject(); + + PDDocument origDoc = new PDDocument(); + origDoc.addPage(new PDPage(PDPage.PAGE_SIZE_A4)); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + origDoc.save(baos); + baos.close(); + + pdfObject.setOriginalDocument(new ByteArrayDataSource(baos + .toByteArray())); + + SignatureProfileSettings signatureProfileSettings = TableFactory + .createProfile(requestedSignature.getSignatureProfileID(), + pdfObject.getStatus().getSettings()); + + // create Table describtion + Table main = TableFactory.createSigTable(signatureProfileSettings, + MAIN, pdfObject.getStatus(), requestedSignature); + + IPDFStamper stamper = StamperFactory.createDefaultStamper(pdfObject + .getStatus().getSettings()); + + IPDFVisualObject visualObject = stamper.createVisualPDFObject( + pdfObject, main); + + SignatureProfileConfiguration signatureProfileConfiguration = pdfObject + .getStatus().getSignatureProfileConfiguration( + requestedSignature.getSignatureProfileID()); + + String signaturePosString = signatureProfileConfiguration + .getDefaultPositioning(); + PositioningInstruction positioningInstruction = null; + if (signaturePosString != null) { + positioningInstruction = Positioning.determineTablePositioning( + new TablePos(signaturePosString), "", origDoc, + visualObject, false); + } else { + positioningInstruction = Positioning.determineTablePositioning( + new TablePos(), "", origDoc, visualObject, false); + } + + origDoc.close(); + + SignaturePositionImpl position = new SignaturePositionImpl(); + position.setX(positioningInstruction.getX()); + position.setY(positioningInstruction.getY()); + position.setPage(positioningInstruction.getPage()); + position.setHeight(visualObject.getHeight()); + position.setWidth(visualObject.getWidth()); + + requestedSignature.setSignaturePosition(position); + + PDFAsVisualSignatureProperties properties = new PDFAsVisualSignatureProperties( + pdfObject.getStatus().getSettings(), pdfObject, + (PdfBoxVisualObject) visualObject, positioningInstruction); + + properties.buildSignature(); + PDDocument visualDoc = PDDocument.load(properties + .getVisibleSignature()); + // PDPageable pageable = new PDPageable(visualDoc); + List<PDPage> pages = new ArrayList<PDPage>(); + visualDoc.getDocumentCatalog().getPages().getAllKids(pages); + + PDPage firstPage = pages.get(0); + + float stdRes = 72; + float targetRes = resolution; + float factor = targetRes / stdRes; + + BufferedImage outputImage = firstPage.convertToImage( + BufferedImage.TYPE_4BYTE_ABGR, (int) targetRes); + + BufferedImage cutOut = new BufferedImage( + (int) (position.getWidth() * factor), + (int) (position.getHeight() * factor), + BufferedImage.TYPE_4BYTE_ABGR); + + Graphics2D graphics = (Graphics2D) cutOut.getGraphics(); + + graphics.drawImage(outputImage, 0, 0, cutOut.getWidth(), cutOut + .getHeight(), (int) (1 * factor), (int) (outputImage + .getHeight() - ((position.getHeight() + 1) * factor)), + (int) ((1 + position.getWidth()) * factor), + (int) (outputImage.getHeight() + - ((position.getHeight() + 1) * factor) + (position + .getHeight() * factor)), null); + return cutOut; + } catch (PdfAsException e) { + logger.error("PDF-AS Exception", e); + throw ErrorExtractor.searchPdfAsError(e); + } catch (Throwable e) { + logger.error("Throwable Exception", e); + throw ErrorExtractor.searchPdfAsError(e); + } + } +} diff --git a/pdf-as-pdfbox/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox/PDFASPDFBOXExtractorInterface.java b/pdf-as-pdfbox/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox/PDFASPDFBOXExtractorInterface.java new file mode 100644 index 00000000..2a2ac4b1 --- /dev/null +++ b/pdf-as-pdfbox/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox/PDFASPDFBOXExtractorInterface.java @@ -0,0 +1,7 @@ +package at.gv.egiz.pdfas.lib.impl.signing.pdfbox; + +import at.gv.egiz.pdfas.lib.impl.signing.PDFASSignatureExtractor; + +public interface PDFASPDFBOXExtractorInterface extends PDFASSignatureExtractor, PDFASPDFBOXSignatureInterface { + +} diff --git a/pdf-as-pdfbox/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox/PDFASPDFBOXSignatureInterface.java b/pdf-as-pdfbox/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox/PDFASPDFBOXSignatureInterface.java new file mode 100644 index 00000000..54eaaf54 --- /dev/null +++ b/pdf-as-pdfbox/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox/PDFASPDFBOXSignatureInterface.java @@ -0,0 +1,10 @@ +package at.gv.egiz.pdfas.lib.impl.signing.pdfbox; + +import org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature; +import org.apache.pdfbox.pdmodel.interactive.digitalsignature.SignatureInterface; + +import at.gv.egiz.pdfas.lib.impl.signing.PDFASSignatureInterface; + +public interface PDFASPDFBOXSignatureInterface extends PDFASSignatureInterface, SignatureInterface { + public void setPDSignature(PDSignature signature); +} diff --git a/pdf-as-pdfbox/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox/PdfboxSignerWrapper.java b/pdf-as-pdfbox/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox/PdfboxSignerWrapper.java new file mode 100644 index 00000000..cad7536e --- /dev/null +++ b/pdf-as-pdfbox/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox/PdfboxSignerWrapper.java @@ -0,0 +1,96 @@ +/******************************************************************************* + * <copyright> Copyright 2014 by E-Government Innovation Center EGIZ, Graz, Austria </copyright> + * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a + * joint initiative of the Federal Chancellery Austria and Graz University of + * Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + ******************************************************************************/ +package at.gv.egiz.pdfas.lib.impl.signing.pdfbox; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Calendar; + +import org.apache.pdfbox.exceptions.SignatureException; +import org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.gv.egiz.pdfas.common.exceptions.PdfAsException; +import at.gv.egiz.pdfas.common.exceptions.PdfAsWrappedIOException; +import at.gv.egiz.pdfas.common.utils.PDFUtils; +import at.gv.egiz.pdfas.common.utils.StreamUtils; +import at.gv.egiz.pdfas.lib.api.sign.IPlainSigner; +import at.gv.egiz.pdfas.lib.api.sign.SignParameter; +import at.gv.egiz.pdfas.lib.impl.status.RequestedSignature; + +public class PdfboxSignerWrapper implements PDFASPDFBOXSignatureInterface { + + private static final Logger logger = LoggerFactory + .getLogger(PdfboxSignerWrapper.class); + + private IPlainSigner signer; + private PDSignature signature; + private int[] byteRange; + private Calendar date; + private SignParameter parameters; + private RequestedSignature requestedSignature; + + public PdfboxSignerWrapper(IPlainSigner signer, SignParameter parameters, RequestedSignature requestedSignature) { + this.signer = signer; + this.date = Calendar.getInstance(); + this.parameters = parameters; + this.requestedSignature = requestedSignature; + } + + public byte[] sign(InputStream inputStream) throws SignatureException, + IOException { + byte[] data = StreamUtils.inputStreamToByteArray(inputStream); + byteRange = PDFUtils.extractSignatureByteRange(data); + int[] byteRange2 = signature.getByteRange(); + logger.debug("Byte Range 2: " + byteRange2); + try { + logger.debug("Signing with Pdfbox Wrapper"); + byte[] signature = signer.sign(data, byteRange, this.parameters, this.requestedSignature); + return signature; + } catch (PdfAsException e) { + throw new PdfAsWrappedIOException(e); + } + } + + public int[] getByteRange() { + return byteRange; + } + + public String getPDFSubFilter() { + return this.signer.getPDFSubFilter(); + } + + public String getPDFFilter() { + return this.signer.getPDFFilter(); + } + + public void setPDSignature(PDSignature signature) { + this.signature = signature; + } + + public Calendar getSigningDate() { + return this.date; + } +} diff --git a/pdf-as-pdfbox/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox/SignatureDataExtractor.java b/pdf-as-pdfbox/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox/SignatureDataExtractor.java new file mode 100644 index 00000000..5e3d1085 --- /dev/null +++ b/pdf-as-pdfbox/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox/SignatureDataExtractor.java @@ -0,0 +1,94 @@ +/******************************************************************************* + * <copyright> Copyright 2014 by E-Government Innovation Center EGIZ, Graz, Austria </copyright> + * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a + * joint initiative of the Federal Chancellery Austria and Graz University of + * Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + ******************************************************************************/ +package at.gv.egiz.pdfas.lib.impl.signing.pdfbox; + +import iaik.x509.X509Certificate; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Calendar; + +import org.apache.pdfbox.exceptions.SignatureException; +import org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature; + +import at.gv.egiz.pdfas.common.utils.StreamUtils; +import at.gv.egiz.pdfas.lib.impl.signing.PDFASSignatureInterface; + +public class SignatureDataExtractor implements PDFASPDFBOXExtractorInterface { + + protected X509Certificate certificate; + protected byte[] signatureData; + + protected String pdfSubFilter; + protected String pdfFilter; + protected PDSignature signature; + protected int[] byteRange; + protected Calendar date; + + public SignatureDataExtractor(X509Certificate certificate, + String filter, String subfilter, Calendar date) { + this.certificate = certificate; + this.pdfFilter = filter; + this.pdfSubFilter = subfilter; + this.date = date; + } + + public X509Certificate getCertificate() { + return certificate; + } + + public String getPDFSubFilter() { + return this.pdfSubFilter; + } + + public String getPDFFilter() { + return this.pdfFilter; + } + + public byte[] getSignatureData() { + return this.signatureData; + } + + public byte[] sign(InputStream content) throws SignatureException, + IOException { + signatureData = StreamUtils.inputStreamToByteArray(content); + byteRange = this.signature.getByteRange(); + return new byte[] { 0 }; + } + + public void setPDSignature(PDSignature signature) { + this.signature = signature; + } + + public int[] getByteRange() { + return byteRange; + } + + public Calendar getSigningDate() { + return this.date; + } + + + +} |