diff options
| author | Andreas Fitzek <andreas.fitzek@iaik.tugraz.at> | 2014-07-10 12:09:05 +0200 | 
|---|---|---|
| committer | Andreas Fitzek <andreas.fitzek@iaik.tugraz.at> | 2014-07-10 12:09:05 +0200 | 
| commit | af90012c848711a4c9010dbcf71694dbfbca0e86 (patch) | |
| tree | cd40f8fab90b6a2fe62359a404497d369d82ece0 /pdf-as-lib/src/main/java | |
| parent | 83a573238984575b76ab06dca677831f4a650534 (diff) | |
| download | pdf-as-4-af90012c848711a4c9010dbcf71694dbfbca0e86.tar.gz pdf-as-4-af90012c848711a4c9010dbcf71694dbfbca0e86.tar.bz2 pdf-as-4-af90012c848711a4c9010dbcf71694dbfbca0e86.zip | |
Integrity verification of Signature after Signature creation to ensure correct signed Document
Diffstat (limited to 'pdf-as-lib/src/main/java')
8 files changed, 159 insertions, 81 deletions
| diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/api/sign/IPlainSigner.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/api/sign/IPlainSigner.java index 903b9630..a167c596 100644 --- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/api/sign/IPlainSigner.java +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/api/sign/IPlainSigner.java @@ -25,6 +25,7 @@ package at.gv.egiz.pdfas.lib.api.sign;  import iaik.x509.X509Certificate;  import at.gv.egiz.pdfas.common.exceptions.PdfAsException; +import at.gv.egiz.pdfas.lib.impl.status.RequestedSignature;  /**   * Signer interface @@ -48,7 +49,7 @@ public interface IPlainSigner {  	 * @return  	 * @throws PdfAsException  	 */ -    public byte[] sign(byte[] input, int[] byteRange, SignParameter parameter) throws PdfAsException; +    public byte[] sign(byte[] input, int[] byteRange, SignParameter parameter, RequestedSignature requestedSignature) throws PdfAsException;      /**       * Gets the PDF Subfilter for this signer diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/PdfAsImpl.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/PdfAsImpl.java index 28bd9151..7dcdca2b 100644 --- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/PdfAsImpl.java +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/PdfAsImpl.java @@ -31,15 +31,12 @@ import java.awt.image.BufferedImage;  import java.io.ByteArrayInputStream;  import java.io.ByteArrayOutputStream;  import java.io.File; -import java.io.FileOutputStream;  import java.io.IOException;  import java.io.OutputStream;  import java.util.ArrayList;  import java.util.Calendar;  import java.util.List; -import javax.imageio.ImageIO; -  import org.apache.pdfbox.cos.COSArray;  import org.apache.pdfbox.cos.COSBase;  import org.apache.pdfbox.cos.COSDictionary; @@ -47,14 +44,13 @@ import org.apache.pdfbox.cos.COSName;  import org.apache.pdfbox.cos.COSString;  import org.apache.pdfbox.pdmodel.PDDocument;  import org.apache.pdfbox.pdmodel.PDPage; -import org.apache.pdfbox.pdmodel.PDPageable; -import org.apache.pdfbox.util.PDFImageWriter;  import org.slf4j.Logger;  import org.slf4j.LoggerFactory;  import at.gv.egiz.pdfas.common.exceptions.PDFIOException;  import at.gv.egiz.pdfas.common.exceptions.PdfAsException;  import at.gv.egiz.pdfas.common.exceptions.PdfAsSettingsException; +import at.gv.egiz.pdfas.common.exceptions.PdfAsSignatureException;  import at.gv.egiz.pdfas.common.exceptions.PdfAsValidationException;  import at.gv.egiz.pdfas.common.settings.ISettings;  import at.gv.egiz.pdfas.common.settings.Settings; @@ -87,6 +83,7 @@ import at.gv.egiz.pdfas.lib.impl.status.PDFObject;  import at.gv.egiz.pdfas.lib.impl.status.RequestedSignature;  import at.gv.egiz.pdfas.lib.impl.verify.IVerifyFilter;  import at.gv.egiz.pdfas.lib.impl.verify.VerifierDispatcher; +import at.gv.egiz.pdfas.lib.util.SignatureUtils;  import at.knowcenter.wag.egov.egiz.pdf.PositioningInstruction;  import at.knowcenter.wag.egov.egiz.pdf.TablePos;  import at.knowcenter.wag.egov.egiz.table.Table; @@ -193,18 +190,11 @@ public class PdfAsImpl implements PdfAs, IConfigurationConstants {  			IPdfSigner signer = PdfSignerFactory.createPdfSigner();  			signer.signPDF(status.getPdfObject(), requestedSignature,  					new PdfboxSignerWrapper(status.getSignParamter() -							.getPlainSigner(), parameter)); +							.getPlainSigner(), parameter, requestedSignature));  			// ================================================================  			// Create SignResult -			SignResultImpl result = new SignResultImpl(status.getSignParamter() -					.getOutput()); -			OutputStream outputStream = result.getOutputDocument() -					.createOutputStream(); - -			outputStream.write(status.getPdfObject().getSignedDocument()); - -			outputStream.close(); +			SignResult result = createSignResult(status);  			return result;  		} catch (Throwable e) { @@ -424,7 +414,16 @@ public class PdfAsImpl implements PdfAs, IConfigurationConstants {  			String signature = new COSString(request.getSignature())  					.getHexString();  			byte[] pdfSignature = signature.getBytes(); - +			//byte[] input = PDFUtils.blackOutSignature(status.getPdfObject().getSignedDocument(),  +			//		request.getSignatureDataByteRange()); +			VerifyResult verifyResult = SignatureUtils.verifySignature(request.getSignature(), request.getSignatureData()); +			RequestedSignature requestedSignature = request.getStatus().getRequestedSignature(); +			 +			if(!StreamUtils.dataCompare(requestedSignature.getCertificate().getFingerprintSHA(), +					verifyResult.getSignerCertificate().getFingerprintSHA())) { +				throw new PdfAsSignatureException("Certificates missmatch!"); +			} +			  			for (int i = 0; i < pdfSignature.length; i++) {  				status.getPdfObject().getSignedDocument()[offset + i] = pdfSignature[i];  			} 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 index 4e82efa5..c8c4eeb4 100644 --- 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 @@ -35,7 +35,6 @@ import java.util.List;  import org.apache.pdfbox.cos.COSBase;  import org.apache.pdfbox.cos.COSDictionary;  import org.apache.pdfbox.cos.COSName; -import org.apache.pdfbox.cos.COSObject;  import org.apache.pdfbox.exceptions.COSVisitorException;  import org.apache.pdfbox.exceptions.SignatureException;  import org.apache.pdfbox.pdmodel.PDDocument; @@ -343,7 +342,7 @@ public class PADESPDFBOXSigner implements IPdfSigner, IConfigurationConstants {  				sigFieldName = "PDF-AS Signatur";  			} -			int count = SignatureUtils.countSignatures(doc); +			int count = SignatureUtils.countSignatures(doc, sigFieldName);  			sigFieldName = sigFieldName + count; 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 index faa49148..44915a42 100644 --- 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 @@ -39,6 +39,7 @@ 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.signing.sig_interface.PDFASSignatureInterface; +import at.gv.egiz.pdfas.lib.impl.status.RequestedSignature;  public class PdfboxSignerWrapper implements PDFASSignatureInterface { @@ -46,16 +47,17 @@ public class PdfboxSignerWrapper implements PDFASSignatureInterface {  			.getLogger(PdfboxSignerWrapper.class);  	private IPlainSigner signer; -	@SuppressWarnings("unused") -  private PDSignature signature; +	private PDSignature signature;  	private int[] byteRange;  	private Calendar date;  	private SignParameter parameters; +	private RequestedSignature requestedSignature; -	public PdfboxSignerWrapper(IPlainSigner signer, SignParameter parameters) { +	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, @@ -66,7 +68,7 @@ public class PdfboxSignerWrapper implements PDFASSignatureInterface {  		logger.info("Byte Range 2: " + byteRange2);  		try {  			logger.info("Signing with Pdfbox Wrapper"); -			byte[] signature = signer.sign(data, byteRange, this.parameters); +			byte[] signature = signer.sign(data, byteRange, this.parameters, this.requestedSignature);  			return signature;  		} catch (PdfAsException e) {  			throw new PdfAsWrappedIOException(e); diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/util/SignatureUtils.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/util/SignatureUtils.java index 28713e1a..4527b92b 100644 --- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/util/SignatureUtils.java +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/util/SignatureUtils.java @@ -1,13 +1,31 @@  package at.gv.egiz.pdfas.lib.util; +import iaik.cms.CMSException; +import iaik.cms.SignedData; +import iaik.cms.SignerInfo; +import iaik.x509.X509Certificate; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.security.SignatureException; +  import org.apache.pdfbox.cos.COSArray;  import org.apache.pdfbox.cos.COSDictionary;  import org.apache.pdfbox.cos.COSName;  import org.apache.pdfbox.pdmodel.PDDocument; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.gv.egiz.pdfas.common.exceptions.PdfAsSignatureException; +import at.gv.egiz.pdfas.lib.api.verify.VerifyResult; +import at.gv.egiz.pdfas.lib.impl.verify.VerifyResultImpl;  public class SignatureUtils { -	public static int countSignatures(PDDocument doc) { +	private static final Logger logger = LoggerFactory +			.getLogger(SignatureUtils.class); + +	public static int countSignatures(PDDocument doc, String sigName) {  		int count = 0;  		COSDictionary trailer = doc.getDocument().getTrailer();  		COSDictionary root = (COSDictionary) trailer @@ -20,10 +38,93 @@ public class SignatureUtils {  			COSDictionary field = (COSDictionary) fields.getObject(i);  			String type = field.getNameAsString("FT");  			if ("Sig".equals(type)) { -				count++; +				String name = field.getString(COSName.T); +				if (name != null) { +					logger.debug("Found Sig: " + name); +					try { +						if (name.startsWith(sigName)) { +							String numberString = name.replace(sigName, ""); + +							logger.debug("Found Number: " + numberString); + +							int SigIDX = Integer.parseInt(numberString); +							if(SigIDX > count) { +								count = SigIDX; +							} +						} +					} catch (Throwable e) { +						logger.error("Failed to extract Signature Name!", e); +					} +				}  			} +  		} + +		count++; +		 +		logger.debug("Returning sig number: " + count);  		return count;  	} + +	 +	public static VerifyResult verifySignature(byte[] signature, byte[] input) throws PdfAsSignatureException { +		//List<VerifyResult> results = new ArrayList<VerifyResult>(); +		try { +			SignedData signedData = new SignedData(new ByteArrayInputStream( +					signature)); + +			signedData.setContent(input); +			 +			// get the signer infos +			SignerInfo[] signerInfos = signedData.getSignerInfos(); +			if (signerInfos.length == 0) { +				throw new PdfAsSignatureException("Invalid Signature (no signer info created!)", null); +			} +			 +			if (signerInfos.length != 1) { +				throw new PdfAsSignatureException("Invalid Signature (multiple signer infos found!)", null); +			} +			// verify the signatures +			//for (int i = 0; i < signerInfos.length; i++) { +				VerifyResultImpl verifyResult = new VerifyResultImpl(); +				//results.add(verifyResult); +				try { +					logger.info("Signature Algo: {}, Digest {}", signedData +							.getSignerInfos()[0].getSignatureAlgorithm(), +							signedData.getSignerInfos()[0].getDigestAlgorithm()); +					// verify the signature for SignerInfo at index i +					X509Certificate signer_cert = signedData.verify(0); +					// if the signature is OK the certificate of the +					// signer is returned +					logger.info("Signature OK from signer: " +							+ signer_cert.getSubjectDN()); +					verifyResult.setSignerCertificate(signer_cert); + +				} catch (SignatureException ex) { +					// if the signature is not OK a SignatureException +					// is thrown +					logger.error( +							"Signature ERROR from signer: " +									+ signedData.getCertificate( +											signerInfos[0] +													.getSignerIdentifier()) +											.getSubjectDN(), ex); + +					verifyResult.setSignerCertificate(signedData +							.getCertificate(signerInfos[0] +									.getSignerIdentifier())); +					throw new PdfAsSignatureException("error.pdf.sig.08", ex); +				} +				 +				return verifyResult; +			//} +		} catch (CMSException e) { +			throw new PdfAsSignatureException("error.pdf.sig.08", e); +		} catch (IOException e) { +			throw new PdfAsSignatureException("error.pdf.sig.08", e); +		} +		 +		 +	}  } diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/sl/util/ISignatureConnector.java b/pdf-as-lib/src/main/java/at/gv/egiz/sl/util/ISignatureConnector.java index fdb95f49..24a1b84d 100644 --- a/pdf-as-lib/src/main/java/at/gv/egiz/sl/util/ISignatureConnector.java +++ b/pdf-as-lib/src/main/java/at/gv/egiz/sl/util/ISignatureConnector.java @@ -26,8 +26,9 @@ package at.gv.egiz.sl.util;  import iaik.x509.X509Certificate;  import at.gv.egiz.pdfas.common.exceptions.PdfAsException;  import at.gv.egiz.pdfas.lib.api.sign.SignParameter; +import at.gv.egiz.pdfas.lib.impl.status.RequestedSignature;  public interface ISignatureConnector {  	public X509Certificate getCertificate(SignParameter parameter) throws PdfAsException; -    public byte[] sign(byte[] input, int[] byteRange, SignParameter parameter) throws PdfAsException; +    public byte[] sign(byte[] input, int[] byteRange, SignParameter parameter, RequestedSignature requestedSignature) throws PdfAsException;  } diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/sl/util/ISignatureConnectorSLWrapper.java b/pdf-as-lib/src/main/java/at/gv/egiz/sl/util/ISignatureConnectorSLWrapper.java index b564c215..077f2f9b 100644 --- a/pdf-as-lib/src/main/java/at/gv/egiz/sl/util/ISignatureConnectorSLWrapper.java +++ b/pdf-as-lib/src/main/java/at/gv/egiz/sl/util/ISignatureConnectorSLWrapper.java @@ -23,24 +23,23 @@   ******************************************************************************/  package at.gv.egiz.sl.util; -import iaik.cms.CMSException; -import iaik.cms.SignedData; -import iaik.cms.SignerInfo;  import iaik.x509.X509Certificate; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.security.SignatureException;  import java.security.cert.CertificateException;  import java.util.Iterator; +import java.util.List;  import org.slf4j.Logger;  import org.slf4j.LoggerFactory;  import at.gv.egiz.pdfas.common.exceptions.PdfAsException;  import at.gv.egiz.pdfas.common.exceptions.PdfAsSignatureException; +import at.gv.egiz.pdfas.common.utils.StreamUtils;  import at.gv.egiz.pdfas.lib.api.sign.SignParameter; -import at.gv.egiz.pdfas.lib.impl.verify.VerifyResultImpl; +import at.gv.egiz.pdfas.lib.api.verify.VerifyResult; +import at.gv.egiz.pdfas.lib.impl.SignResultImpl; +import at.gv.egiz.pdfas.lib.impl.status.RequestedSignature; +import at.gv.egiz.pdfas.lib.util.SignatureUtils;  import at.gv.egiz.sl.schema.CreateCMSSignatureResponseType;  import at.gv.egiz.sl.schema.InfoboxAssocArrayPairType;  import at.gv.egiz.sl.schema.InfoboxReadRequestType; @@ -84,59 +83,20 @@ public class ISignatureConnectorSLWrapper implements ISignatureConnector {  		return certificate;  	} -	public byte[] sign(byte[] input, int[] byteRange, SignParameter parameter) throws PdfAsException { +	public byte[] sign(byte[] input, int[] byteRange,  +			SignParameter parameter, RequestedSignature requestedSignature) throws PdfAsException {  		RequestPackage pack = connector.createCMSRequest(  				input, byteRange, parameter);  		CreateCMSSignatureResponseType response = connector  				.sendCMSRequest(pack, parameter); -		try { -			SignedData signedData = new SignedData(new ByteArrayInputStream( -					response.getCMSSignature())); - -			signedData.setContent(input); - -			// get the signer infos -			SignerInfo[] signerInfos = signedData.getSignerInfos(); -			if (signerInfos.length == 0) { -				throw new PdfAsSignatureException("Invalid Signature (no signer info created!)", null); -			} -			// verify the signatures -			for (int i = 0; i < signerInfos.length; i++) { -				VerifyResultImpl verifyResult = new VerifyResultImpl(); -				try { -					logger.info("Signature Algo: {}, Digest {}", signedData -							.getSignerInfos()[i].getSignatureAlgorithm(), -							signedData.getSignerInfos()[i].getDigestAlgorithm()); -					// verify the signature for SignerInfo at index i -					X509Certificate signer_cert = signedData.verify(i); -					// if the signature is OK the certificate of the -					// signer is returned -					logger.info("Signature OK from signer: " -							+ signer_cert.getSubjectDN()); -					verifyResult.setSignerCertificate(signer_cert); +		 +		VerifyResult verifyResult = SignatureUtils.verifySignature(response.getCMSSignature(), input); -				} catch (SignatureException ex) { -					// if the signature is not OK a SignatureException -					// is thrown -					logger.error( -							"Signature ERROR from signer: " -									+ signedData.getCertificate( -											signerInfos[i] -													.getSignerIdentifier()) -											.getSubjectDN(), ex); - -					verifyResult.setSignerCertificate(signedData -							.getCertificate(signerInfos[i] -									.getSignerIdentifier())); -					throw new PdfAsSignatureException("error.pdf.sig.08", ex); -				} -			} -		} catch (CMSException e) { -			throw new PdfAsSignatureException("error.pdf.sig.08", e); -		} catch (IOException e) { -			throw new PdfAsSignatureException("error.pdf.sig.08", e); +		if(!StreamUtils.dataCompare(requestedSignature.getCertificate().getFingerprintSHA(), +				verifyResult.getSignerCertificate().getFingerprintSHA())) { +			throw new PdfAsSignatureException("Certificates missmatch!");  		} - +		  		return response.getCMSSignature();  	} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/sl/util/MOAConnector.java b/pdf-as-lib/src/main/java/at/gv/egiz/sl/util/MOAConnector.java index 73de30cf..1059dba1 100644 --- a/pdf-as-lib/src/main/java/at/gv/egiz/sl/util/MOAConnector.java +++ b/pdf-as-lib/src/main/java/at/gv/egiz/sl/util/MOAConnector.java @@ -55,10 +55,15 @@ import org.xml.sax.SAXException;  import at.gv.egiz.pdfas.common.exceptions.PdfAsException;  import at.gv.egiz.pdfas.common.exceptions.PdfAsMOAException; +import at.gv.egiz.pdfas.common.exceptions.PdfAsSignatureException;  import at.gv.egiz.pdfas.common.exceptions.PdfAsWrappedIOException;  import at.gv.egiz.pdfas.common.settings.ISettings; +import at.gv.egiz.pdfas.common.utils.StreamUtils;  import at.gv.egiz.pdfas.lib.api.Configuration;  import at.gv.egiz.pdfas.lib.api.sign.SignParameter; +import at.gv.egiz.pdfas.lib.api.verify.VerifyResult; +import at.gv.egiz.pdfas.lib.impl.status.RequestedSignature; +import at.gv.egiz.pdfas.lib.util.SignatureUtils;  public class MOAConnector implements ISignatureConnector { @@ -135,7 +140,8 @@ public class MOAConnector implements ISignatureConnector {  		return builder.build();  	} -	public byte[] sign(byte[] input, int[] byteRange, SignParameter parameter) throws PdfAsException { +	public byte[] sign(byte[] input, int[] byteRange, SignParameter parameter +			, RequestedSignature requestedSignature) throws PdfAsException {  		CloseableHttpClient client = null;  		try {  			client = buildHttpClient(); @@ -220,7 +226,16 @@ public class MOAConnector implements ISignatureConnector {  				if (cmsSignature != null) {  					try { -						return base64.decode(cmsSignature); +						byte[] cmsSignatureData = base64.decode(cmsSignature); +						 +						VerifyResult verifyResult = SignatureUtils.verifySignature(cmsSignatureData, input); + +						if(!StreamUtils.dataCompare(requestedSignature.getCertificate().getFingerprintSHA(), +								verifyResult.getSignerCertificate().getFingerprintSHA())) { +							throw new PdfAsSignatureException("Certificates missmatch!"); +						} +						 +						return cmsSignatureData;  					} catch(Exception e) {  						throw new PdfAsException("error.pdf.io.07", e);  					} | 
