summaryrefslogtreecommitdiff
path: root/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/SignatureVerificationService.java
diff options
context:
space:
mode:
Diffstat (limited to 'eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/SignatureVerificationService.java')
-rw-r--r--eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/SignatureVerificationService.java348
1 files changed, 348 insertions, 0 deletions
diff --git a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/SignatureVerificationService.java b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/SignatureVerificationService.java
new file mode 100644
index 00000000..b2ea5cb7
--- /dev/null
+++ b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/SignatureVerificationService.java
@@ -0,0 +1,348 @@
+package at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl;
+
+import java.io.ByteArrayInputStream;
+import java.security.Provider;
+import java.security.Security;
+import java.security.cert.CertificateEncodingException;
+import java.util.List;
+
+import javax.annotation.PostConstruct;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.lang.Nullable;
+import org.springframework.stereotype.Service;
+import org.springframework.util.Base64Utils;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.api.ISignatureVerificationService;
+import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.api.data.ICMSSignatureVerificationResponse;
+import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.api.data.IXMLSignatureVerificationResponse;
+import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.exceptions.MOASigServiceBuilderException;
+import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.exceptions.MOASigServiceConfigurationException;
+import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.exceptions.MOASigServiceException;
+import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.parser.VerifyXMLSignatureResponseParser;
+import at.gv.egovernment.moa.spss.MOAException;
+import at.gv.egovernment.moa.spss.api.Configurator;
+import at.gv.egovernment.moa.spss.api.cmsverify.VerifyCMSSignatureRequest;
+import at.gv.egovernment.moa.spss.api.cmsverify.VerifyCMSSignatureResponse;
+import at.gv.egovernment.moa.spss.api.cmsverify.VerifyCMSSignatureResponseElement;
+import at.gv.egovernment.moa.spss.api.impl.VerifyCMSSignatureRequestImpl;
+import at.gv.egovernment.moa.spss.api.xmlbind.VerifyXMLSignatureRequestParser;
+import at.gv.egovernment.moa.spss.api.xmlbind.VerifyXMLSignatureResponseBuilder;
+import at.gv.egovernment.moa.spss.api.xmlverify.VerifyXMLSignatureRequest;
+import at.gv.egovernment.moa.spss.api.xmlverify.VerifyXMLSignatureResponse;
+import at.gv.egovernment.moaspss.logging.LoggingContext;
+import at.gv.egovernment.moaspss.logging.LoggingContextManager;
+import at.gv.egovernment.moaspss.util.Constants;
+import iaik.asn1.structures.AlgorithmID;
+import iaik.security.ec.provider.ECCelerate;
+import iaik.security.provider.IAIK;
+
+
+/**
+ * @author tlenz
+ *
+ */
+@Service
+public class SignatureVerificationService implements ISignatureVerificationService {
+ private static final Logger log = LoggerFactory.getLogger(SignatureVerificationService.class);
+
+ private static final String XMLNS_NS_URI = Constants.XMLNS_NS_URI;
+ private static final String MOA_NS_URI = Constants.MOA_NS_URI;
+ private static final String DSIG = Constants.DSIG_PREFIX + ":";
+
+ private at.gv.egovernment.moa.spss.api.SignatureVerificationService svs;
+
+ @PostConstruct
+ private void initialize() throws MOASigServiceConfigurationException {
+ log.info("Initializing MOA-Sig signature-verification service ... ");
+
+ log.info("Loading Java security providers.");
+ IAIK.addAsProvider();
+ ECCelerate.addAsProvider();
+
+ try {
+ LoggingContextManager.getInstance().setLoggingContext(
+ new LoggingContext("startup"));
+ log.debug("MOA-Sig library initialization process ... ");
+ Configurator.getInstance().init();
+ log.info("MOA-Sig library initialization complete ");
+
+ } catch (final MOAException e) {
+ log.error("MOA-SP initialization FAILED!", e.getWrapped());
+ throw new MOASigServiceConfigurationException("service.moasig.04", new Object[] { e
+ .toString() }, e);
+ }
+
+ Security.insertProviderAt(IAIK.getInstance(), 0);
+
+ final ECCelerate eccProvider = ECCelerate.getInstance();
+ if (Security.getProvider(eccProvider.getName()) != null)
+ Security.removeProvider(eccProvider.getName());
+ Security.addProvider(new ECCelerate());
+
+ fixJava8_141ProblemWithSSLAlgorithms();
+
+ if (log.isDebugEnabled()) {
+ log.debug("Loaded Security Provider:");
+ final Provider[] providerList = Security.getProviders();
+ for (int i=0; i<providerList.length; i++)
+ log.debug(i + ": " + providerList[i].getName() + " Version " + providerList[i].getVersion());
+
+ }
+
+ log.debug("Instanzing SignatureVerificationService implementation ... ");
+ svs = at.gv.egovernment.moa.spss.api.SignatureVerificationService.getInstance();
+
+ log.info("MOA-Sig signature-verification service initialized");
+ }
+
+
+
+ /* (non-Javadoc)
+ * @see at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.ISignatureVerificationService#verifyCMSSignature(byte[], java.lang.String)
+ */
+ @Override
+ @Nullable
+ public ICMSSignatureVerificationResponse verifyCMSSignature(byte[] signature, String trustProfileID) throws MOASigServiceException {
+ try {
+ final VerifyCMSSignatureRequest cmsSigVerifyReq = buildVerfifyCMSRequest(signature, trustProfileID, false, false);
+ final VerifyCMSSignatureResponse cmsSigVerifyResp = svs.verifyCMSSignature(cmsSigVerifyReq );
+ return parseCMSVerificationResult(cmsSigVerifyResp);
+
+ } catch (final MOAException e) {
+ log.warn("CMS signature verification has an error.", e);
+ throw new MOASigServiceException("service.03", new Object[] { e.toString()}, e);
+
+ } catch (final CertificateEncodingException e) {
+ log.warn("Can NOT serialize X509 certificate from CMS/CAdES signature-verification response", e);
+ throw new MOASigServiceException("service.03", new Object[] { e.toString()}, e);
+
+ }
+
+ }
+
+ private ICMSSignatureVerificationResponse parseCMSVerificationResult(VerifyCMSSignatureResponse cmsSigVerifyResp) throws CertificateEncodingException {
+
+ if (cmsSigVerifyResp.getResponseElements() == null ||
+ cmsSigVerifyResp.getResponseElements().isEmpty()) {
+ log.info("No CMS signature FOUND. ");
+ return null;
+
+ }
+
+ if (cmsSigVerifyResp.getResponseElements().size() > 1)
+ log.warn("CMS or CAdES signature contains more than one technical signatures. Only validate the first signature");
+
+ final VerifyCMSSignatureResponseElement firstSig = (VerifyCMSSignatureResponseElement) cmsSigVerifyResp.getResponseElements().get(0);
+
+ final at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.data.VerifyCMSSignatureResponse result =
+ new at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.data.VerifyCMSSignatureResponse();
+
+ //parse results into response container
+ result.setSignatureCheckCode(firstSig.getSignatureCheck().getCode());
+ result.setCertificateCheckCode(firstSig.getCertificateCheck().getCode());
+
+ if (firstSig.getSignerInfo() != null) {
+ result.setSigningDateTime(firstSig.getSignerInfo().getSigningTime());
+ result.setX509CertificateEncoded(firstSig.getSignerInfo().getSignerCertificate().getEncoded());
+ result.setQualifiedCertificate(firstSig.getSignerInfo().isQualifiedCertificate());
+
+ result.setPublicAuthority(firstSig.getSignerInfo().isPublicAuthority());
+ result.setPublicAuthorityCode(firstSig.getSignerInfo().getPublicAuhtorityID());
+
+ } else
+ log.info("CMS or CAdES verification result contains no SignerInfo");
+
+ return result;
+ }
+
+
+
+ /* (non-Javadoc)
+ * @see at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.ISignatureVerificationService#verifyXMLSignature(byte[], java.lang.String)
+ */
+ @Override
+ public IXMLSignatureVerificationResponse verifyXMLSignature(byte[] signature, String trustProfileID) throws MOASigServiceException {
+ return verifyXMLSignature(signature, trustProfileID, null);
+
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.ISignatureVerificationService#verifyXMLSignature(byte[], java.lang.String, java.util.List)
+ */
+ @Override
+ public IXMLSignatureVerificationResponse verifyXMLSignature(byte[] signature, String trustProfileID, List<String> verifyTransformsInfoProfileID) throws MOASigServiceException {
+ try {
+ //build signature-verification request
+ final Element domVerifyXMLSignatureRequest = buildVerifyXMLRequest(signature, trustProfileID, verifyTransformsInfoProfileID);
+
+ //send signature-verification to MOA-Sig
+ final VerifyXMLSignatureRequest vsrequest = new VerifyXMLSignatureRequestParser().parse(domVerifyXMLSignatureRequest);
+ final VerifyXMLSignatureResponse vsresponse = svs.verifyXMLSignature(vsrequest);
+ final Document result = new VerifyXMLSignatureResponseBuilder(true).build(vsresponse);
+
+ // parses the <IXMLSignatureVerificationResponse>
+ final IXMLSignatureVerificationResponse verifyXMLSignatureResponse = new VerifyXMLSignatureResponseParser(result.getDocumentElement()).parseData();
+
+ return verifyXMLSignatureResponse;
+
+ } catch (final MOASigServiceException e) {
+ throw e;
+
+ } catch (final MOAException e) {
+ log.warn("MOA-Sig signature-verification has an internal error."
+ + " MsgCode: " + e.getMessageId()
+ + " Msg: " + e.getMessage(),
+ e);
+ throw new MOASigServiceException("service.moasig.03", new Object[]{e.getMessage()}, e);
+
+ }
+ }
+
+ /**
+ * Build a VerifyCMS-Siganture request for MOA-Sig.
+ * <br><br>
+ * This builder only generates verification-request for enveloped CMS or CAdES signatures
+ * <br>
+ * This
+ *
+ * @param signature CMS or CAdES signature
+ * @param trustProfileID trustProfileID MOA-Sig Trust-Profile
+ * @param isPdfSignature Make CAdES signature as part of an PAdES document
+ * @param performExtendedValidation To extended validation. See MOA-Sig documentation for detailed information
+ * @return
+ */
+ private VerifyCMSSignatureRequest buildVerfifyCMSRequest(byte[] signature, String trustProfileID,
+ boolean isPdfSignature, boolean performExtendedValidation) {
+ final VerifyCMSSignatureRequestImpl verifyCMSSignatureRequest = new VerifyCMSSignatureRequestImpl();
+ verifyCMSSignatureRequest.setDateTime(null);
+ verifyCMSSignatureRequest.setCMSSignature(new ByteArrayInputStream(signature));
+ verifyCMSSignatureRequest.setDataObject(null);
+ verifyCMSSignatureRequest.setTrustProfileId(trustProfileID);
+ verifyCMSSignatureRequest.setSignatories(VerifyCMSSignatureRequest.ALL_SIGNATORIES);
+ verifyCMSSignatureRequest.setPDF(isPdfSignature);
+ verifyCMSSignatureRequest.setExtended(performExtendedValidation);
+ return verifyCMSSignatureRequest;
+
+ }
+
+ /**
+ * Build a VerifyXML-Signature request for MOA-Sig
+ *
+ * @param signature Serialized XML signature
+ * @param trustProfileID MOA-Sig Trust-Profile
+ * @param verifyTransformsInfoProfileID {@link List} of Transformation-Profiles used for validation
+ * @return
+ * @throws MOASigServiceBuilderException
+ */
+ private Element buildVerifyXMLRequest(byte[] signature, String trustProfileID, List<String> verifyTransformsInfoProfileID) throws MOASigServiceBuilderException {
+ try {
+ //build empty document
+ final Document requestDoc_ = getNewDocumentBuilder();
+ final Element requestElem_ = requestDoc_.createElementNS(MOA_NS_URI, "VerifyXMLSignatureRequest");
+ requestElem_.setAttributeNS(XMLNS_NS_URI, "xmlns", MOA_NS_URI);
+ requestElem_.setAttributeNS(XMLNS_NS_URI, "xmlns:" + Constants.DSIG_PREFIX, Constants.DSIG_NS_URI);
+ requestDoc_.appendChild(requestElem_);
+
+
+ // build the request
+ final Element verifiySignatureInfoElem = requestDoc_.createElementNS(MOA_NS_URI, "VerifySignatureInfo");
+ requestElem_.appendChild(verifiySignatureInfoElem);
+ final Element verifySignatureEnvironmentElem = requestDoc_.createElementNS(MOA_NS_URI, "VerifySignatureEnvironment");
+ verifiySignatureInfoElem.appendChild(verifySignatureEnvironmentElem);
+ final Element base64ContentElem = requestDoc_.createElementNS(MOA_NS_URI, "Base64Content");
+ verifySignatureEnvironmentElem.appendChild(base64ContentElem);
+
+ // insert the base64 encoded signature
+ String base64EncodedAssertion = Base64Utils.encodeToString(signature);
+ //replace all '\r' characters by no char.
+ final StringBuffer replaced = new StringBuffer();
+ for (int i = 0; i < base64EncodedAssertion.length(); i ++) {
+ final char c = base64EncodedAssertion.charAt(i);
+ if (c != '\r') {
+ replaced.append(c);
+ }
+ }
+ base64EncodedAssertion = replaced.toString();
+ final Node base64Content = requestDoc_.createTextNode(base64EncodedAssertion);
+ base64ContentElem.appendChild(base64Content);
+
+ // specify the signature location
+ final Element verifySignatureLocationElem = requestDoc_.createElementNS(MOA_NS_URI, "VerifySignatureLocation");
+ verifiySignatureInfoElem.appendChild(verifySignatureLocationElem);
+ final Node signatureLocation = requestDoc_.createTextNode(DSIG + "Signature");
+ verifySignatureLocationElem.appendChild(signatureLocation);
+
+ // signature manifest params
+ final Element signatureManifestCheckParamsElem = requestDoc_.createElementNS(MOA_NS_URI, "SignatureManifestCheckParams");
+ requestElem_.appendChild(signatureManifestCheckParamsElem);
+ signatureManifestCheckParamsElem.setAttribute("ReturnReferenceInputData", "false");
+
+ //verify transformations
+ if (verifyTransformsInfoProfileID != null && !verifyTransformsInfoProfileID.isEmpty()) {
+ final Element referenceInfoElem = requestDoc_.createElementNS(MOA_NS_URI, "ReferenceInfo");
+ signatureManifestCheckParamsElem.appendChild(referenceInfoElem);
+ for (final String element : verifyTransformsInfoProfileID) {
+ final Element verifyTransformsInfoProfileIDElem = requestDoc_.createElementNS(MOA_NS_URI, "VerifyTransformsInfoProfileID");
+ referenceInfoElem.appendChild(verifyTransformsInfoProfileIDElem);
+ verifyTransformsInfoProfileIDElem.appendChild(requestDoc_.createTextNode(element));
+
+ }
+ }
+
+ //hashinput data
+ final Element returnHashInputDataElem = requestDoc_.createElementNS(MOA_NS_URI, "ReturnHashInputData");
+ requestElem_.appendChild(returnHashInputDataElem);
+
+ //add trustProfileID
+ final Element trustProfileIDElem = requestDoc_.createElementNS(MOA_NS_URI, "TrustProfileID");
+ trustProfileIDElem.appendChild(requestDoc_.createTextNode(trustProfileID));
+ requestElem_.appendChild(trustProfileIDElem);
+
+ return requestElem_;
+
+ } catch (final Throwable t) {
+ log.warn("Can NOT build VerifyXML-Signature request for MOA-Sig", t);
+ throw new MOASigServiceBuilderException("service.moasig.03", new Object[] { t.getMessage() }, t);
+
+ }
+
+ }
+
+ /**
+ * Get a new {@link Document} from {@link DocumentBuilder} in synchronized form, because
+ * {@link DocumentBuilderFactory} and {@link DocumentBuilder} are not thread-safe.
+ *
+ * @return {@link Document}
+ * @throws ParserConfigurationException
+ */
+ private synchronized Document getNewDocumentBuilder() throws ParserConfigurationException {
+ final DocumentBuilder docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+ return docBuilder.newDocument();
+
+ }
+
+ private static void fixJava8_141ProblemWithSSLAlgorithms() {
+ log.info("Change AlgorithmIDs to fix problems with Java8 >= 141 ...");
+ //new AlgorithmID("1.2.840.113549.1.1.4", "md5WithRSAEncryption", new String[] { "MD5withRSA", "MD5/RSA", }, null, true);
+ new AlgorithmID("1.2.840.113549.1.1.5", "sha1WithRSAEncryption",
+ new String[] { "SHA1withRSA" , "SHA1/RSA", "SHA-1/RSA", "SHA/RSA", }, null, true);
+ new AlgorithmID("1.2.840.113549.1.1.14", "sha224WithRSAEncryption",
+ new String[] { "SHA224withRSA", "SHA224/RSA", "SHA-224/RSA", }, null, true);
+ new AlgorithmID("1.2.840.113549.1.1.11", "sha256WithRSAEncryption",
+ new String[] { "SHA256withRSA", "SHA256/RSA", "SHA-256/RSA", }, null, true);
+ new AlgorithmID("1.2.840.113549.1.1.12", "sha384WithRSAEncryption",
+ new String[] { "SHA384withRSA", "SHA384/RSA", "SHA-384/RSA", }, null, true);
+ new AlgorithmID("1.2.840.113549.1.1.13", "sha512WithRSAEncryption",
+ new String[] { "SHA512withRSA", "SHA512/RSA", "SHA-512/RSA" }, null, true);
+
+ log.info("Change AlgorithmIDs finished");
+ }
+}