package at.gv.egiz.moazs.backend; import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.api.ISignatureVerificationService; 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.moazs.MoaZSException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.function.Consumer; import static at.gv.egiz.moazs.MoaZSException.moaZSException; import static java.lang.String.format; public class SignatureVerifier implements Consumer { private static final Logger log = LoggerFactory.getLogger(SignatureVerifier.class); private static final int OK_CODE = 0; private static final String MOASPSS_FAILED_ERROR_MSG = "MOA SPSS could not find the signature. "; private static final String SIGNATURE_CODE_ERROR_MSG = "Signature is not valid: Check code was %d. "; private static final String CERT_CODE_ERROR_MSG = "Certificate chain is not valid: Check code was %d. "; private static final String MANIFEST_CODE_ERROR_MSG = "Signature Manifest is not valid: Check code was %d. "; private static final String XMLMANIFEST_CODE_ERROR_MSG = "XmlDSIGManifest is not valid: Check code was %d. "; //TODO: Dont make this multiline! private static final String XML_SIGNATURE_RESPONSE_TEMPLATE = " XmlDsigSubjectName: %s\n" + " SignatureManifestCheckCode: %s\n" + " XmlDSIGManifestCheckCode: %s\n" + " CertificateCheckCode: %s\n" + " SignatureCheckCode: %s\n" + " SigningDateTime: %s\n" + " isXmlDSIGManigest: %s\n" + " isPublicAuthority: %s\n" + " isQualifiedCertificate: %s\n" + " getPublicAuthorityCode: %s\n"; private static final String MOASIG_SERVICE_ERROR_MSG = "MOA SPSS could not accept the XML signature. "; private final ISignatureVerificationService service; private final String trustProfile; private final boolean isManifestCheckActive; public SignatureVerifier(ISignatureVerificationService service, String trustProfile, boolean isManifestCheckActive) { this.service = service; this.trustProfile = trustProfile; this.isManifestCheckActive = isManifestCheckActive; } /** * Verifies the signature of a signed XML document. Throws a at.gv.egiz.moazs.MoaZSException exception * if the validation fails. * @param signedXMLdocument * @throws at.gv.egiz.moazs.MoaZSException */ @Override public void accept(byte[] signedXMLdocument) { try { var response = service.verifyXMLSignature(signedXMLdocument, trustProfile); debug(response); if (response == null) { throw moaZSException(MOASPSS_FAILED_ERROR_MSG); } var builder = new StringBuilder(); if (response.getSignatureCheckCode() != OK_CODE) { builder.append(format(SIGNATURE_CODE_ERROR_MSG, response.getSignatureCheckCode())); } if (response.getCertificateCheckCode() != OK_CODE) { builder.append(format(CERT_CODE_ERROR_MSG, response.getCertificateCheckCode())); } if (response.getSignatureManifestCheckCode() != OK_CODE) { var signatureManifestErrorMsg = format(MANIFEST_CODE_ERROR_MSG, response.getSignatureManifestCheckCode()); if (isManifestCheckActive) { builder.append(signatureManifestErrorMsg); } else { log.warn(signatureManifestErrorMsg); } } if (response.isXmlDSIGManigest() && response.getXmlDSIGManifestCheckCode() != OK_CODE) { var xmlDSIGManifestErrorMsg = format(XMLMANIFEST_CODE_ERROR_MSG, response.getXmlDSIGManifestCheckCode()); if (isManifestCheckActive) { builder.append(xmlDSIGManifestErrorMsg); } else { log.warn(xmlDSIGManifestErrorMsg); } } var msg = builder.toString(); if(!msg.isEmpty()) { throw moaZSException(msg); } } catch (MOASigServiceException e) { throw moaZSException(MOASIG_SERVICE_ERROR_MSG, e); } } public static void debug(IXMLSignatureVerificationResponse response) { if (log.isDebugEnabled()) { var builder = new StringBuilder("Response: \n"); if (response == null) { builder.append("null"); } else { var objects = new Object[]{response.getXmlDsigSubjectName(), response.getSignatureManifestCheckCode(), response.getXmlDSIGManifestCheckCode(), response.getCertificateCheckCode(), response.getSignatureCheckCode(), response.getSigningDateTime(), response.isXmlDSIGManigest(), response.isPublicAuthority(), response.isQualifiedCertificate(), response.getPublicAuthorityCode()}; builder.append(String.format(XML_SIGNATURE_RESPONSE_TEMPLATE, objects)); } log.debug(builder.toString()); } } }