aboutsummaryrefslogtreecommitdiff
path: root/pdf-as-moa/src/main/java/at/gv/egiz/pdfas
diff options
context:
space:
mode:
authorAndreas Fitzek <andreas.fitzek@iaik.tugraz.at>2014-10-08 17:54:06 +0200
committerAndreas Fitzek <andreas.fitzek@iaik.tugraz.at>2014-10-08 17:54:06 +0200
commit6336eb94021158575a15abd0efb8f3089197d0ab (patch)
tree87acb392017774639976e6189d8fbf53cfc187c9 /pdf-as-moa/src/main/java/at/gv/egiz/pdfas
parent2b01d83855a10ea2dc34ab1231a5548cf3a61bb8 (diff)
downloadpdf-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/egiz/pdfas')
-rw-r--r--pdf-as-moa/src/main/java/at/gv/egiz/pdfas/moa/MOAConnector.java220
-rw-r--r--pdf-as-moa/src/main/java/at/gv/egiz/pdfas/moa/MOAVerifier.java197
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;
+ }
+
+}