diff options
| author | Andreas Fitzek <andreas.fitzek@iaik.tugraz.at> | 2014-10-08 17:54:06 +0200 | 
|---|---|---|
| committer | Andreas Fitzek <andreas.fitzek@iaik.tugraz.at> | 2014-10-08 17:54:06 +0200 | 
| commit | 6336eb94021158575a15abd0efb8f3089197d0ab (patch) | |
| tree | 87acb392017774639976e6189d8fbf53cfc187c9 /pdf-as-moa/src/main/java/at/gv | |
| parent | 2b01d83855a10ea2dc34ab1231a5548cf3a61bb8 (diff) | |
| download | pdf-as-4-6336eb94021158575a15abd0efb8f3089197d0ab.tar.gz pdf-as-4-6336eb94021158575a15abd0efb8f3089197d0ab.tar.bz2 pdf-as-4-6336eb94021158575a15abd0efb8f3089197d0ab.zip | |
Introduced PDF-AS-MOA
Diffstat (limited to 'pdf-as-moa/src/main/java/at/gv')
| -rw-r--r-- | pdf-as-moa/src/main/java/at/gv/egiz/pdfas/moa/MOAConnector.java | 220 | ||||
| -rw-r--r-- | pdf-as-moa/src/main/java/at/gv/egiz/pdfas/moa/MOAVerifier.java | 197 | 
2 files changed, 417 insertions, 0 deletions
| diff --git a/pdf-as-moa/src/main/java/at/gv/egiz/pdfas/moa/MOAConnector.java b/pdf-as-moa/src/main/java/at/gv/egiz/pdfas/moa/MOAConnector.java new file mode 100644 index 00000000..1b4064a5 --- /dev/null +++ b/pdf-as-moa/src/main/java/at/gv/egiz/pdfas/moa/MOAConnector.java @@ -0,0 +1,220 @@ +/******************************************************************************* + * <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.moa; + +import iaik.x509.X509Certificate; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.security.cert.CertificateException; + +import javax.xml.ws.BindingProvider; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.gv.e_government.reference.namespace.moa._20020822.CMSContentBaseType; +import at.gv.e_government.reference.namespace.moa._20020822.CMSDataObjectInfoType.DataObject; +import at.gv.e_government.reference.namespace.moa._20020822.CreateCMSSignatureRequest; +import at.gv.e_government.reference.namespace.moa._20020822.CreateCMSSignatureRequestType.SingleSignatureInfo; +import at.gv.e_government.reference.namespace.moa._20020822.CreateCMSSignatureRequestType.SingleSignatureInfo.DataObjectInfo; +import at.gv.e_government.reference.namespace.moa._20020822.CreateCMSSignatureResponseType; +import at.gv.e_government.reference.namespace.moa._20020822.ErrorResponseType; +import at.gv.e_government.reference.namespace.moa._20020822.MetaInfoType; +import at.gv.e_government.reference.namespace.moa._20020822_.MOAFault; +import at.gv.e_government.reference.namespace.moa._20020822_.SignatureCreationPortType; +import at.gv.e_government.reference.namespace.moa._20020822_.SignatureCreationService; +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.IConfigurationConstants; +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; +import at.gv.egiz.sl.util.ISignatureConnector; + +public class MOAConnector implements ISignatureConnector, +		IConfigurationConstants { + +	private static final Logger logger = LoggerFactory +			.getLogger(MOAConnector.class); + +	private X509Certificate certificate; +	private String moaEndpoint; +	private String keyIdentifier; + +	public MOAConnector(Configuration config) throws CertificateException, +			FileNotFoundException, IOException { +		if (config.getValue(MOA_SIGN_CERTIFICATE) == null) { +			logger.error(MOA_SIGN_CERTIFICATE +					+ " not configured for MOA connector"); +			throw new PdfAsWrappedIOException(new PdfAsException( +					"Please configure: " + MOA_SIGN_CERTIFICATE +							+ " to use MOA connector")); +		} + +		if (!(config instanceof ISettings)) { +			logger.error("Configuration is no instance of ISettings"); +			throw new PdfAsWrappedIOException(new PdfAsException( +					"Configuration is no instance of ISettings")); +		} + +		ISettings settings = (ISettings) config; + +		String certificateValue = config.getValue(MOA_SIGN_CERTIFICATE); + +		if (certificateValue.startsWith("http")) { +			logger.info("Loading certificate from url: " + certificateValue); +			 +			try { +				URL certificateURL = new URL(certificateValue); +			 +				this.certificate = new X509Certificate(certificateURL.openStream()); +			} catch(MalformedURLException e) { +				logger.error(certificateValue +						+ " is not a valid url but!"); +				throw new PdfAsWrappedIOException(new PdfAsException( +						certificateValue +						+ " is not a valid url but!")); +			} +		} else { + +			File certFile = new File(certificateValue); +			if (!certFile.isAbsolute()) { +				certificateValue = settings.getWorkingDirectory() + "/" +						+ config.getValue(MOA_SIGN_CERTIFICATE); +				certFile = new File(certificateValue); +			} + +			logger.info("Loading certificate from file: " + certificateValue); + +			this.certificate = new X509Certificate( +					new FileInputStream(certFile)); +		} +		this.moaEndpoint = config.getValue(MOA_SIGN_URL); +		this.keyIdentifier = config.getValue(MOA_SIGN_KEY_ID); +	} + +	public X509Certificate getCertificate(SignParameter parameter) +			throws PdfAsException { +		return this.certificate; +	} + +	public byte[] sign(byte[] input, int[] byteRange, SignParameter parameter, +			RequestedSignature requestedSignature) throws PdfAsException { +		 +		logger.info("signing with MOA @ " + this.moaEndpoint); +		URL moaUrl; +		try { +			moaUrl = new URL(this.moaEndpoint); +		} catch (MalformedURLException e1) { +			throw new PdfAsException("Invalid MOA endpoint!", e1); +		} +		SignatureCreationService service = new SignatureCreationService(moaUrl); +		 +		SignatureCreationPortType creationPort = service.getSignatureCreationPort(); +		BindingProvider provider = (BindingProvider) creationPort; +		provider.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, this.moaEndpoint); +		 +		CreateCMSSignatureRequest request = new CreateCMSSignatureRequest(); +		request.setKeyIdentifier(this.keyIdentifier.trim()); +		SingleSignatureInfo sigInfo = new SingleSignatureInfo(); +		sigInfo.setSecurityLayerConformity(Boolean.TRUE); +		DataObjectInfo dataObjectInfo = new DataObjectInfo(); +		dataObjectInfo.setStructure("detached"); +		DataObject dataObject = new DataObject(); +		MetaInfoType metaInfoType = new MetaInfoType(); +		 +		metaInfoType.setMimeType("application/pdf"); +		 +		dataObject.setMetaInfo(metaInfoType); +		 +		CMSContentBaseType content = new CMSContentBaseType(); +		content.setBase64Content(input); +		 +		dataObject.setContent(content); +		 +		dataObjectInfo.setDataObject(dataObject); +		sigInfo.setDataObjectInfo(dataObjectInfo); +		request.getSingleSignatureInfo().add(sigInfo); +		 +		CreateCMSSignatureResponseType response; +		try { +			response = creationPort.createCMSSignature(request); +		} catch (MOAFault e) { +			logger.error("MOA signing failed!", e); +			if(e.getFaultInfo() != null) { +				throw new PdfAsMOAException(e.getFaultInfo().getErrorCode().toString(),  +					e.getFaultInfo().getInfo(), +					"", ""); +			} else { +				throw new PdfAsMOAException("",  +						e.getMessage(), +						"", ""); +			} +		} +		 +		if(response.getCMSSignatureOrErrorResponse().size() != 1) { +			throw new PdfAsException("Invalid Response Count [" + response.getCMSSignatureOrErrorResponse().size() +					+ "] from MOA!"); +		} +		 +		Object resp = response.getCMSSignatureOrErrorResponse().get(0); +		if(resp instanceof byte[]) { +			// done the signature! +			byte[] cmsSignatureData = (byte[])resp; + +			VerifyResult verifyResult = SignatureUtils +					.verifySignature(cmsSignatureData, input); + +			if (!StreamUtils.dataCompare(requestedSignature +					.getCertificate().getFingerprintSHA(), +					((X509Certificate) verifyResult +							.getSignerCertificate()) +							.getFingerprintSHA())) { +				throw new PdfAsSignatureException( +						"Certificates missmatch!"); +			} + +			return cmsSignatureData; +		} else if(resp instanceof ErrorResponseType) { +			ErrorResponseType err = (ErrorResponseType) resp; +			 +			throw new PdfAsMOAException("", "", +					err.getInfo(), err.getErrorCode().toString()); +			 +		} else { +			throw new PdfAsException("MOA response is not byte[] nor error but: " + resp.getClass().getName()); +		} +	} +} diff --git a/pdf-as-moa/src/main/java/at/gv/egiz/pdfas/moa/MOAVerifier.java b/pdf-as-moa/src/main/java/at/gv/egiz/pdfas/moa/MOAVerifier.java new file mode 100644 index 00000000..42af02f7 --- /dev/null +++ b/pdf-as-moa/src/main/java/at/gv/egiz/pdfas/moa/MOAVerifier.java @@ -0,0 +1,197 @@ +package at.gv.egiz.pdfas.moa; + +import iaik.x509.X509Certificate; + +import java.net.URL; +import java.util.ArrayList; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.List; + +import javax.xml.bind.JAXBElement; +import javax.xml.datatype.DatatypeFactory; +import javax.xml.datatype.XMLGregorianCalendar; +import javax.xml.ws.BindingProvider; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3._2000._09.xmldsig.KeyInfoType; +import org.w3._2000._09.xmldsig.X509DataType; + +import com.sun.org.apache.xerces.internal.dom.ElementNSImpl; + +import at.gv.e_government.reference.namespace.moa._20020822.CMSContentBaseType; +import at.gv.e_government.reference.namespace.moa._20020822.CMSDataObjectOptionalMetaType; +import at.gv.e_government.reference.namespace.moa._20020822.CheckResultType; +import at.gv.e_government.reference.namespace.moa._20020822.MetaInfoType; +import at.gv.e_government.reference.namespace.moa._20020822.VerifyCMSSignatureRequest; +import at.gv.e_government.reference.namespace.moa._20020822.VerifyCMSSignatureResponseType; +import at.gv.e_government.reference.namespace.moa._20020822_.SignatureVerificationPortType; +import at.gv.e_government.reference.namespace.moa._20020822_.SignatureVerificationService; +import at.gv.egiz.pdfas.common.exceptions.PdfAsException; +import at.gv.egiz.pdfas.lib.api.Configuration; +import at.gv.egiz.pdfas.lib.api.verify.VerifyParameter.SignatureVerificationLevel; +import at.gv.egiz.pdfas.lib.api.verify.VerifyResult; +import at.gv.egiz.pdfas.lib.impl.verify.IVerifier; +import at.gv.egiz.pdfas.lib.impl.verify.SignatureCheckImpl; +import at.gv.egiz.pdfas.lib.impl.verify.VerifyResultImpl; + +public class MOAVerifier implements IVerifier { + +	private static final Logger logger = LoggerFactory +			.getLogger(MOAVerifier.class); + +	private static final String MOA_VERIFY_URL = "moa.verify.url"; +	private static final String MOA_VERIFY_TRUSTPROFILE = "moa.verify.TrustProfileID"; + +	private String moaEndpoint; +	private String moaTrustProfile; + +	 +	public List<VerifyResult> verify(byte[] signature, byte[] signatureContent, +			Date verificationTime) throws PdfAsException { +		List<VerifyResult> resultList = new ArrayList<VerifyResult>(); +		try { +			logger.info("verification with MOA @ " + this.moaEndpoint); +			URL moaUrl = new URL(this.moaEndpoint); +			 +			SignatureVerificationService service = new SignatureVerificationService(moaUrl); +			 +			SignatureVerificationPortType verificationPort = service.getSignatureVerificationPort(); +			BindingProvider provider = (BindingProvider) verificationPort; +			provider.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, this.moaEndpoint); +			VerifyCMSSignatureRequest verifyCMSSignatureRequest = new VerifyCMSSignatureRequest(); +			verifyCMSSignatureRequest.setTrustProfileID(this.moaTrustProfile); +			verifyCMSSignatureRequest.setCMSSignature(signature); +			CMSDataObjectOptionalMetaType metaDataType = new CMSDataObjectOptionalMetaType(); +			 +			MetaInfoType metaInfoType = new MetaInfoType(); +			metaInfoType.setDescription("PDF Document"); +			metaInfoType.setMimeType("application/pdf"); +			metaDataType.setMetaInfo(metaInfoType); +			 +			CMSContentBaseType contentBase = new CMSContentBaseType(); +			contentBase.setBase64Content(signatureContent); +			metaDataType.setContent(contentBase); +			 +			verifyCMSSignatureRequest.setDataObject(metaDataType); +			 +			if (verificationTime != null) { +				GregorianCalendar c = new GregorianCalendar(); +				c.setTime(verificationTime); +				XMLGregorianCalendar date2 = DatatypeFactory.newInstance().newXMLGregorianCalendar(c); +				verifyCMSSignatureRequest.setDateTime(date2); +			} +			 +			VerifyCMSSignatureResponseType response = verificationPort +					.verifyCMSSignature(verifyCMSSignatureRequest); +			 +			logger.debug("Got Verify Response from MOA"); +			 +			List<JAXBElement<?>> verifySequence = response.getSignerInfoAndSignatureCheckAndCertificateCheck(); +			 +			VerifyResultImpl result = new VerifyResultImpl(); +			 +			result.setCertificateCheck(new SignatureCheckImpl(1,"")); +			result.setValueCheckCode(new SignatureCheckImpl(1,"")); +			result.setVerificationDone(true); +			result.setSignatureData(signatureContent); +			 +			for (int i = 0; i < verifySequence.size(); i++) { +				// +				 +				JAXBElement<?> element = verifySequence.get(i); + +				logger.debug(" ---------------------- "); +				logger.debug("Name: " + element.getName().getLocalPart()); +				logger.debug("Class: " + element.getValue().getClass().getName()); +				 +				if(element.getName().getLocalPart().equals("SignerInfo")) { +					if(!(element.getValue() instanceof KeyInfoType)) { +						// TODO throw Exception +					} +					KeyInfoType keyInfo = (KeyInfoType)element.getValue(); + +					for(Object obj : keyInfo.getContent()) { +						logger.debug("KeyInfo: " + obj.getClass().toString()); +						if(obj instanceof JAXBElement<?>) { +							JAXBElement<?> ele = (JAXBElement<?>)obj; +							logger.debug("KeyInfo: " + ele.getName().getLocalPart()); +							logger.debug("KeyInfo: " + ele.getValue().getClass().getName()); +							if(ele.getName().getLocalPart().equals("X509Data") &&  +									ele.getValue() instanceof X509DataType) { +								X509DataType x509Data = (X509DataType)ele.getValue(); +								for(Object o : x509Data.getX509IssuerSerialOrX509SKIOrX509SubjectName()) { +									logger.debug("X509 class: " + o.getClass().getName()); +									if(o instanceof JAXBElement<?>) { +										JAXBElement<?> e = (JAXBElement<?>)o; +										logger.debug("X509 class CHILD: " + e.getName().getLocalPart()); +										logger.debug("X509 class CHILD: " + e.getValue().getClass().getName()); +										if(e.getName().getLocalPart().equals("X509Certificate")) { +											if(e.getValue() instanceof byte[]) { +												X509Certificate signerCertificate = new X509Certificate((byte[])e.getValue()); +												result.setSignerCertificate(signerCertificate); +											} +										} +									} /*else if(o instanceof ElementNSImpl) { +										logger.debug("ElementNSImpl name: " + ((ElementNSImpl) o).getNodeValue()); +										for(int j = 0; j < ((ElementNSImpl) o).getAttributes().getLength(); j++) { +											 +											//logger.debug("ElementNSImpl name: " + ((ElementNSImpl) o).getAttributes().item(j)..getTextContent()); +										} +									}*/ +								} +							} +						} +					} +					 +				} else if(element.getName().getLocalPart().equals("SignatureCheck")) { +					 +					if(!(element.getValue() instanceof CheckResultType)) { +						// TODO throw Exception +					} +					 +					CheckResultType checkResult = (CheckResultType)element.getValue(); +					 +					result.setValueCheckCode(new SignatureCheckImpl( +							checkResult.getCode().intValue(),  +							(checkResult.getInfo() != null) ?  +									checkResult.getInfo().toString() : "" +								)); +					 +				} else if(element.getName().getLocalPart().equals("CertificateCheck")) { +					 +					if(!(element.getValue() instanceof CheckResultType)) { +						// TODO throw Exception +					} +					 +					CheckResultType checkResult = (CheckResultType)element.getValue(); +					 +					result.setCertificateCheck(new SignatureCheckImpl( +							checkResult.getCode().intValue(),  +							(checkResult.getInfo() != null) ?  +									checkResult.getInfo().toString() : "" +								)); +				} +				 +				logger.debug(" ---------------------- "); +			} +			resultList.add(result); +		} catch (Throwable e) { +			logger.error("Verification failed", e); +			throw new PdfAsException("error.pdf.verify.02", e); +		} +		return resultList; +	} +	 +	public void setConfiguration(Configuration config) { +		this.moaEndpoint = config.getValue(MOA_VERIFY_URL); +		this.moaTrustProfile = config.getValue(MOA_VERIFY_TRUSTPROFILE); +	} + +	@Override +	public SignatureVerificationLevel getLevel() { +		return SignatureVerificationLevel.FULL_VERIFICATION; +	} + +} | 
