From 53ae98cdfa510650c1e015efd0d11a96ad4dc87a Mon Sep 17 00:00:00 2001 From: Andreas Fitzek Date: Mon, 20 Jun 2016 12:45:07 +0200 Subject: ASiC Library added --- .../gv/egiz/asic/impl/ASiCBaseFormatFactory.java | 134 +++++++++++++++ .../java/at/gv/egiz/asic/impl/ASiCContainer.java | 22 +++ .../egiz/asic/impl/ASiCExtendedFormatFactory.java | 51 ++++++ .../main/java/at/gv/egiz/asic/impl/ASiCImpl.java | 73 ++++++++ .../java/at/gv/egiz/asic/impl/ASiCMOAVerifier.java | 87 ++++++++++ .../gv/egiz/asic/impl/ASiCSimpleFormatFactory.java | 54 ++++++ .../java/at/gv/egiz/asic/impl/EntryHandler.java | 14 ++ .../main/java/at/gv/egiz/asic/impl/Verifier.java | 18 ++ .../gv/egiz/asic/impl/ZipCommentReaderStream.java | 180 ++++++++++++++++++++ .../gv/egiz/asic/impl/handler/AllDataHandler.java | 28 ++++ .../at/gv/egiz/asic/impl/handler/BaseHandler.java | 27 +++ .../at/gv/egiz/asic/impl/handler/CAdESHandler.java | 20 +++ .../impl/handler/EvidenceERSRecordHandler.java | 18 ++ .../impl/handler/EvidenceXMLRecordHandler.java | 15 ++ .../impl/handler/ExtendedASiCCAdESHandler.java | 13 ++ .../impl/handler/ExtendedASiCXAdESHandler.java | 11 ++ .../handler/ExtendedEvidenceERSRecordHandler.java | 11 ++ .../handler/ExtendedEvidenceXMLRecordHandler.java | 11 ++ .../gv/egiz/asic/impl/handler/HandlerSorter.java | 16 ++ .../gv/egiz/asic/impl/handler/MetaInfHandler.java | 33 ++++ .../gv/egiz/asic/impl/handler/MimefileHandler.java | 36 ++++ .../egiz/asic/impl/handler/SignatureHandler.java | 36 ++++ .../asic/impl/handler/SimpleASiCCAdESHandler.java | 13 ++ .../asic/impl/handler/SimpleASiCXAdESHandler.java | 13 ++ .../handler/SimpleEvidenceERSRecordHandler.java | 13 ++ .../handler/SimpleEvidenceXMLRecordHandler.java | 13 ++ .../at/gv/egiz/asic/impl/handler/XAdESHandler.java | 17 ++ .../gv/egiz/asic/impl/verifier/BaseVerifier.java | 61 +++++++ .../gv/egiz/asic/impl/verifier/CAdESVerifier.java | 43 +++++ .../asic/impl/verifier/ExtendedCAdESVerifier.java | 168 +++++++++++++++++++ .../asic/impl/verifier/ExtendedXAdESVerifier.java | 184 +++++++++++++++++++++ .../asic/impl/verifier/SimpleCAdESVerifier.java | 45 +++++ .../asic/impl/verifier/SimpleXAdESVerifier.java | 128 ++++++++++++++ .../gv/egiz/asic/impl/verifier/XAdESVerifier.java | 54 ++++++ 34 files changed, 1660 insertions(+) create mode 100644 moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/ASiCBaseFormatFactory.java create mode 100644 moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/ASiCContainer.java create mode 100644 moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/ASiCExtendedFormatFactory.java create mode 100644 moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/ASiCImpl.java create mode 100644 moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/ASiCMOAVerifier.java create mode 100644 moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/ASiCSimpleFormatFactory.java create mode 100644 moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/EntryHandler.java create mode 100644 moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/Verifier.java create mode 100644 moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/ZipCommentReaderStream.java create mode 100644 moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/AllDataHandler.java create mode 100644 moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/BaseHandler.java create mode 100644 moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/CAdESHandler.java create mode 100644 moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/EvidenceERSRecordHandler.java create mode 100644 moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/EvidenceXMLRecordHandler.java create mode 100644 moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/ExtendedASiCCAdESHandler.java create mode 100644 moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/ExtendedASiCXAdESHandler.java create mode 100644 moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/ExtendedEvidenceERSRecordHandler.java create mode 100644 moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/ExtendedEvidenceXMLRecordHandler.java create mode 100644 moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/HandlerSorter.java create mode 100644 moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/MetaInfHandler.java create mode 100644 moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/MimefileHandler.java create mode 100644 moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/SignatureHandler.java create mode 100644 moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/SimpleASiCCAdESHandler.java create mode 100644 moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/SimpleASiCXAdESHandler.java create mode 100644 moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/SimpleEvidenceERSRecordHandler.java create mode 100644 moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/SimpleEvidenceXMLRecordHandler.java create mode 100644 moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/XAdESHandler.java create mode 100644 moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/verifier/BaseVerifier.java create mode 100644 moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/verifier/CAdESVerifier.java create mode 100644 moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/verifier/ExtendedCAdESVerifier.java create mode 100644 moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/verifier/ExtendedXAdESVerifier.java create mode 100644 moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/verifier/SimpleCAdESVerifier.java create mode 100644 moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/verifier/SimpleXAdESVerifier.java create mode 100644 moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/verifier/XAdESVerifier.java (limited to 'moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl') diff --git a/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/ASiCBaseFormatFactory.java b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/ASiCBaseFormatFactory.java new file mode 100644 index 0000000..bce179d --- /dev/null +++ b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/ASiCBaseFormatFactory.java @@ -0,0 +1,134 @@ +package at.gv.egiz.asic.impl; + +import at.gv.egiz.asic.api.ASiC; +import at.gv.egiz.asic.api.ASiCEntry; +import at.gv.egiz.asic.api.ASiCFormat; +import at.gv.egiz.asic.impl.handler.*; +import at.gv.egovernment.moa.spss.MOAApplicationException; +import at.gv.egovernment.moa.spss.MOAException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + +/** + * Created by Andreas Fitzek on 6/15/16. + */ +public abstract class ASiCBaseFormatFactory implements ASiCContainer { + + private static final Logger logger = LoggerFactory.getLogger(ASiCBaseFormatFactory.class); + + protected boolean cadesSigned = false; + protected boolean xadesSigned = false; + protected boolean timestamped = false; + + protected String mimeType = null; + + protected List signatureEntries = new ArrayList(); + protected List dataEntries = new ArrayList(); + protected List informationEntries = new ArrayList(); + + protected List handlers = new ArrayList(); + + @Override + public void addDataEntry(ASiCEntry entry) { + this.dataEntries.add(entry); + } + + @Override + public void addSignatureEntry(ASiCEntry entry) { + this.signatureEntries.add(entry); + } + + @Override + public void addInformationEntry(ASiCEntry entry) { + this.informationEntries.add(entry); + } + + public ASiCBaseFormatFactory() { + handlers.add(new MimefileHandler()); + handlers.add(new MetaInfHandler()); + handlers.add(new AllDataHandler()); + } + + public abstract ASiCFormat factoryFormat(); + + protected abstract void validate() throws MOAException; + + public ASiC createASiC(InputStream is) throws MOAException { + + ZipCommentReaderStream commentReaderStream = new ZipCommentReaderStream(is); + + ZipInputStream zipInputStream = new ZipInputStream(commentReaderStream); + + try { + for (ZipEntry entry = zipInputStream.getNextEntry(); entry != null; entry = zipInputStream.getNextEntry()) { + String entryName = entry.getName(); + + Iterator handlerIterator = this.handlers.iterator(); + while (handlerIterator.hasNext()) { + EntryHandler entryHandler = handlerIterator.next(); + + if (entryHandler.handle(entryName, zipInputStream, this)) { + break; + } + } + } + } catch(IOException e) { + logger.info("Failed to read from ASiC Container", e); + throw new MOAApplicationException("asic.0007", null); + } + + + if(this.mimeType == null) { + String mimeTypeComment = commentReaderStream.getFileComment(); + if(mimeTypeComment != null) { + this.mimeType = mimeTypeComment; + } + } + + this.validate(); + + // unpack and retrieve all available information on ASiC signature + return new ASiCImpl(this.factoryFormat(), this.xadesSigned, this.cadesSigned, this.signatureEntries, dataEntries, this.informationEntries); + } + + @Override + public void setMimeType(String mimeType) { + this.mimeType = mimeType; + } + + public void setIsXAdES() throws MOAException { + if(this.cadesSigned) { + throw new MOAApplicationException("asic.0010", null); + } + this.xadesSigned = true; + } + + public void setIsCAdES() throws MOAException { + if(this.xadesSigned) { + throw new MOAApplicationException("asic.0010", null); + } + this.cadesSigned = true; + } + + public void setIsTimestamped() throws MOAException { + throw new MOAApplicationException("asic.0013", null); + } + + @Override + public void setIsEvidenceERS() throws MOAException { + throw new MOAApplicationException("asic.0011", null); + } + + @Override + public void setIsEvidenceXML() throws MOAException { + throw new MOAApplicationException("asic.0012", null); + } +} diff --git a/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/ASiCContainer.java b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/ASiCContainer.java new file mode 100644 index 0000000..73d1566 --- /dev/null +++ b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/ASiCContainer.java @@ -0,0 +1,22 @@ +package at.gv.egiz.asic.impl; + +import at.gv.egiz.asic.api.ASiCEntry; +import at.gv.egovernment.moa.spss.MOAException; + +/** + * Created by afitzek on 6/15/16. + */ +public interface ASiCContainer { + + public void setMimeType(String mimeType); + public void addDataEntry(ASiCEntry entry); + public void addSignatureEntry(ASiCEntry entry); + public void addInformationEntry(ASiCEntry entry); + + public void setIsXAdES() throws MOAException; + public void setIsCAdES() throws MOAException; + public void setIsEvidenceERS() throws MOAException; + public void setIsEvidenceXML() throws MOAException; + public void setIsTimestamped() throws MOAException; + +} diff --git a/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/ASiCExtendedFormatFactory.java b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/ASiCExtendedFormatFactory.java new file mode 100644 index 0000000..f71552b --- /dev/null +++ b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/ASiCExtendedFormatFactory.java @@ -0,0 +1,51 @@ +package at.gv.egiz.asic.impl; + +import at.gv.egiz.asic.api.ASiC; +import at.gv.egiz.asic.api.ASiCFormat; +import at.gv.egiz.asic.impl.handler.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + +/** + * Created by Andreas Fitzek on 6/15/16. + */ +public class ASiCExtendedFormatFactory extends ASiCBaseFormatFactory { + + private static final Logger logger = LoggerFactory.getLogger(ASiCExtendedFormatFactory.class); + + public ASiCExtendedFormatFactory() { + super(); + handlers.add(new ExtendedASiCCAdESHandler()); + handlers.add(new ExtendedASiCXAdESHandler()); + handlers.add(new ExtendedEvidenceERSRecordHandler()); + handlers.add(new ExtendedEvidenceXMLRecordHandler()); + + Collections.sort(handlers, new HandlerSorter()); + + logger.debug("Handler ordering for ASiCExtendedFormatFactory"); + Iterator handlerIterator = this.handlers.iterator(); + while(handlerIterator.hasNext()) { + EntryHandler entryHandler = handlerIterator.next(); + logger.debug(" " + entryHandler.getPriority() + " " + entryHandler.getClass().getSimpleName()); + } + } + + @Override + protected void validate() { + + } + + @Override + public ASiCFormat factoryFormat() { + return ASiCFormat.ASiCE; + } +} diff --git a/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/ASiCImpl.java b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/ASiCImpl.java new file mode 100644 index 0000000..c78385a --- /dev/null +++ b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/ASiCImpl.java @@ -0,0 +1,73 @@ +package at.gv.egiz.asic.impl; + +import at.gv.egiz.asic.api.ASiC; +import at.gv.egiz.asic.api.ASiCEntry; +import at.gv.egiz.asic.api.ASiCFormat; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by Andreas Fitzek on 6/15/16. + */ +public class ASiCImpl implements ASiC { + + private ASiCFormat format; + private boolean xades; + private boolean cades; + + protected List signatureEntries = new ArrayList(); + protected List dataEntries = new ArrayList(); + protected List informationEntries = new ArrayList(); + + public ASiCImpl(ASiCFormat format, boolean xades, boolean cades, List signatureEntries, List dataEntries, List informationEntries) { + this.format = format; + this.xades = xades; + this.cades = cades; + this.signatureEntries = signatureEntries; + this.dataEntries = dataEntries; + this.informationEntries = informationEntries; + } + + @Override + public ASiCFormat getFormat() { + return format; + } + + @Override + public boolean isXAdES() { + return xades; + } + + @Override + public boolean isCAdES() { + return cades; + } + + @Override + public List getSignaturesEntries() { + return signatureEntries; + } + + @Override + public List getDataEntries() { + return dataEntries; + } + + @Override + public List getInformationEntries() { + return informationEntries; + } + + @Override + public String toString() { + return "ASiCImpl{" + + "format=" + format + + ", xades=" + xades + + ", cades=" + cades + + ", signatureEntries=" + signatureEntries + + ", dataEntries=" + dataEntries + + ", informationEntries=" + informationEntries + + '}'; + } +} diff --git a/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/ASiCMOAVerifier.java b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/ASiCMOAVerifier.java new file mode 100644 index 0000000..51392da --- /dev/null +++ b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/ASiCMOAVerifier.java @@ -0,0 +1,87 @@ +package at.gv.egiz.asic.impl; + +import at.gv.egiz.asic.ASiCManifestType; +import at.gv.egiz.asic.DataObjectReferenceType; +import at.gv.egiz.asic.ReferenceType; +import at.gv.egiz.asic.XAdESSignaturesType; +import at.gv.egiz.asic.api.*; +import at.gv.egiz.asic.impl.verifier.ExtendedCAdESVerifier; +import at.gv.egiz.asic.impl.verifier.ExtendedXAdESVerifier; +import at.gv.egiz.asic.impl.verifier.SimpleCAdESVerifier; +import at.gv.egiz.asic.impl.verifier.SimpleXAdESVerifier; +import at.gv.egovernment.moa.spss.MOAApplicationException; +import at.gv.egovernment.moa.spss.MOAException; +import at.gv.egovernment.moa.spss.MOARuntimeException; +import at.gv.egovernment.moa.spss.MOASystemException; +import at.gv.egovernment.moa.spss.api.SPSSFactory; +import at.gv.egovernment.moa.spss.api.cmsverify.*; +import at.gv.egovernment.moa.spss.api.common.*; +import at.gv.egovernment.moa.spss.api.impl.SPSSFactoryImpl; +import at.gv.egovernment.moa.spss.api.xmlverify.SupplementProfile; +import at.gv.egovernment.moa.spss.api.xmlverify.VerifySignatureInfo; +import at.gv.egovernment.moa.spss.api.xmlverify.VerifySignatureLocation; +import at.gv.egovernment.moa.spss.api.xmlverify.VerifyXMLSignatureRequest; +import at.gv.egovernment.moa.spss.server.invoke.CMSSignatureVerificationInvoker; +import at.gv.egovernment.moa.spss.server.invoke.VerifyCMSSignatureResponseBuilder; +import at.gv.egovernment.moa.spss.server.invoke.XMLSignatureVerificationInvoker; +import iaik.server.cmspdfverify.CertificateValidationResult; +import org.apache.commons.codec.binary.Hex; +import org.apache.commons.io.IOUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.xml.bind.DataBindingException; +import javax.xml.bind.JAXB; +import javax.xml.crypto.dsig.Reference; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.security.DigestInputStream; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.cert.X509Certificate; +import java.util.*; + +/** + * Created by Andreas Fitzek on 6/15/16. + */ +public class ASiCMOAVerifier implements ASiCVerifier { + + private static final Logger logger = LoggerFactory.getLogger(ASiCMOAVerifier.class); + + private List verifierMap = new ArrayList(); + + public ASiCMOAVerifier() { + verifierMap.add(new SimpleCAdESVerifier()); + verifierMap.add(new SimpleXAdESVerifier()); + verifierMap.add(new ExtendedCAdESVerifier()); + verifierMap.add(new ExtendedXAdESVerifier()); + } + + @Override + public List verify(ASiC asic, String trustProfileID, Date date) throws MOAException { + List response = new ArrayList(); + boolean handled = false; + + Iterator verifierIterator = verifierMap.iterator(); + + while (verifierIterator.hasNext()) { + Verifier verifier = verifierIterator.next(); + if (verifier.handles(asic)) { + verifier.verify(asic, trustProfileID, date, response); + handled = true; + break; + } + } + + if (!handled) { + logger.warn("Cannot handle ASiC: {}", asic); + throw new MOASystemException("asic.0016", null); + } + + return response; + } + + +} diff --git a/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/ASiCSimpleFormatFactory.java b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/ASiCSimpleFormatFactory.java new file mode 100644 index 0000000..90b3081 --- /dev/null +++ b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/ASiCSimpleFormatFactory.java @@ -0,0 +1,54 @@ +package at.gv.egiz.asic.impl; + +import at.gv.egiz.asic.api.ASiCFormat; +import at.gv.egiz.asic.impl.handler.*; +import at.gv.egovernment.moa.spss.MOAApplicationException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Collections; +import java.util.Iterator; + +/** + * Created by Andreas Fitzek on 6/15/16. + */ +public class ASiCSimpleFormatFactory extends ASiCBaseFormatFactory { + + private static final Logger logger = LoggerFactory.getLogger(ASiCSimpleFormatFactory.class); + + public ASiCSimpleFormatFactory() { + super(); + + handlers.add(new SimpleASiCCAdESHandler()); + handlers.add(new SimpleASiCXAdESHandler()); + handlers.add(new SimpleEvidenceXMLRecordHandler()); + handlers.add(new SimpleEvidenceERSRecordHandler()); + + Collections.sort(handlers, new HandlerSorter()); + + logger.debug("Handler ordering for ASiCSimpleFormatFactory"); + Iterator handlerIterator = this.handlers.iterator(); + while(handlerIterator.hasNext()) { + EntryHandler entryHandler = handlerIterator.next(); + logger.debug(" " + entryHandler.getPriority() + " " + entryHandler.getClass().getSimpleName()); + } + } + + @Override + protected void validate() throws MOAApplicationException { + if(this.dataEntries.size() != 1) { + logger.warn("There can only be one data entry for ASiC signatures in simple format"); + throw new MOAApplicationException("asic.0014", null); + } + + if(this.signatureEntries.size() != 1) { + logger.warn("There can only be one signature entry for ASiC signatures in simple format"); + throw new MOAApplicationException("asic.0015", null); + } + } + + @Override + public ASiCFormat factoryFormat() { + return ASiCFormat.ASiCS; + } +} diff --git a/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/EntryHandler.java b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/EntryHandler.java new file mode 100644 index 0000000..7767b33 --- /dev/null +++ b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/EntryHandler.java @@ -0,0 +1,14 @@ +package at.gv.egiz.asic.impl; + +import at.gv.egovernment.moa.spss.MOAException; + +import java.io.IOException; +import java.io.InputStream; + +/** + * Created by afitzek on 6/15/16. + */ +public interface EntryHandler { + public int getPriority(); + public boolean handle(String entryName, InputStream is, ASiCContainer container) throws IOException, MOAException; +} diff --git a/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/Verifier.java b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/Verifier.java new file mode 100644 index 0000000..95a2450 --- /dev/null +++ b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/Verifier.java @@ -0,0 +1,18 @@ +package at.gv.egiz.asic.impl; + +import at.gv.egiz.asic.api.ASiC; +import at.gv.egiz.asic.api.ASiCVerificationResult; +import at.gv.egovernment.moa.spss.MOAException; + +import java.util.Date; +import java.util.List; + +/** + * Created by Andreas Fitzek on 6/17/16. + */ +public interface Verifier { + public boolean handles(ASiC asic); + + public void verify(ASiC asic, String trustProfileID, Date date, List response) + throws MOAException; +} diff --git a/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/ZipCommentReaderStream.java b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/ZipCommentReaderStream.java new file mode 100644 index 0000000..93b7651 --- /dev/null +++ b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/ZipCommentReaderStream.java @@ -0,0 +1,180 @@ +package at.gv.egiz.asic.impl; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; + +/** + * Created by afitzek on 6/15/16. + */ +public class ZipCommentReaderStream extends InputStream { + + private InputStream inputStream; + + private int[] tempBuffer = new int[22]; + + private int[] commentBuffer = null; + + private int commentBufferContentLen = 0; + private int commentBufferContentOff = 0; + + private int tempBufferContentLen = 0; + private int tempBufferContentOff = 0; + + private String fileComment = null; + + private static final byte[] directoryRecord = new byte[] { (byte)0x50, (byte)0x4b, 0x05, 0x06 }; + + public ZipCommentReaderStream(InputStream inputStream) { + this.inputStream = inputStream; + } + + private int readIntIntoBuffer() throws IOException { + int tValue = this.inputStream.read(); + + if(this.tempBuffer.length <= tempBufferContentOff) { + throw new IOException("Temp Buffer is out of space! @ " + tempBufferContentOff); + } + + this.tempBuffer[tempBufferContentOff] = tValue; + tempBufferContentOff++; + tempBufferContentLen++; + + return tValue; + } + + private int readIntIntoCommentBuffer() throws IOException { + int tValue = this.inputStream.read(); + + if(this.commentBuffer.length <= commentBufferContentOff) { + throw new IOException("Comment Buffer is out of space! @ " + commentBufferContentOff); + } + + this.commentBuffer[commentBufferContentOff] = tValue; + commentBufferContentOff++; + commentBufferContentLen++; + + return tValue; + } + + private void checkMagicBytes() throws IOException { + boolean foundMagic = true; + tempBufferContentOff = 0; + tempBufferContentLen = 0; + for(int i = 1; i < directoryRecord.length; i++) { + int tValue = readIntIntoBuffer(); + if(tValue != directoryRecord[i]) { + foundMagic = false; + break; + } + if(tValue < 0) { + // Found EOF + return; + } + } + + if(foundMagic) { + // read input stream until comment length + for(int i = 0; i < 16; i++) { + int tValue = readIntIntoBuffer(); + + if(tValue < 0) { + // Found EOF + return; + } + } + + int commentlengthHigh = readIntIntoBuffer(); + + if(commentlengthHigh < 0) { + // Found EOF + return; + } + + int commentlengthLow = readIntIntoBuffer(); + + if(commentlengthLow < 0) { + // Found EOF + return; + } + + int commentLength = commentlengthLow * 255 + commentlengthHigh; + + if(commentLength == 0) { + return; + } + + this.commentBuffer = new int[commentLength]; + + commentBufferContentOff = 0; + commentBufferContentLen = 0; + + // read comment buffer string + for(int i = 0; i < commentLength; i++) { + int tValue = readIntIntoCommentBuffer(); + + if(tValue < 0) { + // Found EOF + return; + } + } + + byte[] stringBuffer = new byte[this.commentBuffer.length]; + + for(int i = 0; i < stringBuffer.length; i++) { + stringBuffer[i] = (byte)this.commentBuffer[i]; + } + + this.fileComment = new String(stringBuffer); + } + } + + @Override + public int read() throws IOException { + int value = -1; + if(tempBufferContentLen > 0) { + value = this.tempBuffer[tempBufferContentOff]; + tempBufferContentOff++; + + // reset temp buffer + if(tempBufferContentOff >= tempBufferContentLen) { + tempBufferContentOff = 0; + tempBufferContentLen = 0; + } + + return value; + } + + if(this.commentBuffer != null) { + value = this.commentBuffer[commentBufferContentOff]; + + commentBufferContentOff++; + + // reset comment buffer + if(commentBufferContentOff >= commentBufferContentLen) { + commentBufferContentOff = 0; + commentBufferContentLen = 0; + this.commentBuffer = null; + } + + return value; + } + + value = this.inputStream.read(); + + if(value == directoryRecord[0] && this.fileComment == null) { + // might have found start of magic bytes + checkMagicBytes(); + // reset buffer offsets + tempBufferContentOff = 0; + commentBufferContentOff = 0; + } + + return value; + } + + public String getFileComment() { + return this.fileComment; + } +} diff --git a/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/AllDataHandler.java b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/AllDataHandler.java new file mode 100644 index 0000000..fa31bfc --- /dev/null +++ b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/AllDataHandler.java @@ -0,0 +1,28 @@ +package at.gv.egiz.asic.impl.handler; + +import at.gv.egiz.asic.api.ASiCConstants; +import at.gv.egiz.asic.impl.ASiCContainer; +import at.gv.egiz.asic.api.ASiCEntry; +import at.gv.egiz.asic.impl.EntryHandler; + +import java.io.IOException; +import java.io.InputStream; + +/** + * Created by afitzek on 6/15/16. + */ +public class AllDataHandler extends BaseHandler implements EntryHandler, ASiCConstants { + @Override + public int getPriority() { + return 100; + } + + @Override + public boolean handle(String entryName, InputStream is, ASiCContainer container) throws IOException { + + ASiCEntry entry = buildASiCEntry(entryName, is); + container.addDataEntry(entry); + + return true; + } +} diff --git a/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/BaseHandler.java b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/BaseHandler.java new file mode 100644 index 0000000..2b5ca9a --- /dev/null +++ b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/BaseHandler.java @@ -0,0 +1,27 @@ +package at.gv.egiz.asic.impl.handler; + +import at.gv.egiz.asic.api.ASiCConstants; +import at.gv.egiz.asic.api.ASiCEntry; +import at.gv.egiz.asic.impl.EntryHandler; +import org.apache.commons.io.IOUtils; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; + +/** + * Created by Andreas Fitzek on 6/15/16. + */ +public abstract class BaseHandler implements EntryHandler, ASiCConstants { + + protected ASiCEntry buildASiCEntry(String entryName, InputStream is) throws IOException { + ASiCEntry entry = new ASiCEntry(); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + IOUtils.copy(is, baos); + entry.setContents(new ByteArrayInputStream(baos.toByteArray())); + entry.setEntryName(entryName); + return entry; + } + +} diff --git a/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/CAdESHandler.java b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/CAdESHandler.java new file mode 100644 index 0000000..3ee97fc --- /dev/null +++ b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/CAdESHandler.java @@ -0,0 +1,20 @@ +package at.gv.egiz.asic.impl.handler; + +import at.gv.egiz.asic.api.ASiCConstants; +import at.gv.egiz.asic.impl.ASiCContainer; +import at.gv.egiz.asic.impl.EntryHandler; +import at.gv.egovernment.moa.spss.MOAException; + +import java.io.IOException; +import java.io.InputStream; + +/** + * Created by Andreas Fitzek on 6/15/16. + */ +public abstract class CAdESHandler extends SignatureHandler implements EntryHandler, ASiCConstants { + + @Override + protected void setType(ASiCContainer container) throws MOAException { + container.setIsCAdES(); + } +} diff --git a/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/EvidenceERSRecordHandler.java b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/EvidenceERSRecordHandler.java new file mode 100644 index 0000000..f89c6d0 --- /dev/null +++ b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/EvidenceERSRecordHandler.java @@ -0,0 +1,18 @@ +package at.gv.egiz.asic.impl.handler; + +import at.gv.egiz.asic.impl.ASiCContainer; +import at.gv.egovernment.moa.spss.MOAException; + +import java.io.IOException; +import java.io.InputStream; + +/** + * Created by Andreas Fitzek on 6/17/16. + */ +public abstract class EvidenceERSRecordHandler extends SignatureHandler { + + @Override + protected void setType(ASiCContainer container) throws MOAException { + container.setIsEvidenceERS(); + } +} diff --git a/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/EvidenceXMLRecordHandler.java b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/EvidenceXMLRecordHandler.java new file mode 100644 index 0000000..4516bb0 --- /dev/null +++ b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/EvidenceXMLRecordHandler.java @@ -0,0 +1,15 @@ +package at.gv.egiz.asic.impl.handler; + +import at.gv.egiz.asic.impl.ASiCContainer; +import at.gv.egovernment.moa.spss.MOAException; + +/** + * Created by Andreas Fitzek on 6/17/16. + */ +public abstract class EvidenceXMLRecordHandler extends SignatureHandler { + + @Override + protected void setType(ASiCContainer container) throws MOAException { + container.setIsEvidenceXML(); + } +} diff --git a/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/ExtendedASiCCAdESHandler.java b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/ExtendedASiCCAdESHandler.java new file mode 100644 index 0000000..464bcf6 --- /dev/null +++ b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/ExtendedASiCCAdESHandler.java @@ -0,0 +1,13 @@ +package at.gv.egiz.asic.impl.handler; + +import at.gv.egiz.asic.api.ASiCConstants; + +/** + * Created by Andreas Fitzek on 6/15/16. + */ +public class ExtendedASiCCAdESHandler extends CAdESHandler { + @Override + protected boolean matches(String entryName) { + return entryName.endsWith(".p7s") && entryName.startsWith(FILE_META_INF) && entryName.contains("signature"); + } +} diff --git a/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/ExtendedASiCXAdESHandler.java b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/ExtendedASiCXAdESHandler.java new file mode 100644 index 0000000..28b21a3 --- /dev/null +++ b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/ExtendedASiCXAdESHandler.java @@ -0,0 +1,11 @@ +package at.gv.egiz.asic.impl.handler; + +/** + * Created by Andreas Fitzek on 6/15/16. + */ +public class ExtendedASiCXAdESHandler extends XAdESHandler { + @Override + protected boolean matches(String entryName) { + return entryName.endsWith(".xml") && entryName.startsWith(FILE_META_INF) && entryName.contains("signature"); + } +} diff --git a/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/ExtendedEvidenceERSRecordHandler.java b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/ExtendedEvidenceERSRecordHandler.java new file mode 100644 index 0000000..ccf9224 --- /dev/null +++ b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/ExtendedEvidenceERSRecordHandler.java @@ -0,0 +1,11 @@ +package at.gv.egiz.asic.impl.handler; + +/** + * Created by Andreas Fitzek on 6/17/16. + */ +public class ExtendedEvidenceERSRecordHandler extends EvidenceERSRecordHandler { + @Override + protected boolean matches(String entryName) { + return entryName.endsWith(".ers") && entryName.startsWith(FILE_META_INF) && entryName.contains("evidencerecord"); + } +} diff --git a/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/ExtendedEvidenceXMLRecordHandler.java b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/ExtendedEvidenceXMLRecordHandler.java new file mode 100644 index 0000000..d24d61b --- /dev/null +++ b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/ExtendedEvidenceXMLRecordHandler.java @@ -0,0 +1,11 @@ +package at.gv.egiz.asic.impl.handler; + +/** + * Created by Andreas Fitzek on 6/17/16. + */ +public class ExtendedEvidenceXMLRecordHandler extends EvidenceERSRecordHandler { + @Override + protected boolean matches(String entryName) { + return entryName.endsWith(".xml") && entryName.startsWith(FILE_META_INF) && entryName.contains("evidencerecord"); + } +} diff --git a/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/HandlerSorter.java b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/HandlerSorter.java new file mode 100644 index 0000000..36a215d --- /dev/null +++ b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/HandlerSorter.java @@ -0,0 +1,16 @@ +package at.gv.egiz.asic.impl.handler; + +import at.gv.egiz.asic.impl.EntryHandler; + +import java.util.Comparator; + +/** + * Created by afitzek on 6/15/16. + */ +public class HandlerSorter implements Comparator { + + @Override + public int compare(EntryHandler o1, EntryHandler o2) { + return Integer.compare(o1.getPriority(), o2.getPriority()); + } +} diff --git a/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/MetaInfHandler.java b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/MetaInfHandler.java new file mode 100644 index 0000000..ec4f101 --- /dev/null +++ b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/MetaInfHandler.java @@ -0,0 +1,33 @@ +package at.gv.egiz.asic.impl.handler; + +import at.gv.egiz.asic.api.ASiCConstants; +import at.gv.egiz.asic.impl.ASiCContainer; +import at.gv.egiz.asic.api.ASiCEntry; +import at.gv.egiz.asic.impl.EntryHandler; + +import java.io.IOException; +import java.io.InputStream; + +/** + * Created by Andreas Fitzek on 6/15/16. + */ +public class MetaInfHandler extends BaseHandler implements EntryHandler, ASiCConstants { + @Override + public int getPriority() { + return 20; + } + + @Override + public boolean handle(String entryName, InputStream is, ASiCContainer container) throws IOException { + + boolean metainf = entryName.startsWith(FILE_META_INF); + + if(metainf) { + ASiCEntry entry = buildASiCEntry(entryName, is); + container.addInformationEntry(entry); + return true; + } + + return false; + } +} diff --git a/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/MimefileHandler.java b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/MimefileHandler.java new file mode 100644 index 0000000..68fc87e --- /dev/null +++ b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/MimefileHandler.java @@ -0,0 +1,36 @@ +package at.gv.egiz.asic.impl.handler; + +import at.gv.egiz.asic.api.ASiCConstants; +import at.gv.egiz.asic.impl.ASiCContainer; +import at.gv.egiz.asic.impl.EntryHandler; +import org.apache.commons.io.IOUtils; + +import java.io.IOException; +import java.io.InputStream; + +/** + * Created by afitzek on 6/15/16. + */ +public class MimefileHandler implements EntryHandler, ASiCConstants { + + private boolean isMimeType(String entryName) { + return FILE_MIME_TYPE.equalsIgnoreCase(entryName); + } + + @Override + public int getPriority() { + return 1; + } + + @Override + public boolean handle(String entryName, InputStream is, ASiCContainer container) throws IOException { + + if(isMimeType(entryName)) { + String mimeType = IOUtils.toString(is, "UTF-8"); + container.setMimeType(mimeType); + return true; + } + + return false; + } +} diff --git a/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/SignatureHandler.java b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/SignatureHandler.java new file mode 100644 index 0000000..621c9d4 --- /dev/null +++ b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/SignatureHandler.java @@ -0,0 +1,36 @@ +package at.gv.egiz.asic.impl.handler; + +import at.gv.egiz.asic.impl.ASiCContainer; +import at.gv.egovernment.moa.spss.MOAException; + +import java.io.IOException; +import java.io.InputStream; + +/** + * Created by Andreas Fitzek on 6/15/16. + */ +public abstract class SignatureHandler extends BaseHandler { + + @Override + public int getPriority() { + return 0; + } + + protected abstract boolean matches(String entryName); + + protected abstract void setType(ASiCContainer container) throws MOAException; + + @Override + public boolean handle(String entryName, InputStream is, ASiCContainer container) throws IOException, MOAException { + boolean signature = this.matches(entryName); + + if(signature) { + this.setType(container); + container.addSignatureEntry(buildASiCEntry(entryName, is)); + return true; + } + + return false; + } + +} diff --git a/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/SimpleASiCCAdESHandler.java b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/SimpleASiCCAdESHandler.java new file mode 100644 index 0000000..fdeda41 --- /dev/null +++ b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/SimpleASiCCAdESHandler.java @@ -0,0 +1,13 @@ +package at.gv.egiz.asic.impl.handler; + +import at.gv.egiz.asic.api.ASiCConstants; + +/** + * Created by Andreas Fitzek on 6/15/16. + */ +public class SimpleASiCCAdESHandler extends CAdESHandler { + @Override + protected boolean matches(String entryName) { + return (ASiCConstants.FILE_META_INF + "signature.p7s").equalsIgnoreCase(entryName); + } +} diff --git a/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/SimpleASiCXAdESHandler.java b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/SimpleASiCXAdESHandler.java new file mode 100644 index 0000000..66a7546 --- /dev/null +++ b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/SimpleASiCXAdESHandler.java @@ -0,0 +1,13 @@ +package at.gv.egiz.asic.impl.handler; + +import at.gv.egiz.asic.api.ASiCConstants; + +/** + * Created by Andreas Fitzek on 6/15/16. + */ +public class SimpleASiCXAdESHandler extends XAdESHandler { + @Override + protected boolean matches(String entryName) { + return (ASiCConstants.FILE_META_INF + "signatures.xml").equalsIgnoreCase(entryName); + } +} diff --git a/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/SimpleEvidenceERSRecordHandler.java b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/SimpleEvidenceERSRecordHandler.java new file mode 100644 index 0000000..58221f5 --- /dev/null +++ b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/SimpleEvidenceERSRecordHandler.java @@ -0,0 +1,13 @@ +package at.gv.egiz.asic.impl.handler; + +import at.gv.egiz.asic.api.ASiCConstants; + +/** + * Created by Andreas Fitzek on 6/17/16. + */ +public class SimpleEvidenceERSRecordHandler extends EvidenceERSRecordHandler { + @Override + protected boolean matches(String entryName) { + return (ASiCConstants.FILE_META_INF + "evidencerecord.ers").equalsIgnoreCase(entryName); + } +} diff --git a/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/SimpleEvidenceXMLRecordHandler.java b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/SimpleEvidenceXMLRecordHandler.java new file mode 100644 index 0000000..dacc218 --- /dev/null +++ b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/SimpleEvidenceXMLRecordHandler.java @@ -0,0 +1,13 @@ +package at.gv.egiz.asic.impl.handler; + +import at.gv.egiz.asic.api.ASiCConstants; + +/** + * Created by Andreas Fitzek on 6/17/16. + */ +public class SimpleEvidenceXMLRecordHandler extends EvidenceERSRecordHandler { + @Override + protected boolean matches(String entryName) { + return (ASiCConstants.FILE_META_INF + "evidencerecord.xml").equalsIgnoreCase(entryName); + } +} diff --git a/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/XAdESHandler.java b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/XAdESHandler.java new file mode 100644 index 0000000..ff19759 --- /dev/null +++ b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/handler/XAdESHandler.java @@ -0,0 +1,17 @@ +package at.gv.egiz.asic.impl.handler; + +import at.gv.egiz.asic.api.ASiCConstants; +import at.gv.egiz.asic.impl.ASiCContainer; +import at.gv.egiz.asic.impl.EntryHandler; +import at.gv.egovernment.moa.spss.MOAException; + +/** + * Created by afitzek on 6/15/16. + */ +public abstract class XAdESHandler extends SignatureHandler implements EntryHandler, ASiCConstants { + + @Override + protected void setType(ASiCContainer container) throws MOAException { + container.setIsXAdES(); + } +} diff --git a/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/verifier/BaseVerifier.java b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/verifier/BaseVerifier.java new file mode 100644 index 0000000..a0bc516 --- /dev/null +++ b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/verifier/BaseVerifier.java @@ -0,0 +1,61 @@ +package at.gv.egiz.asic.impl.verifier; + +import at.gv.egiz.asic.impl.Verifier; +import at.gv.egovernment.moa.spss.api.cmsverify.VerifyCMSSignatureResponse; +import org.apache.commons.codec.binary.Hex; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +/** + * Created by Andreas Fitzek on 6/17/16. + */ +public abstract class BaseVerifier implements Verifier { + + protected static Map hashTranslator = new HashMap(); + + static { + hashTranslator.put("http://www.w3.org/2000/09/xmldsig#sha1", "SHA-1"); + hashTranslator.put("http://www.w3.org/2001/04/xmldsig-more#sha224", "SHA-224"); + hashTranslator.put("http://www.w3.org/2001/04/xmlenc#sha256", "SHA-256"); + hashTranslator.put("http://www.w3.org/2001/04/xmldsig-more#sha384", "SHA-384"); + hashTranslator.put("http://www.w3.org/2001/04/xmlenc#sha512", "SHA-512"); + hashTranslator.put("http://www.w3.org/2001/04/xmlenc#ripemd160", "RIPEMD-160"); + } + + private static final Logger logger = LoggerFactory.getLogger(BaseVerifier.class); + + protected boolean compareHash(byte[] reference, byte[] calculated, String refName) { + String referenceHex = Hex.encodeHexString(reference); + String calculatedHex = Hex.encodeHexString(calculated); + if(Arrays.equals(reference, calculated)) { + logger.info("Digest from manifest do match for {}", refName); + return true; + } else { + logger.info("Digest from manifest do not match for {}", refName); + logger.info("Digest from manifest for {} : {}", refName, referenceHex); + logger.info("Digest from calculated for {} : {}", refName, calculatedHex); + return false; + } + } + + protected MessageDigest getMessageDigestFromURI(String uri) { + try { + + String algo = hashTranslator.get(uri); + + if(algo == null) { + algo = uri; + } + + return MessageDigest.getInstance(algo); + } catch (NoSuchAlgorithmException e) { + return null; + } + } +} diff --git a/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/verifier/CAdESVerifier.java b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/verifier/CAdESVerifier.java new file mode 100644 index 0000000..5ab677c --- /dev/null +++ b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/verifier/CAdESVerifier.java @@ -0,0 +1,43 @@ +package at.gv.egiz.asic.impl.verifier; + +import at.gv.egiz.asic.api.ASiC; +import at.gv.egovernment.moa.spss.MOAException; +import at.gv.egovernment.moa.spss.api.SPSSFactory; +import at.gv.egovernment.moa.spss.api.cmsverify.CMSContent; +import at.gv.egovernment.moa.spss.api.cmsverify.CMSDataObject; +import at.gv.egovernment.moa.spss.api.cmsverify.VerifyCMSSignatureRequest; +import at.gv.egovernment.moa.spss.api.cmsverify.VerifyCMSSignatureResponse; +import at.gv.egovernment.moa.spss.server.invoke.CMSSignatureVerificationInvoker; + +import java.io.InputStream; +import java.util.Date; + +/** + * Created by Andreas Fitzek on 6/17/16. + */ +public abstract class CAdESVerifier extends BaseVerifier { + @Override + public boolean handles(ASiC asic) { + return asic.isCAdES(); + } + + protected VerifyCMSSignatureResponse runCMSVerification(InputStream signedData, InputStream cmsSignature, + String trustProfileID, Date date) throws MOAException { + CMSContent cmsContent = SPSSFactory.getInstance().createCMSContent(signedData); + CMSDataObject cmsDataObject = SPSSFactory.getInstance().createCMSDataObject(null, cmsContent, null, null); + + VerifyCMSSignatureRequest verifyCMSSignatureRequest = + SPSSFactory.getInstance().createVerifyCMSSignatureRequest( + VerifyCMSSignatureRequest.ALL_SIGNATORIES, + date, + cmsSignature, + cmsDataObject, + trustProfileID, + false, + true); + + VerifyCMSSignatureResponse verifyResponse = CMSSignatureVerificationInvoker.getInstance().verifyCMSSignature( + verifyCMSSignatureRequest); + return verifyResponse; + } +} diff --git a/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/verifier/ExtendedCAdESVerifier.java b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/verifier/ExtendedCAdESVerifier.java new file mode 100644 index 0000000..e71f263 --- /dev/null +++ b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/verifier/ExtendedCAdESVerifier.java @@ -0,0 +1,168 @@ +package at.gv.egiz.asic.impl.verifier; + +import at.gv.egiz.asic.ASiCManifestType; +import at.gv.egiz.asic.DataObjectReferenceType; +import at.gv.egiz.asic.api.ASiC; +import at.gv.egiz.asic.api.ASiCEntry; +import at.gv.egiz.asic.api.ASiCFormat; +import at.gv.egiz.asic.api.ASiCVerificationResult; +import at.gv.egovernment.moa.spss.MOAApplicationException; +import at.gv.egovernment.moa.spss.MOAException; +import at.gv.egovernment.moa.spss.MOASystemException; +import at.gv.egovernment.moa.spss.api.SPSSFactory; +import at.gv.egovernment.moa.spss.api.cmsverify.*; +import at.gv.egovernment.moa.spss.api.common.CheckResult; +import at.gv.egovernment.moa.spss.api.common.SignerInfo; +import at.gv.egovernment.moa.spss.server.invoke.CMSSignatureVerificationInvoker; +import org.apache.commons.codec.binary.Hex; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.xml.bind.JAXB; +import java.io.IOException; +import java.security.DigestInputStream; +import java.security.MessageDigest; +import java.util.ArrayList; +import java.util.Date; +import java.util.Iterator; +import java.util.List; + +/** + * Created by Andreas Fitzek on 6/17/16. + */ +public class ExtendedCAdESVerifier extends CAdESVerifier { + + private static final Logger logger = LoggerFactory.getLogger(ExtendedCAdESVerifier.class); + + @Override + public boolean handles(ASiC asic) { + return super.handles(asic) && ASiCFormat.ASiCE.equals(asic.getFormat()); + } + + @Override + public void verify(ASiC asic, String trustProfileID, Date date, List response) throws MOAException { + try { + Iterator informationsIterator = asic.getInformationEntries().iterator(); + + while (informationsIterator.hasNext()) { + ASiCEntry informationEntry = informationsIterator.next(); + + if (informationEntry.getEntryName().startsWith("META-INF/") && informationEntry.getEntryName().endsWith(".xml") + && informationEntry.getEntryName().contains("ASiCManifest")) { + // Got ASiC Manifest + ASiCManifestType asiCManifestType = JAXB.unmarshal(informationEntry.getContents(), ASiCManifestType.class); + String signatureName = asiCManifestType.getSigReference().getURI(); + + ASiCEntry cadesSignature = null; + + // find referenced signature + Iterator cadesSignatureIterator = asic.getSignaturesEntries().iterator(); + + while (cadesSignatureIterator.hasNext()) { + ASiCEntry tmpCadesSignature = cadesSignatureIterator.next(); + if (signatureName.equalsIgnoreCase(tmpCadesSignature.getEntryName())) { + cadesSignature = tmpCadesSignature; + break; + } + } + + if (cadesSignature == null) { + throw new MOAApplicationException("asic.0004", new Object[]{signatureName}); + } + + // verify all references + + boolean allReferencesValid = true; + List signedFiles = new ArrayList(); + Iterator dataObjectReferenceTypeIterator = asiCManifestType.getDataObjectReference().iterator(); + while (dataObjectReferenceTypeIterator.hasNext()) { + DataObjectReferenceType dataObjectReferenceType = dataObjectReferenceTypeIterator.next(); + + String mdURI = dataObjectReferenceType.getDigestMethod().getAlgorithm(); + String uri = dataObjectReferenceType.getURI(); + signedFiles.add(uri); + + Iterator dataEntryIterator = asic.getDataEntries().iterator(); + + while (dataEntryIterator.hasNext()) { + ASiCEntry dataEntry = dataEntryIterator.next(); + if (uri.equalsIgnoreCase(dataEntry.getEntryName())) { + MessageDigest md = this.getMessageDigestFromURI(mdURI); + if (md == null) { + throw new MOAApplicationException("asic.0005", new Object[]{mdURI}); + } + DigestInputStream dis = new DigestInputStream(dataEntry.getContents(), md); + byte[] buffer = new byte[8096]; + while (dis.read(buffer) > 0) ; + + if (!this.compareHash(dataObjectReferenceType.getDigestValue(), md.digest(), uri)) { + allReferencesValid = false; + } + + dataEntry.getContents().reset(); + break; + } + } + } + + if (allReferencesValid) { + logger.info("ASiCManifest {} references do match data files!", + informationEntry.getEntryName()); + } + + informationEntry.getContents().reset(); + MessageDigest md = this.getMessageDigestFromURI("SHA-256"); + DigestInputStream dis = new DigestInputStream(informationEntry.getContents(), md); + + VerifyCMSSignatureResponse verifyResponse = + this.runCMSVerification(dis, cadesSignature.getContents(), trustProfileID, date); + + dis.close(); + + String fullDigest = Hex.encodeHexString(md.digest()); + logger.info("CMS Input data {}", fullDigest); + + if (!allReferencesValid) { + logger.warn("ASiCManifest {} References do not match data files!", + informationEntry.getEntryName()); + List responseElements = new ArrayList(); + + SignerInfo signerInfo; + + + // add SignerInfo element + Iterator responseElementIterator = verifyResponse.getResponseElements().iterator(); + while (responseElementIterator.hasNext()) { + VerifyCMSSignatureResponseElement orig = (VerifyCMSSignatureResponseElement) + responseElementIterator.next(); + + CheckResult signatureCheck; + CheckResult certificateCheck; + + // add SignatureCheck element + signatureCheck = SPSSFactory.getInstance().createCheckResult(1, null); + + // build the response element + VerifyCMSSignatureResponseElement responseElement = + SPSSFactory.getInstance().createVerifyCMSSignatureResponseElement( + orig.getSignerInfo(), + signatureCheck, + orig.getCertificateCheck(), + orig.getAdESFormResults(), + orig.getExtendedCertificateCheck()); + responseElements.add(responseElement); + } + VerifyCMSSignatureResponse verifyCMSSignatureResponse = SPSSFactory.getInstance(). + createVerifyCMSSignatureResponse(responseElements); + response.add(new ASiCVerificationResult(signedFiles, verifyCMSSignatureResponse)); + continue; + } else { + response.add(new ASiCVerificationResult(signedFiles, verifyResponse)); + } + } + } + } catch (IOException ex) { + throw new MOASystemException("asic.0003", null, ex); + } + } +} diff --git a/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/verifier/ExtendedXAdESVerifier.java b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/verifier/ExtendedXAdESVerifier.java new file mode 100644 index 0000000..58f0185 --- /dev/null +++ b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/verifier/ExtendedXAdESVerifier.java @@ -0,0 +1,184 @@ +package at.gv.egiz.asic.impl.verifier; + +import at.gv.egiz.asic.ReferenceType; +import at.gv.egiz.asic.SignatureType; +import at.gv.egiz.asic.XAdESSignaturesType; +import at.gv.egiz.asic.api.ASiC; +import at.gv.egiz.asic.api.ASiCEntry; +import at.gv.egiz.asic.api.ASiCFormat; +import at.gv.egiz.asic.api.ASiCVerificationResult; +import at.gv.egovernment.moa.spss.MOAException; +import at.gv.egovernment.moa.spss.MOARuntimeException; +import at.gv.egovernment.moa.spss.MOASystemException; +import at.gv.egovernment.moa.spss.api.SPSSFactory; +import at.gv.egovernment.moa.spss.api.common.Content; +import at.gv.egovernment.moa.spss.api.common.XMLDataObjectAssociation; +import at.gv.egovernment.moa.spss.api.impl.SPSSFactoryImpl; +import at.gv.egovernment.moa.spss.api.xmlverify.SupplementProfile; +import at.gv.egovernment.moa.spss.api.xmlverify.VerifySignatureInfo; +import at.gv.egovernment.moa.spss.api.xmlverify.VerifySignatureLocation; +import at.gv.egovernment.moa.spss.api.xmlverify.VerifyXMLSignatureRequest; +import at.gv.egovernment.moa.spss.server.invoke.XMLSignatureVerificationInvoker; +import at.gv.egovernment.moaspss.util.URLEncoder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.*; +import org.xml.sax.SAXException; + +import javax.xml.bind.*; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import java.io.*; +import java.util.*; + +/** + * Created by Andreas Fitzek on 6/17/16. + */ +public class ExtendedXAdESVerifier extends XAdESVerifier { + + private static final Logger logger = LoggerFactory.getLogger(ExtendedXAdESVerifier.class); + + private void resetStream(InputStream is) { + try { + is.reset(); + } catch (IOException e) { + throw new MOARuntimeException("Failed to reset inputStream", null, e); + } + } + + @Override + public void verify(ASiC asic, String trustProfileID, Date date, List response) throws MOAException { + try { + Iterator xadesSignatureIterator = asic.getSignaturesEntries().iterator(); + + while (xadesSignatureIterator.hasNext()) { + ASiCEntry xadesSignature = xadesSignatureIterator.next(); + + List xmlSignatures = null; + //int signatureSize = 0; + + + // TODO: support not only XAdESSignaturesType object 4.4.3.2 +// XAdESSignaturesType xAdESSignaturesType = JAXB.unmarshal(xadesSignature.getContents(), XAdESSignaturesType.class); + // signatureSize = xAdESSignaturesType.getSignature().size(); + + // this.resetStream(xadesSignature.getContents()); + DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); + dbFactory.setNamespaceAware(true); + //dbFactory.setValidating(true); + DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); + Document doc = dBuilder.parse(xadesSignature.getContents()); + + this.resetStream(xadesSignature.getContents()); + + org.w3c.dom.Element rootElement = doc.getDocumentElement(); + + if ("http://www.w3.org/2000/09/xmldsig#".equals(rootElement.getNamespaceURI()) && + "Signature".equals(rootElement.getTagName())) { + JAXBContext jc = JAXBContext.newInstance("at.gv.egiz.asic"); + JAXBElement xmlSignatureJaxb = jc.createUnmarshaller().unmarshal(rootElement, SignatureType.class); + SignatureType xmlSignature = xmlSignatureJaxb.getValue(); + xmlSignatures = new ArrayList(); + xmlSignatures.add(xmlSignature); + } else if ("http://uri.etsi.org/02918/v1.2.1#".equals(rootElement.getNamespaceURI()) && + "XAdESSignatures".equals(rootElement.getLocalName())) { + XAdESSignaturesType xAdESSignaturesType = JAXB.unmarshal(xadesSignature.getContents(), XAdESSignaturesType.class); + xmlSignatures = xAdESSignaturesType.getSignature(); + } else { + NodeList childrenNodes = rootElement.getChildNodes(); + for(int i = 0; i < childrenNodes.getLength(); i++) { + Node node = childrenNodes.item(i); + JAXBContext jc = JAXBContext.newInstance("at.gv.egiz.asic"); + xmlSignatures = new ArrayList(); + if ("http://www.w3.org/2000/09/xmldsig#".equals(node.getNamespaceURI()) && + "Signature".equals(rootElement.getTagName())) { + JAXBElement xmlSignatureJaxb = jc.createUnmarshaller().unmarshal(rootElement, SignatureType.class); + SignatureType xmlSignature = xmlSignatureJaxb.getValue(); + xmlSignatures.add(xmlSignature); + } + } + } + + + this.resetStream(xadesSignature.getContents()); + + Map namespaces = new HashMap(); + + //namespaces.put("asic", "http://uri.etsi.org/02918/v1.2.1#"); + namespaces.put("ds", "http://www.w3.org/2000/09/xmldsig#"); + + for (int i = 0; i < xmlSignatures.size(); i++) { + //NodeList nodes = (NodeList) result; + + //for(int i = 0; i < nodes.getLength(); i++) { + //Node node = nodes.item(i); + //JAXBContext jc = JAXBContext.newInstance( "at.gv.egiz.asic" ); + //JAXBElement xmlSignatureJaxb = jc.createUnmarshaller().unmarshal(node, SignatureType.class); + //SignatureType xmlSignature = xmlSignatureJaxb.getValue(); + List signedFiles = new ArrayList(); + + //Iterator it = xmlSignature.getSignedInfo().getReference().iterator(); + Iterator it = xmlSignatures.get(i).getSignedInfo().getReference().iterator(); + while (it.hasNext()) { + ReferenceType refType = it.next(); + if (!refType.getURI().startsWith("#")) { + signedFiles.add(refType.getURI()); + } + } + + Iterator dataEntryIterator = asic.getDataEntries().iterator(); + + Content content = SPSSFactory.getInstance().createContent(xadesSignature.getContents(), null); + + List supplementsList = new ArrayList(); + while (dataEntryIterator.hasNext()) { + ASiCEntry dataEntry = dataEntryIterator.next(); + dataEntry.getContents().reset(); + String entryName = URLEncoder.encode(dataEntry.getEntryName(), "UTF-8") + .replaceAll("\\+", "%20") + .replaceAll("\\%21", "!") + .replaceAll("\\%2F", "/") + //.replaceAll("\\%27", "'") + //.replaceAll("\\%28", "(") + //.replaceAll("\\%29", ")") + .replaceAll("\\%7E", "~"); + logger.info("Adding Entry : {}", entryName); + Content dataContent = SPSSFactory.getInstance().createContent(dataEntry.getContents(), entryName); + XMLDataObjectAssociation association = SPSSFactoryImpl.getInstance().createXMLDataObjectAssociation(null, dataContent); + SupplementProfile profile = SPSSFactoryImpl.getInstance().createSupplementProfile(association); + supplementsList.add(profile); + } + String location = "(//ds:Signature)[" + (i + 1) + "]"; + + VerifySignatureLocation verifySignatureLocation = SPSSFactory.getInstance().createVerifySignatureLocation( + location, namespaces); + + VerifySignatureInfo verifySignatureInfo = SPSSFactory.getInstance().createVerifySignatureInfo(content, verifySignatureLocation); + + VerifyXMLSignatureRequest verifyXMLSignatureRequest = SPSSFactory.getInstance().createVerifyXMLSignatureRequest( + date, verifySignatureInfo, supplementsList, null, false, trustProfileID, true); + + response.add(new ASiCVerificationResult(signedFiles, + XMLSignatureVerificationInvoker.getInstance().verifyXMLSignature(verifyXMLSignatureRequest))); + } + } + } catch( UnsupportedEncodingException e) { + logger.error("UTF8 encoding not supported by system. MOA will not work on this system!", e); + throw new MOARuntimeException("asic.0003", null, e); + } catch (IOException ex) { + throw new MOASystemException("asic.0003", null, ex); + } catch (ParserConfigurationException e) { + throw new MOASystemException("asic.0003", null, e); + } catch (SAXException e) { + throw new MOASystemException("asic.0003", null, e); + } catch (JAXBException e) { + throw new MOASystemException("asic.0003", null, e); + } + } + + @Override + public boolean handles(ASiC asic) { + return super.handles(asic) && ASiCFormat.ASiCE.equals(asic.getFormat()); + } +} diff --git a/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/verifier/SimpleCAdESVerifier.java b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/verifier/SimpleCAdESVerifier.java new file mode 100644 index 0000000..b86e290 --- /dev/null +++ b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/verifier/SimpleCAdESVerifier.java @@ -0,0 +1,45 @@ +package at.gv.egiz.asic.impl.verifier; + +import at.gv.egiz.asic.api.ASiC; +import at.gv.egiz.asic.api.ASiCEntry; +import at.gv.egiz.asic.api.ASiCFormat; +import at.gv.egiz.asic.api.ASiCVerificationResult; +import at.gv.egovernment.moa.spss.MOAException; +import at.gv.egovernment.moa.spss.api.SPSSFactory; +import at.gv.egovernment.moa.spss.api.cmsverify.CMSContent; +import at.gv.egovernment.moa.spss.api.cmsverify.CMSDataObject; +import at.gv.egovernment.moa.spss.api.cmsverify.VerifyCMSSignatureRequest; +import at.gv.egovernment.moa.spss.api.cmsverify.VerifyCMSSignatureResponse; +import at.gv.egovernment.moa.spss.server.invoke.CMSSignatureVerificationInvoker; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +/** + * Created by Andreas Fitzek on 6/17/16. + */ +public class SimpleCAdESVerifier extends CAdESVerifier { + @Override + public boolean handles(ASiC asic) { + return super.handles(asic) && ASiCFormat.ASiCS.equals(asic.getFormat()); + } + + @Override + public void verify(ASiC asic, String trustProfileID, Date date, List response) throws MOAException { + ASiCEntry cadesSignature = asic.getSignaturesEntries().get(0); + + ASiCEntry dataEntry = asic.getDataEntries().get(0); + + List signedFiles = new ArrayList(); + signedFiles.add(dataEntry.getEntryName()); + + VerifyCMSSignatureResponse verifyResponse = + this.runCMSVerification(dataEntry.getContents(), cadesSignature.getContents(), trustProfileID, date); + + response.add(new ASiCVerificationResult(signedFiles, + verifyResponse)); + } + + +} diff --git a/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/verifier/SimpleXAdESVerifier.java b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/verifier/SimpleXAdESVerifier.java new file mode 100644 index 0000000..a71462c --- /dev/null +++ b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/verifier/SimpleXAdESVerifier.java @@ -0,0 +1,128 @@ +package at.gv.egiz.asic.impl.verifier; + +import at.gv.egiz.asic.ReferenceType; +import at.gv.egiz.asic.XAdESSignaturesType; +import at.gv.egiz.asic.api.ASiC; +import at.gv.egiz.asic.api.ASiCEntry; +import at.gv.egiz.asic.api.ASiCFormat; +import at.gv.egiz.asic.api.ASiCVerificationResult; +import at.gv.egovernment.moa.spss.MOAApplicationException; +import at.gv.egovernment.moa.spss.MOAException; +import at.gv.egovernment.moa.spss.MOARuntimeException; +import at.gv.egovernment.moa.spss.api.SPSSFactory; +import at.gv.egovernment.moa.spss.api.common.Content; +import at.gv.egovernment.moa.spss.api.common.XMLDataObjectAssociation; +import at.gv.egovernment.moa.spss.api.impl.SPSSFactoryImpl; +import at.gv.egovernment.moa.spss.api.xmlverify.SupplementProfile; +import at.gv.egovernment.moa.spss.api.xmlverify.VerifySignatureInfo; +import at.gv.egovernment.moa.spss.api.xmlverify.VerifySignatureLocation; +import at.gv.egovernment.moa.spss.api.xmlverify.VerifyXMLSignatureRequest; +import at.gv.egovernment.moa.spss.server.invoke.XMLSignatureVerificationInvoker; +import at.gv.egovernment.moaspss.util.URLEncoder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.xml.bind.JAXB; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.util.*; + +/** + * Created by Andreas Fitzek on 6/17/16. + */ +public class SimpleXAdESVerifier extends XAdESVerifier { + + private static final Logger logger = LoggerFactory.getLogger(SimpleXAdESVerifier.class); + + + @Override + public void verify(ASiC asic, String trustProfileID, Date date, List response) throws MOAException { + // XAdES + try { + ASiCEntry xadesSignature = asic.getSignaturesEntries().get(0); + + XAdESSignaturesType xAdESSignaturesType = null; + try { + xAdESSignaturesType = JAXB.unmarshal(xadesSignature.getContents(), XAdESSignaturesType.class); + } catch (Throwable ex) { + logger.warn("Failed to process xml signature: ex"); + throw new MOAApplicationException("asic.0003", null, ex); + } + + if (xAdESSignaturesType == null) { + throw new MOAApplicationException("asic.0003", null); + } + + int signatureSize = xAdESSignaturesType.getSignature().size(); + + try { + xadesSignature.getContents().reset(); + } catch (IOException e) { + throw new MOARuntimeException("asic.0003", null, e); + } + Map namespaces = new HashMap(); + + namespaces.put("asic", "http://uri.etsi.org/02918/v1.2.1#"); + namespaces.put("ds", "http://www.w3.org/2000/09/xmldsig#"); + + for (int i = 0; i < signatureSize; i++) { + + List signedFiles = new ArrayList(); + + Iterator it = xAdESSignaturesType.getSignature().get(i).getSignedInfo().getReference().iterator(); + while (it.hasNext()) { + ReferenceType refType = it.next(); + if (!refType.getURI().startsWith("#")) { + signedFiles.add(refType.getURI()); + } + } + + boolean addAll = signedFiles.isEmpty() && asic.getDataEntries().size() == 1; + + Iterator dataEntryIterator = asic.getDataEntries().iterator(); + + Content content = SPSSFactory.getInstance().createContent(xadesSignature.getContents(), null); + List supplementsList = new ArrayList(); + while (dataEntryIterator.hasNext()) { + ASiCEntry dataEntry = dataEntryIterator.next(); + String uriName = URLEncoder.encode(dataEntry.getEntryName(), "UTF-8") + .replaceAll("\\+", "%20") + .replaceAll("\\%21", "!") + .replaceAll("\\%27", "'") + //.replaceAll("\\%28", "(") + //.replaceAll("\\%29", ")") + .replaceAll("\\%7E", "~"); + + Content dataContent = SPSSFactory.getInstance().createContent(dataEntry.getContents(), uriName); + XMLDataObjectAssociation association = SPSSFactoryImpl.getInstance().createXMLDataObjectAssociation(null, dataContent); + SupplementProfile profile = SPSSFactoryImpl.getInstance().createSupplementProfile(association); + supplementsList.add(profile); + + if (addAll) { + signedFiles.add(dataEntry.getEntryName()); + } + } + String location = "(//ds:Signature)[" + (i + 1) + "]"; + + VerifySignatureLocation verifySignatureLocation = SPSSFactory.getInstance().createVerifySignatureLocation( + location, namespaces); + + VerifySignatureInfo verifySignatureInfo = SPSSFactory.getInstance().createVerifySignatureInfo(content, verifySignatureLocation); + + VerifyXMLSignatureRequest verifyXMLSignatureRequest = SPSSFactory.getInstance().createVerifyXMLSignatureRequest( + date, verifySignatureInfo, supplementsList, null, false, trustProfileID, true); + + response.add(new ASiCVerificationResult(signedFiles, + XMLSignatureVerificationInvoker.getInstance().verifyXMLSignature(verifyXMLSignatureRequest))); + } + } catch(UnsupportedEncodingException e) { + logger.error("UTF8 encoding not supported by system. MOA will not work on this system!", e); + throw new MOARuntimeException("asic.0003", null, e); + } + } + + @Override + public boolean handles(ASiC asic) { + return super.handles(asic) && ASiCFormat.ASiCS.equals(asic.getFormat()); + } +} \ No newline at end of file diff --git a/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/verifier/XAdESVerifier.java b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/verifier/XAdESVerifier.java new file mode 100644 index 0000000..904ad4e --- /dev/null +++ b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/impl/verifier/XAdESVerifier.java @@ -0,0 +1,54 @@ +package at.gv.egiz.asic.impl.verifier; + +import at.gv.egiz.asic.api.ASiC; +import at.gv.egiz.asic.api.ASiCEntry; +import at.gv.egiz.asic.api.ASiCVerificationResult; +import at.gv.egovernment.moa.spss.MOAException; +import at.gv.egovernment.moa.spss.api.SPSSFactory; +import at.gv.egovernment.moa.spss.api.cmsverify.CMSContent; +import at.gv.egovernment.moa.spss.api.cmsverify.CMSDataObject; +import at.gv.egovernment.moa.spss.api.cmsverify.VerifyCMSSignatureRequest; +import at.gv.egovernment.moa.spss.api.cmsverify.VerifyCMSSignatureResponse; +import at.gv.egovernment.moa.spss.api.common.Content; +import at.gv.egovernment.moa.spss.api.common.XMLDataObjectAssociation; +import at.gv.egovernment.moa.spss.api.impl.SPSSFactoryImpl; +import at.gv.egovernment.moa.spss.api.xmlverify.*; +import at.gv.egovernment.moa.spss.server.invoke.CMSSignatureVerificationInvoker; +import at.gv.egovernment.moa.spss.server.invoke.XMLSignatureVerificationInvoker; + +import java.io.InputStream; +import java.util.*; + +/** + * Created by Andreas Fitzek on 6/17/16. + */ +public abstract class XAdESVerifier extends BaseVerifier { + @Override + public boolean handles(ASiC asic) { + return asic.isXAdES(); + } + + protected VerifyXMLSignatureResponse runXMLVerification(InputStream signedData, InputStream xmlSignature, + String trustProfileID, Date date, List supplementsList, + String location, Map namespaces) throws MOAException { + + if(namespaces == null) { + namespaces = new HashMap(); + + namespaces.put("asic", "http://uri.etsi.org/02918/v1.2.1#"); + namespaces.put("ds", "http://www.w3.org/2000/09/xmldsig#"); + } + + Content content = SPSSFactory.getInstance().createContent(xmlSignature, null); + + VerifySignatureLocation verifySignatureLocation = SPSSFactory.getInstance().createVerifySignatureLocation( + location, namespaces); + + VerifySignatureInfo verifySignatureInfo = SPSSFactory.getInstance().createVerifySignatureInfo(content, verifySignatureLocation); + + VerifyXMLSignatureRequest verifyXMLSignatureRequest = SPSSFactory.getInstance().createVerifyXMLSignatureRequest( + date, verifySignatureInfo, supplementsList, null, false, trustProfileID, true); + + return XMLSignatureVerificationInvoker.getInstance().verifyXMLSignature(verifyXMLSignatureRequest); + } +} -- cgit v1.2.3