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 --- .../src/main/java/at/gv/egiz/asic/api/ASiC.java | 13 ++ .../java/at/gv/egiz/asic/api/ASiCConstants.java | 9 + .../main/java/at/gv/egiz/asic/api/ASiCEntry.java | 38 +++++ .../main/java/at/gv/egiz/asic/api/ASiCFactory.java | 159 +++++++++++++++++- .../main/java/at/gv/egiz/asic/api/ASiCFormat.java | 9 + .../gv/egiz/asic/api/ASiCVerificationResult.java | 40 +++++ .../java/at/gv/egiz/asic/api/ASiCVerifier.java | 16 ++ .../at/gv/egiz/asic/exceptions/ASiCException.java | 7 + .../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 ++++++ .../xmlbind/VerifyASICSignatureRequestParser.java | 112 +++++++++++++ .../VerifyASICSignatureResponseBuilder.java | 177 ++++++++++++++++++++ .../at/gv/egiz/asic/xmlbind/VerifyASiCRequest.java | 46 ++++++ 45 files changed, 2285 insertions(+), 1 deletion(-) create mode 100644 moaSig/moa-asic/src/main/java/at/gv/egiz/asic/api/ASiC.java create mode 100644 moaSig/moa-asic/src/main/java/at/gv/egiz/asic/api/ASiCConstants.java create mode 100644 moaSig/moa-asic/src/main/java/at/gv/egiz/asic/api/ASiCEntry.java create mode 100644 moaSig/moa-asic/src/main/java/at/gv/egiz/asic/api/ASiCFormat.java create mode 100644 moaSig/moa-asic/src/main/java/at/gv/egiz/asic/api/ASiCVerificationResult.java create mode 100644 moaSig/moa-asic/src/main/java/at/gv/egiz/asic/api/ASiCVerifier.java create mode 100644 moaSig/moa-asic/src/main/java/at/gv/egiz/asic/exceptions/ASiCException.java 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 create mode 100644 moaSig/moa-asic/src/main/java/at/gv/egiz/asic/xmlbind/VerifyASICSignatureRequestParser.java create mode 100644 moaSig/moa-asic/src/main/java/at/gv/egiz/asic/xmlbind/VerifyASICSignatureResponseBuilder.java create mode 100644 moaSig/moa-asic/src/main/java/at/gv/egiz/asic/xmlbind/VerifyASiCRequest.java (limited to 'moaSig/moa-asic/src/main/java/at/gv') diff --git a/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/api/ASiC.java b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/api/ASiC.java new file mode 100644 index 0000000..e79d2ca --- /dev/null +++ b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/api/ASiC.java @@ -0,0 +1,13 @@ +package at.gv.egiz.asic.api; + +import java.util.List; + +public interface ASiC { + public ASiCFormat getFormat(); + public boolean isXAdES(); + public boolean isCAdES(); + + public List getSignaturesEntries(); + public List getDataEntries(); + public List getInformationEntries(); +} diff --git a/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/api/ASiCConstants.java b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/api/ASiCConstants.java new file mode 100644 index 0000000..02baf40 --- /dev/null +++ b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/api/ASiCConstants.java @@ -0,0 +1,9 @@ +package at.gv.egiz.asic.api; + +/** + * Created by afitzek on 6/15/16. + */ +public interface ASiCConstants { + public static final String FILE_MIME_TYPE = "mimetype"; + public static final String FILE_META_INF = "META-INF/"; +} diff --git a/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/api/ASiCEntry.java b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/api/ASiCEntry.java new file mode 100644 index 0000000..7c026cf --- /dev/null +++ b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/api/ASiCEntry.java @@ -0,0 +1,38 @@ +package at.gv.egiz.asic.api; + +import java.io.InputStream; + +/** + * Created by afitzek on 6/15/16. + */ +public class ASiCEntry { + + private String entryName; + private InputStream contents; + + public ASiCEntry() { + } + + public String getEntryName() { + return entryName; + } + + public void setEntryName(String entryName) { + this.entryName = entryName; + } + + public InputStream getContents() { + return contents; + } + + public void setContents(InputStream contents) { + this.contents = contents; + } + + @Override + public String toString() { + return "ASiCEntry{" + + "entryName='" + entryName + '\'' + + '}'; + } +} diff --git a/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/api/ASiCFactory.java b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/api/ASiCFactory.java index e9ad9dc..6b067f7 100644 --- a/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/api/ASiCFactory.java +++ b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/api/ASiCFactory.java @@ -1,7 +1,164 @@ package at.gv.egiz.asic.api; +import at.gv.egiz.asic.exceptions.ASiCException; +import at.gv.egiz.asic.impl.ASiCBaseFormatFactory; +import at.gv.egiz.asic.impl.ASiCExtendedFormatFactory; +import at.gv.egiz.asic.impl.ASiCSimpleFormatFactory; +import at.gv.egiz.asic.impl.ZipCommentReaderStream; +import at.gv.egovernment.moa.spss.MOAApplicationException; +import at.gv.egovernment.moa.spss.MOAException; +import org.apache.commons.io.IOUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + /** * Created by afitzek on 6/15/16. */ -public interface ASiCFactory { +public class ASiCFactory { + + private static final Logger logger = LoggerFactory.getLogger(ASiCFactory.class); + + private static final String MIMETYPE_FORMAT_E = "application/vnd.etsi.asic-e+zip"; + private static final String MIMETYPE_FORMAT_S = "application/vnd.etsi.asic-s+zip"; + + public static ASiC parseASiC(InputStream is, ASiCFormat format) throws MOAException { + + InputStream newInputStream = is; + + + // Try to determine the asic format! + if (!newInputStream.markSupported()) { + ByteArrayOutputStream asicContainer = new ByteArrayOutputStream(); + + try { + IOUtils.copy(newInputStream, asicContainer); + } catch (IOException e) { + throw new MOAApplicationException("asic.0003", null); + } + newInputStream = new ByteArrayInputStream(asicContainer.toByteArray()); + } + + String mimeTypeFile = null; + ZipCommentReaderStream commentReaderStream = new ZipCommentReaderStream(newInputStream); + byte[] buffer = new byte[8096]; + try { + while (commentReaderStream.read(buffer) >= 0) { + } + newInputStream.reset(); + } catch (IOException e) { + throw new MOAApplicationException("asic.0003", null); + } + + ZipInputStream zipInputStream = new ZipInputStream(newInputStream); + + try { + for (ZipEntry entry = zipInputStream.getNextEntry(); entry != null; entry = zipInputStream.getNextEntry()) { + String entryName = entry.getName(); + + if("mimetype".equalsIgnoreCase(entryName)) { + if(mimeTypeFile == null) { + mimeTypeFile = IOUtils.toString(zipInputStream, "UTF-8"); + } else { + logger.warn("multiple mimetype files found in archiv"); + } + } + } + newInputStream.reset(); + } catch (IOException e) { + throw new MOAApplicationException("asic.0007", null); + } + + String fileComment = commentReaderStream.getFileComment(); + ASiCFormat fileCommentFormat = null; + if (fileComment != null) { + logger.info("Found file comment in ASiC {}", fileComment); + if(fileComment.startsWith("mimetype=")) { + String fileCommentMimeType = fileComment.substring("mimetype=".length()); + if(fileCommentMimeType.startsWith(MIMETYPE_FORMAT_E)) { + fileCommentFormat = ASiCFormat.ASiCE; + } else if(fileCommentMimeType.startsWith(MIMETYPE_FORMAT_S)) { + fileCommentFormat = ASiCFormat.ASiCS; + } + } + } else { + logger.info("No file comment in ASiC"); + } + + + ASiCFormat mimeTypeFileFormat = null; + if (mimeTypeFile != null) { + logger.info("Found mimetype file in ASiC {}", mimeTypeFile); + if(MIMETYPE_FORMAT_E.equalsIgnoreCase(mimeTypeFile)) { + mimeTypeFileFormat = ASiCFormat.ASiCE; + } else if(MIMETYPE_FORMAT_S.equalsIgnoreCase(mimeTypeFile)) { + mimeTypeFileFormat = ASiCFormat.ASiCS; + } + } else { + logger.info("No mimetype file in ASiC"); + } + + if (format == null) { + if (fileCommentFormat != null && mimeTypeFileFormat != null) { + // both are set + if (fileCommentFormat == mimeTypeFileFormat) { + format = fileCommentFormat; + } else { + throw new MOAApplicationException("asic.0009", null); + } + } else if (fileCommentFormat != null) { + format = fileCommentFormat; + } else if (mimeTypeFileFormat != null) { + format = mimeTypeFileFormat; + } else { + throw new MOAApplicationException("asic.0008", null); + } + } else { + // format is provided, only check for missmatches + if (fileCommentFormat != null && fileCommentFormat != format) { + logger.warn("ASiC format missmatch file comment {} vs provided {}", fileCommentFormat, format); + throw new MOAApplicationException("asic.0009", null); + } + if (mimeTypeFileFormat != null && mimeTypeFileFormat != format) { + logger.warn("ASiC format missmatch mimetype file {} vs provided {}", mimeTypeFileFormat, format); + throw new MOAApplicationException("asic.0009", null); + } + + if (fileCommentFormat != null && mimeTypeFileFormat != null) { + // both are set + if (fileCommentFormat != mimeTypeFileFormat) { + logger.warn("ASiC format missmatch file comment {} vs mimetype file {}", fileCommentFormat, mimeTypeFileFormat); + throw new MOAApplicationException("asic.0009", null); + } + } + } + + ASiCBaseFormatFactory formatFactory = null; + + if (format == null) { + throw new MOAApplicationException("asic.0008", null); + } + + switch (format) { + case ASiCE: + formatFactory = new ASiCExtendedFormatFactory(); + break; + case ASiCS: + formatFactory = new ASiCSimpleFormatFactory(); + break; + } + + if (formatFactory == null) { + throw new MOAApplicationException("asic.0008", null); + } + + return formatFactory.createASiC(newInputStream); + } + } diff --git a/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/api/ASiCFormat.java b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/api/ASiCFormat.java new file mode 100644 index 0000000..8106944 --- /dev/null +++ b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/api/ASiCFormat.java @@ -0,0 +1,9 @@ +package at.gv.egiz.asic.api; + +/** + * Created by Andreas Fitzek on 6/15/16. + */ +public enum ASiCFormat { + ASiCS, + ASiCE +} diff --git a/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/api/ASiCVerificationResult.java b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/api/ASiCVerificationResult.java new file mode 100644 index 0000000..a350f18 --- /dev/null +++ b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/api/ASiCVerificationResult.java @@ -0,0 +1,40 @@ +package at.gv.egiz.asic.api; + +import at.gv.egovernment.moa.spss.api.cmsverify.VerifyCMSSignatureResponse; +import at.gv.egovernment.moa.spss.api.xmlverify.VerifyXMLSignatureResponse; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by Andreas Fitzek on 6/16/16. + */ +public class ASiCVerificationResult { + + private List signedFiles = new ArrayList(); + + private VerifyCMSSignatureResponse cmsResult = null; + private VerifyXMLSignatureResponse xmlResult = null; + + public ASiCVerificationResult(List references, VerifyCMSSignatureResponse cmsResult) { + this.signedFiles = references; + this.cmsResult = cmsResult; + } + + public ASiCVerificationResult(List references, VerifyXMLSignatureResponse xmlResult) { + this.signedFiles = references; + this.xmlResult = xmlResult; + } + + public List getSignedFiles() { + return signedFiles; + } + + public VerifyXMLSignatureResponse getXmlResult() { + return xmlResult; + } + + public VerifyCMSSignatureResponse getCmsResult() { + return cmsResult; + } +} diff --git a/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/api/ASiCVerifier.java b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/api/ASiCVerifier.java new file mode 100644 index 0000000..77bc61d --- /dev/null +++ b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/api/ASiCVerifier.java @@ -0,0 +1,16 @@ +package at.gv.egiz.asic.api; + +import at.gv.egovernment.moa.spss.MOAException; +import at.gv.egovernment.moa.spss.api.cmsverify.VerifyCMSSignatureResponse; + +import java.util.Date; +import java.util.List; + +/** + * Created by Andreas Fitzek on 6/15/16. + */ +public interface ASiCVerifier { + + public List verify(ASiC asic, String trustProfileID, Date date) throws MOAException; + +} diff --git a/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/exceptions/ASiCException.java b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/exceptions/ASiCException.java new file mode 100644 index 0000000..f29199a --- /dev/null +++ b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/exceptions/ASiCException.java @@ -0,0 +1,7 @@ +package at.gv.egiz.asic.exceptions; + +/** + * Created by afitzek on 6/15/16. + */ +public class ASiCException { +} 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); + } +} diff --git a/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/xmlbind/VerifyASICSignatureRequestParser.java b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/xmlbind/VerifyASICSignatureRequestParser.java new file mode 100644 index 0000000..c06e30e --- /dev/null +++ b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/xmlbind/VerifyASICSignatureRequestParser.java @@ -0,0 +1,112 @@ +/* + * Copyright 2003 Federal Chancellery Austria + * MOA-SPSS has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, 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.asic.xmlbind; + +import at.gv.egiz.asic.api.ASiCFormat; +import at.gv.egovernment.moa.spss.MOAApplicationException; +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.common.MetaInfo; +import at.gv.egovernment.moa.spss.api.xmlbind.RequestParserUtils; +import at.gv.egovernment.moaspss.util.*; +import org.w3c.dom.Element; + +import java.io.InputStream; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.StringTokenizer; + +/** + * A parser to parse VerifyCMSSignatureRequest DOM trees into + * VerifyCMSSignatureRequest API objects. + * + * @author Patrick Peck + * @version $Id$ + */ +public class VerifyASICSignatureRequestParser { + + // + // XPath expressions for selecting parts of the DOM message + // + private static final String MOA = Constants.MOA_PREFIX + ":"; + private static final String DATE_TIME_XPATH = MOA + "DateTime"; + private static final String EXTENDED_VALIDATION_XPATH = MOA + "ExtendedValidation"; + private static final String ASIC_SIGNATURE_XPATH = MOA + "ASICSignature"; + private static final String ASIC_EXTENSION_XPATH = MOA + "ASICExtension"; + private static final String TRUST_PROFILE_ID_XPATH = MOA + "TrustProfileID"; + + + /** The SPSSFactory for creating new API objects. */ + private SPSSFactory factory = SPSSFactory.getInstance(); + + /** + * Parse a VerifyCMSSignatureRequest DOM element, as defined + * by the MOA schema. + * + * @param requestElem The VerifyCMSSignatureRequest to parse. The + * request must have been successfully parsed against the schema for this + * method to succeed. + * @return A VerifyCMSSignatureRequest API objects containing + * the data from the DOM element. + * @throws MOAApplicationException An error occurred parsing the request. + */ + public VerifyASiCRequest parseASIC(Element requestElem) + throws MOAApplicationException { + Date dateTime = + RequestParserUtils.parseDateTime(requestElem, DATE_TIME_XPATH); + + boolean extendedValidation = + RequestParserUtils.parseExtendedValidation(requestElem, EXTENDED_VALIDATION_XPATH, false); + + String asicSignatureStr = + XPathUtils.getElementValue(requestElem, ASIC_SIGNATURE_XPATH, ""); + + String asicExtensionStr = + XPathUtils.getElementValue(requestElem, ASIC_EXTENSION_XPATH, ""); + + String trustProfileID = + XPathUtils.getElementValue(requestElem, TRUST_PROFILE_ID_XPATH, null); + //Logger.info("CMSSignature: " + cmsSignatureStr); + InputStream asicSignature = + Base64Utils.decodeToStream(asicSignatureStr, true); + + ASiCFormat format = null; + + if("asics".equalsIgnoreCase(asicExtensionStr) || "scs".equalsIgnoreCase(asicExtensionStr) + || "application/vnd.etsi.asic-s+zip".equalsIgnoreCase(asicExtensionStr)) { + format = ASiCFormat.ASiCS; + } else if("asice".equalsIgnoreCase(asicExtensionStr) || "sce".equalsIgnoreCase(asicExtensionStr) + || "application/vnd.etsi.asic-e+zip".equalsIgnoreCase(asicExtensionStr)) { + format = ASiCFormat.ASiCE; + } + + return new VerifyASiCRequest(format, dateTime, asicSignature, trustProfileID, extendedValidation); + } + +} diff --git a/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/xmlbind/VerifyASICSignatureResponseBuilder.java b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/xmlbind/VerifyASICSignatureResponseBuilder.java new file mode 100644 index 0000000..781a081 --- /dev/null +++ b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/xmlbind/VerifyASICSignatureResponseBuilder.java @@ -0,0 +1,177 @@ +/* + * Copyright 2003 Federal Chancellery Austria + * MOA-SPSS has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, 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.asic.xmlbind; + +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.cmsverify.VerifyCMSSignatureResponse; +import at.gv.egovernment.moa.spss.api.cmsverify.VerifyCMSSignatureResponseElement; +import at.gv.egovernment.moa.spss.api.common.CheckResult; +import at.gv.egovernment.moa.spss.api.common.SignerInfo; +import at.gv.egovernment.moa.spss.api.xmlbind.ResponseBuilderUtils; +import at.gv.egovernment.moa.spss.api.xmlbind.VerifyXMLSignatureResponseBuilder; +import at.gv.egovernment.moa.spss.api.xmlverify.AdESFormResults; +import at.gv.egovernment.moa.spss.api.xmlbind.VerifyCMSSignatureResponseBuilder; +import at.gv.egovernment.moaspss.util.Constants; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import java.util.Iterator; +import java.util.List; + +/** + * Convert a VerifyCMSSignatureResponse API object into its + * XML representation, according to the MOA XML schema. + * + * @author Patrick Peck + * @version $Id$ + */ +public class VerifyASICSignatureResponseBuilder { + /** The XML document containing the response element. */ + private Document responseDoc; + /** The response VerifyCMSSignatureResponse DOM element. */ + private Element responseElem; + + /** + * Create a new VerifyCMSSignatureResponseBuilder: + * + * @throws MOASystemException An error occurred setting up the resulting + * XML document. + */ + public VerifyASICSignatureResponseBuilder() throws MOASystemException { + responseDoc = + ResponseBuilderUtils.createResponse("VerifyASICSignatureResponse"); + responseElem = responseDoc.getDocumentElement(); + } + + /** + * Build a document containing a VerifyCMSSignatureResponse + * DOM element being the XML representation of the given + * VerifyCMSSignatureResponse API object. + * + * @param response The VerifyCMSSignatureResponse to convert + * to XML. + * @return A document containing the VerifyCMSSignatureResponse + * DOM element. + * @throws MOAApplicationException An error occurred building the response. + */ + public Document build(List results) + throws MOAException { + + Iterator iter = results.iterator(); + + while(iter.hasNext()) { + ASiCVerificationResult aSiCVerificationResult = iter.next(); + addASiCResultElement(aSiCVerificationResult); + } + + return responseDoc; + } + + private void addASiCResultElement(ASiCVerificationResult aSiCVerificationResult) + throws MOAException { + Element asiCSignatureResultElem = responseDoc.createElementNS(Constants.MOA_NS_URI, "ASiCSignatureResult"); + + Iterator signedFiles = aSiCVerificationResult.getSignedFiles().iterator(); + while (signedFiles.hasNext()) { + String signedFile = signedFiles.next(); + Element signedFilesElem = responseDoc.createElementNS(Constants.MOA_NS_URI, "signedFiles"); + signedFilesElem.setTextContent(signedFile); + asiCSignatureResultElem.appendChild(signedFilesElem); + } + + if(aSiCVerificationResult.getXmlResult() != null) { + VerifyXMLSignatureResponseBuilder verifyXMLSignatureResponseBuilder = new VerifyXMLSignatureResponseBuilder(this.responseDoc, "XMLSignatureResult"); + asiCSignatureResultElem.appendChild(verifyXMLSignatureResponseBuilder.buildElement(aSiCVerificationResult.getXmlResult())); + } else if(aSiCVerificationResult.getCmsResult() != null) { + VerifyCMSSignatureResponseBuilder verifyCMSSignatureResponseBuilder = new VerifyCMSSignatureResponseBuilder(this.responseDoc, "CMSSignatureResult"); + asiCSignatureResultElem.appendChild(verifyCMSSignatureResponseBuilder.buildElement(aSiCVerificationResult.getCmsResult())); + } + + responseElem.appendChild(asiCSignatureResultElem); + } + + /** + * Add an element to the response. + * + * @param responseElement The element to add to the response. + * @throws MOAApplicationException An error occurred adding the element. + */ + private void addResponseElement(VerifyCMSSignatureResponseElement responseElement) + throws MOAApplicationException { + + SignerInfo signerInfo = responseElement.getSignerInfo(); + CheckResult signatureCheck = responseElement.getSignatureCheck(); + CheckResult certCheck = responseElement.getCertificateCheck(); + + ResponseBuilderUtils.addSignerInfo( + responseDoc, + responseElem, + signerInfo.getSignerCertificate(), + signerInfo.isQualifiedCertificate(), + signerInfo.getQCSource(), + signerInfo.isPublicAuthority(), + signerInfo.getPublicAuhtorityID(), + signerInfo.isSSCD(), + signerInfo.getSSCDSource(), + signerInfo.getIssuerCountryCode()); + + ResponseBuilderUtils.addCodeInfoElement( + responseDoc, + responseElem, + "SignatureCheck", + signatureCheck.getCode(), + signatureCheck.getInfo()); + + ResponseBuilderUtils.addCodeInfoElement( + responseDoc, + responseElem, + "CertificateCheck", + certCheck.getCode(), + certCheck.getInfo()); + + + if (responseElement.getAdESFormResults() != null) { + + Iterator formIterator = responseElement.getAdESFormResults().iterator(); + + while (formIterator.hasNext()) { + AdESFormResults adESFormResult = (AdESFormResults) formIterator.next(); + // add the CertificateCheck + ResponseBuilderUtils.addFormCheckElement(responseDoc, responseElem, "FormCheckResult", + adESFormResult.getCode().intValue(), adESFormResult.getName()); + + } + } + + if(responseElement.getExtendedCertificateCheck() != null) { + ResponseBuilderUtils.addExtendendResult(responseDoc, responseElem, responseElement.getExtendedCertificateCheck()); + } + + } + +} diff --git a/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/xmlbind/VerifyASiCRequest.java b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/xmlbind/VerifyASiCRequest.java new file mode 100644 index 0000000..37584a6 --- /dev/null +++ b/moaSig/moa-asic/src/main/java/at/gv/egiz/asic/xmlbind/VerifyASiCRequest.java @@ -0,0 +1,46 @@ +package at.gv.egiz.asic.xmlbind; + +import at.gv.egiz.asic.api.ASiCFormat; + +import java.io.InputStream; +import java.util.Date; + +/** + * Created by Andreas Fitzek on 6/16/16. + */ +public class VerifyASiCRequest { + private Date date; + private InputStream asicInput; + private String trustProfile; + private ASiCFormat format; + private boolean extendedValidation; + + + public VerifyASiCRequest(ASiCFormat format, Date date, InputStream asicInput, String trustProfile, boolean extendedValidation) { + this.format = format; + this.date = date; + this.asicInput = asicInput; + this.trustProfile = trustProfile; + this.extendedValidation = extendedValidation; + } + + public Date getDate() { + return date; + } + + public InputStream getAsicInput() { + return asicInput; + } + + public String getTrustProfile() { + return trustProfile; + } + + public ASiCFormat getFormat() { + return format; + } + + public boolean isExtendedValidation() { + return extendedValidation; + } +} -- cgit v1.2.3