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.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.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(); //TODO: maybe add additional XAdES version } else if ("http://uri.etsi.org/02918/v1.1.1#".equals(rootElement.getNamespaceURI()) && "XAdESSignatures".equals(rootElement.getLocalName())) { logger.warn("ASiC v1.1.1 is not supported any more. MOA-SP only supports v1.2.1 (http://uri.etsi.org/02918/v1.2.1#)"); //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#"); if (xmlSignatures == null || xmlSignatures.size() == 0) { logger.info("ASiC container does not include a signature or signature format is not supported"); throw new MOAApplicationException("asic.0016", null); } 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()); } }