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(final 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(final 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(final 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(Integer.parseInt(
XPathUtils.getElementValue(verifyXmlSignatureResponse, SIGNATURE_CHECK_CODE_XPATH, "")));
final String xmlDsigCheckCode = XPathUtils.getElementValue(verifyXmlSignatureResponse,
XMLDSIG_MANIFEST_CHECK_CODE_XPATH, null);
if (xmlDsigCheckCode != null) {
respData.setXmlDsigManigest(true);
respData.setXmlDsigManifestCheckCode(Integer.parseInt(xmlDsigCheckCode));
} else {
respData.setXmlDsigManigest(false);
}
final String signatureManifestCheckCode = XPathUtils
.getElementValue(verifyXmlSignatureResponse, SIGNATURE_MANIFEST_CHECK_CODE_XPATH, null);
if (signatureManifestCheckCode != null) {
respData.setSignatureManifestCheckCode(Integer.parseInt(signatureManifestCheckCode));
}
respData.setCertificateCheckCode(Integer.parseInt(
XPathUtils.getElementValue(verifyXmlSignatureResponse, CERTIFICATE_CHECK_CODE_XPATH, "")));
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);
}
}
}