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);
}
}
}