package at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.parser; import java.io.ByteArrayInputStream; import java.io.InputStream; import org.joda.time.DateTime; import org.joda.time.format.ISODateTimeFormat; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.lang.NonNull; import org.w3c.dom.Element; import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.api.data.IXMLSignatureVerificationResponse; import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.exceptions.MOASigServiceException; import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.exceptions.MOASigServiceParserException; import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.data.VerifyXMLSignatureResponse; import at.gv.egovernment.moaspss.util.Constants; import at.gv.egovernment.moaspss.util.DOMUtils; import at.gv.egovernment.moaspss.util.XPathUtils; import iaik.utils.Base64InputStream; import iaik.x509.X509Certificate; public class VerifyXMLSignatureResponseParser { private static final Logger log = LoggerFactory.getLogger(VerifyXMLSignatureResponseParser.class); // // XPath namespace prefix shortcuts // /** Xpath prefix for reaching MOA Namespaces */ private static final String MOA = Constants.MOA_PREFIX + ":"; /** Xpath prefix for reaching DSIG Namespaces */ private static final String DSIG = Constants.DSIG_PREFIX + ":"; /** Xpath expression to the root element */ private static final String ROOT = "/" + MOA + "VerifyXMLSignatureResponse/"; /** Xpath expression to the X509SubjectName element */ private static final String DSIG_SUBJECT_NAME_XPATH = ROOT + MOA + "SignerInfo/" + DSIG + "X509Data/" + DSIG + "X509SubjectName"; /** Xpath expression to the X509Certificate element */ private static final String DSIG_X509_CERTIFICATE_XPATH = ROOT + MOA + "SignerInfo/" + DSIG + "X509Data/" + DSIG + "X509Certificate"; /** Xpath expression to the PublicAuthority element */ private static final String PUBLIC_AUTHORITY_XPATH = ROOT + MOA + "SignerInfo/" + DSIG + "X509Data/" + MOA + "PublicAuthority"; /** Xpath expression to the PublicAuthorityCode element */ private static final String PUBLIC_AUTHORITY_CODE_XPATH = PUBLIC_AUTHORITY_XPATH + "/" + MOA + "Code"; /** Xpath expression to the QualifiedCertificate element */ private static final String QUALIFIED_CERTIFICATE_XPATH = ROOT + MOA + "SignerInfo/" + DSIG + "X509Data/" + MOA + "QualifiedCertificate"; /** Xpath expression to the SignatureCheckCode element */ private static final String SIGNATURE_CHECK_CODE_XPATH = ROOT + MOA + "SignatureCheck/" + MOA + "Code"; /** Xpath expression to the XMLDSIGManifestCheckCode element */ private static final String XMLDSIG_MANIFEST_CHECK_CODE_XPATH = ROOT + MOA + "XMLDSIGManifestCheck/" + MOA + "Code"; /** Xpath expression to the SignatureManifestCheckCode element */ private static final String SIGNATURE_MANIFEST_CHECK_CODE_XPATH = ROOT + MOA + "SignatureManifestCheck/" + MOA + "Code"; /** Xpath expression to the CertificateCheckCode element */ private static final String CERTIFICATE_CHECK_CODE_XPATH = ROOT + MOA + "CertificateCheck/" + MOA + "Code"; private static final String SIGNING_TIME_XPATH = ROOT + MOA + "SigningTime"; /** This is the root element of the XML-Document provided by the Security Layer Card*/ private Element verifyXMLSignatureResponse; /** * Constructor for VerifyXMLSignatureResponseParser. * A DOM-representation of the incoming String will be created * @param xmlResponse <InfoboxReadResponse> as String * @throws MOASigServiceParserException on any parsing error */ public VerifyXMLSignatureResponseParser(String xmlResponse) throws MOASigServiceParserException { try { final InputStream s = new ByteArrayInputStream(xmlResponse.getBytes("UTF-8")); verifyXMLSignatureResponse = DOMUtils.parseXmlValidating(s); } catch (final Throwable t) { log.warn("Can not parse MOA-Sig response." , t); throw new MOASigServiceParserException("service.moasig.02", new Object[] { t.toString() }, t); } } /** * Constructor for VerifyXMLSignatureResponseParser. * A DOM-representation of the incoming Inputstream will be created * @param xmlResponse <InfoboxReadResponse> as InputStream * @throws MOASigServiceParserException on any parsing error */ public VerifyXMLSignatureResponseParser(InputStream xmlResponse) throws MOASigServiceParserException { try { verifyXMLSignatureResponse = DOMUtils.parseXmlValidating(xmlResponse); } catch (final Throwable t) { log.warn("Can not parse MOA-Sig response." , t); throw new MOASigServiceParserException("service.moasig.02", new Object[] { t.toString() }, t); } } /** * Constructor for VerifyXMLSignatureResponseParser. * The incoming Element will be used for further operations * @param xmlResponse <InfoboxReadResponse> as Element */ public VerifyXMLSignatureResponseParser(Element xmlResponse) { verifyXMLSignatureResponse =xmlResponse; } /** * Parse MOA-Sig signatur-verification result into {@link IXMLSignatureVerificationResponse} * * @return {@link IXMLSignatureVerificationResponse} * @throws MOASigServiceException on any parsing error */ @NonNull public IXMLSignatureVerificationResponse parseData() throws MOASigServiceException { try { final VerifyXMLSignatureResponse respData = new VerifyXMLSignatureResponse(); respData.setXmlDsigSubjectName(XPathUtils.getElementValue(verifyXMLSignatureResponse,DSIG_SUBJECT_NAME_XPATH,"")); final Element e = (Element)XPathUtils.selectSingleNode(verifyXMLSignatureResponse,QUALIFIED_CERTIFICATE_XPATH); respData.setQualifiedCertificate(e!=null); final Base64InputStream in = new Base64InputStream(new ByteArrayInputStream(XPathUtils.getElementValue( verifyXMLSignatureResponse,DSIG_X509_CERTIFICATE_XPATH,"").getBytes("UTF-8")),true); respData.setX509CertificateEncoded(new X509Certificate(in).getEncoded()); final Element publicAuthority = (Element)XPathUtils.selectSingleNode(verifyXMLSignatureResponse,PUBLIC_AUTHORITY_XPATH); respData.setPublicAuthority(publicAuthority != null); respData.setPublicAuthorityCode(XPathUtils.getElementValue(verifyXMLSignatureResponse,PUBLIC_AUTHORITY_CODE_XPATH,"")); respData.setSignatureCheckCode(new Integer(XPathUtils.getElementValue(verifyXMLSignatureResponse,SIGNATURE_CHECK_CODE_XPATH,"")).intValue()); final String xmlDsigCheckCode = XPathUtils.getElementValue(verifyXMLSignatureResponse,XMLDSIG_MANIFEST_CHECK_CODE_XPATH,null); if (xmlDsigCheckCode!=null) { respData.setXmlDSIGManigest(true); respData.setXmlDSIGManifestCheckCode(new Integer(xmlDsigCheckCode).intValue()); } else { respData.setXmlDSIGManigest(false); } final String signatureManifestCheckCode = XPathUtils.getElementValue(verifyXMLSignatureResponse,SIGNATURE_MANIFEST_CHECK_CODE_XPATH,null); if (signatureManifestCheckCode != null) { respData.setSignatureManifestCheckCode(new Integer(signatureManifestCheckCode).intValue()); } respData.setCertificateCheckCode(new Integer(XPathUtils.getElementValue(verifyXMLSignatureResponse,CERTIFICATE_CHECK_CODE_XPATH,"")).intValue()); final String signingTimeElement = XPathUtils.getElementValue(verifyXMLSignatureResponse,SIGNING_TIME_XPATH,""); if (signingTimeElement != null && !signingTimeElement.isEmpty()) { final DateTime datetime = ISODateTimeFormat.dateOptionalTimeParser().parseDateTime(signingTimeElement); respData.setSigningDateTime(datetime.toDate()); } return respData; } catch (final Throwable t) { log.warn("Can not parse MOA-Sig response." , t); throw new MOASigServiceParserException("service.moasig.02", new Object[] { t.toString() }, t); } } }