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.egiz.asic.impl.AsicSignedFilesContainer; 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(new AsicSignedFilesContainer(uri, mdURI)); 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.debug("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(), orig.getSignatureAlgorithm()); 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); } } }