package at.gv.egiz.asic.impl.verifier; 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; import javax.xml.bind.JAXB; import org.apache.commons.codec.binary.Hex; import org.slf4j.Logger; import org.slf4j.LoggerFactory; 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.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; /** * 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 { final Iterator informationsIterator = asic.getInformationEntries().iterator(); while (informationsIterator.hasNext()) { final ASiCEntry informationEntry = informationsIterator.next(); if (informationEntry.getEntryName().startsWith("META-INF/") && informationEntry.getEntryName() .endsWith(".xml") && informationEntry.getEntryName().contains("ASiCManifest")) { // Got ASiC Manifest final ASiCManifestType asiCManifestType = JAXB.unmarshal(informationEntry.getContents(), ASiCManifestType.class); final String signatureName = asiCManifestType.getSigReference().getURI(); ASiCEntry cadesSignature = null; // find referenced signature final Iterator cadesSignatureIterator = asic.getSignaturesEntries().iterator(); while (cadesSignatureIterator.hasNext()) { final 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; final List signedFiles = new ArrayList<>(); final Iterator dataObjectReferenceTypeIterator = asiCManifestType .getDataObjectReference().iterator(); while (dataObjectReferenceTypeIterator.hasNext()) { final DataObjectReferenceType dataObjectReferenceType = dataObjectReferenceTypeIterator.next(); final String mdURI = dataObjectReferenceType.getDigestMethod().getAlgorithm(); final String uri = dataObjectReferenceType.getURI(); signedFiles.add(new AsicSignedFilesContainer(uri, mdURI)); final Iterator dataEntryIterator = asic.getDataEntries().iterator(); while (dataEntryIterator.hasNext()) { final ASiCEntry dataEntry = dataEntryIterator.next(); if (uri.equalsIgnoreCase(dataEntry.getEntryName())) { final MessageDigest md = this.getMessageDigestFromURI(mdURI); if (md == null) { throw new MOAApplicationException("asic.0005", new Object[] { mdURI }); } final DigestInputStream dis = new DigestInputStream(dataEntry.getContents(), md); final 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(); final MessageDigest md = this.getMessageDigestFromURI("SHA-256"); final DigestInputStream dis = new DigestInputStream(informationEntry.getContents(), md); final VerifyCMSSignatureResponse verifyResponse = this.runCMSVerification(dis, cadesSignature.getContents(), trustProfileID, date); dis.close(); final 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()); final List responseElements = new ArrayList(); final SignerInfo signerInfo; // add SignerInfo element final Iterator responseElementIterator = verifyResponse.getResponseElements().iterator(); while (responseElementIterator.hasNext()) { final VerifyCMSSignatureResponseElement orig = (VerifyCMSSignatureResponseElement) responseElementIterator.next(); CheckResult signatureCheck; final CheckResult certificateCheck; // add SignatureCheck element signatureCheck = SPSSFactory.getInstance().createCheckResult(1, null); // build the response element final VerifyCMSSignatureResponseElement responseElement = SPSSFactory.getInstance().createVerifyCMSSignatureResponseElement( orig.getSignerInfo(), signatureCheck, orig.getCertificateCheck(), orig.getAdESFormResults(), orig.getExtendedCertificateCheck(), orig.getSignatureAlgorithm(), null, null); responseElements.add(responseElement); } final VerifyCMSSignatureResponse verifyCMSSignatureResponse = SPSSFactory.getInstance() .createVerifyCMSSignatureResponse(responseElements); response.add(new ASiCVerificationResult(signedFiles, verifyCMSSignatureResponse)); continue; } else { response.add(new ASiCVerificationResult(signedFiles, verifyResponse)); } } } } catch (final IOException ex) { throw new MOASystemException("asic.0003", null, ex); } } }