diff options
Diffstat (limited to 'pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/signing')
8 files changed, 301 insertions, 0 deletions
diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/IPdfSigner.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/IPdfSigner.java new file mode 100644 index 00000000..8ff3a276 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/IPdfSigner.java @@ -0,0 +1,12 @@ +package at.gv.egiz.pdfas.lib.impl.signing; + +import at.gv.egiz.pdfas.common.exceptions.PdfAsException; +import at.gv.egiz.pdfas.lib.api.sign.IPlainSigner; +import at.gv.egiz.pdfas.lib.impl.status.PDFObject; +import at.gv.egiz.pdfas.lib.impl.status.RequestedSignature; + +public interface IPdfSigner { + + void signPDF(PDFObject pdfObject, + RequestedSignature requestedSignature, IPlainSigner signer) throws PdfAsException; +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/PdfSignerFactory.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/PdfSignerFactory.java new file mode 100644 index 00000000..469ea174 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/PdfSignerFactory.java @@ -0,0 +1,9 @@ +package at.gv.egiz.pdfas.lib.impl.signing; + +import at.gv.egiz.pdfas.lib.impl.signing.pdfbox.PADESPDFBOXSigner; + +public class PdfSignerFactory { + public static IPdfSigner createPdfSigner() { + return new PADESPDFBOXSigner(); + } +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/package-info.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/package-info.java new file mode 100644 index 00000000..6a59486b --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/package-info.java @@ -0,0 +1,8 @@ +/** + * + */ +/** + * @author afitzek + * + */ +package at.gv.egiz.pdfas.lib.impl.signing;
\ No newline at end of file diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox/PADESPDFBOXSigner.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox/PADESPDFBOXSigner.java new file mode 100644 index 00000000..82ee57fe --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox/PADESPDFBOXSigner.java @@ -0,0 +1,141 @@ +package at.gv.egiz.pdfas.lib.impl.signing.pdfbox; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.Calendar; + +import org.apache.pdfbox.exceptions.COSVisitorException; +import org.apache.pdfbox.exceptions.SignatureException; +import org.apache.pdfbox.pdmodel.PDDocument; +import org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature; +import org.apache.pdfbox.pdmodel.interactive.digitalsignature.SignatureInterface; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +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.sign.IPlainSigner; +import at.gv.egiz.pdfas.lib.impl.signing.IPdfSigner; +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.status.PDFObject; +import at.gv.egiz.pdfas.lib.impl.status.RequestedSignature; + +public class PADESPDFBOXSigner implements IPdfSigner { + + private static final Logger logger = LoggerFactory.getLogger(PADESPDFBOXSigner.class); + + public void signPDF(PDFObject pdfObject, RequestedSignature requestedSignature, IPlainSigner signer) + throws PdfAsException { + String fisTmpFile = null; + + TempFileHelper helper = pdfObject.getStatus().getTempFileHelper(); + + try { + fisTmpFile = helper.getStaticFilename(); + + // write to temporary file + FileOutputStream fos = new FileOutputStream(new File(fisTmpFile)); + fos.write(pdfObject.getStampedDocument()); + + + FileInputStream fis = new FileInputStream(new File(fisTmpFile)); + + PDDocument doc = PDDocument.load( + new ByteArrayInputStream(pdfObject.getStampedDocument())); + + PDSignature signature = new PDSignature(); + signature.setFilter(PDSignature.FILTER_ADOBE_PPKLITE); // default filter + signature.setSubFilter(PDSignature.SUBFILTER_ETSI_CADES_DETACHED); + + SignatureProfileSettings signatureProfileSettings = TableFactory + .createProfile(requestedSignature.getSignatureProfileID(), + pdfObject.getStatus().getSettings()); + + ValueResolver resolver = new ValueResolver(); + String signerName = resolver.resolve("SIG_SUBJECT", signatureProfileSettings.getValue("SIG_SUBJECT"), + signatureProfileSettings, requestedSignature); + // TODO: change signature data from certificate + signature.setName(signerName); + //signature.setLocation("signer location"); + signature.setReason("PDF-AS Signatur"); + + + // the signing date, needed for valid signature + signature.setSignDate(Calendar.getInstance()); + + doc.addSignature(signature, new PdfboxSignerWrapper(signer, signature)); + + // pdfbox patched (FIS -> IS) + doc.saveIncremental(fis, fos); + fis.close(); + fos.close(); + + fis = new FileInputStream(new File(fisTmpFile)); + + // write to resulting output stream + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + bos.write(StreamUtils.inputStreamToByteArray(fis)); + fis.close(); + bos.close(); + + pdfObject.setSignedDocument(bos.toByteArray()); + + 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); + } + } + + + public void signPDF(String src, String dst, SignatureInterface signer) throws Exception { + //ByteArrayOutputStream os = new ByteArrayOutputStream(); + FileInputStream fis = new FileInputStream(new File(src)); + FileOutputStream fos = new FileOutputStream(new File(dst)); + byte[] buffer = new byte[8 * 1024]; + byte[] outbuffer; + int c; + while ((c = fis.read(buffer)) != -1) + { + fos.write(buffer, 0, c); + } + fis.close(); + PDDocument doc = PDDocument.load(src); + fis = new FileInputStream(new File(dst)); + + PDSignature signature = new PDSignature(); + signature.setFilter(PDSignature.FILTER_ADOBE_PPKLITE); // default filter + + signature.setSubFilter(PDSignature.SUBFILTER_ADBE_PKCS7_DETACHED); + signature.setName("Andraes Fitzek"); + signature.setLocation("signer location"); + signature.setReason("Test Signature"); + + // the signing date, needed for valid signature + signature.setSignDate(Calendar.getInstance()); + + doc.addSignature(signature, signer); + + // pdfbox patched (FIS -> IS) + doc.saveIncremental(fis, fos); + + fos.close(); + // FileUtils.writeByteArrayToFile(new File(dst), os.toByteArray()); + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox/PdfboxSignerWrapper.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox/PdfboxSignerWrapper.java new file mode 100644 index 00000000..fb629dd6 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox/PdfboxSignerWrapper.java @@ -0,0 +1,37 @@ +package at.gv.egiz.pdfas.lib.impl.signing.pdfbox; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; + +import org.apache.pdfbox.exceptions.SignatureException; +import org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature; +import org.apache.pdfbox.pdmodel.interactive.digitalsignature.SignatureInterface; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.gv.egiz.pdfas.common.utils.StreamUtils; +import at.gv.egiz.pdfas.common.utils.StringUtils; +import at.gv.egiz.pdfas.lib.api.sign.IPlainSigner; + +public class PdfboxSignerWrapper implements SignatureInterface { + + private static final Logger logger = LoggerFactory.getLogger(PdfboxSignerWrapper.class); + + private IPlainSigner signer; + private PDSignature signature; + + public PdfboxSignerWrapper(IPlainSigner signer, PDSignature signature) { + this.signer = signer; + this.signature = signature; + } + + public byte[] sign(InputStream inputStream) throws SignatureException, IOException { + byte[] signature = signer.sign(StreamUtils.inputStreamToByteArray(inputStream)); + logger.debug("Signature Data: " + StringUtils.bytesToHexString(signature)); + FileOutputStream fos = new FileOutputStream("/tmp/fos.bin"); + fos.write(signature); + fos.close(); + return signature; + } +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox/package-info.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox/package-info.java new file mode 100644 index 00000000..85b552f6 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox/package-info.java @@ -0,0 +1,8 @@ +/** + * + */ +/** + * @author afitzek + * + */ +package at.gv.egiz.pdfas.lib.impl.signing.pdfbox;
\ No newline at end of file diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/sig_interface/JKSSigner.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/sig_interface/JKSSigner.java new file mode 100644 index 00000000..85697436 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/sig_interface/JKSSigner.java @@ -0,0 +1,78 @@ +package at.gv.egiz.pdfas.lib.impl.signing.sig_interface; + +import iaik.asn1.structures.AlgorithmID; +import iaik.cms.SignedDataStream; +import iaik.cms.SignerInfo; +import iaik.cms.SubjectKeyID; +import iaik.security.ecc.provider.ECCProvider; +import iaik.security.provider.IAIK; +import iaik.x509.X509Certificate; +import iaik.x509.X509ExtensionException; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.security.KeyStore; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.cert.Certificate; + +import org.apache.pdfbox.exceptions.SignatureException; + +import at.gv.egiz.pdfas.common.exceptions.PdfAsException; +import at.gv.egiz.pdfas.lib.api.sign.IPlainSigner; + +public class JKSSigner implements IPlainSigner { + + PrivateKey privKey; + X509Certificate cert; + + public JKSSigner(String file, String alias, String kspassword, + String keypassword, String type) throws PdfAsException { + try { + IAIK.getInstance(); + ECCProvider.addAsProvider(); + KeyStore ks = KeyStore.getInstance(type); + ks.load(new FileInputStream(file), kspassword.toCharArray()); + privKey = (PrivateKey) ks.getKey(alias, keypassword.toCharArray()); + cert = new X509Certificate(ks.getCertificate(alias).getEncoded()); + } catch (Throwable e) { + throw new PdfAsException("Failed to get KeyStore", e); + } + } + + public X509Certificate getCertificate() { + return cert; + } + + public byte[] sign(byte[] input) throws SignatureException, IOException { + try { + SignedDataStream signed_data_stream = new SignedDataStream( + new ByteArrayInputStream(input), SignedDataStream.EXPLICIT); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + signed_data_stream.addCertificates(new Certificate[] { cert }); + + SubjectKeyID subjectKeyId = new SubjectKeyID(cert); + SignerInfo signer1 = new SignerInfo(subjectKeyId, + AlgorithmID.sha256, privKey); + signed_data_stream.addSignerInfo(signer1); + InputStream data_is = signed_data_stream.getInputStream(); + if (signed_data_stream.getMode() == SignedDataStream.EXPLICIT) { + byte[] buf = new byte[1024]; + int r; + while ((r = data_is.read(buf)) > 0) { + // do something useful + } + } + signed_data_stream.writeTo(baos); + return baos.toByteArray(); + } catch (NoSuchAlgorithmException e) { + throw new SignatureException(e); + } catch (X509ExtensionException e) { + throw new SignatureException(e); + } + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/sig_interface/package-info.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/sig_interface/package-info.java new file mode 100644 index 00000000..9f552662 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/sig_interface/package-info.java @@ -0,0 +1,8 @@ +/** + * + */ +/** + * @author afitzek + * + */ +package at.gv.egiz.pdfas.lib.impl.signing.sig_interface;
\ No newline at end of file |