diff options
| author | Thomas Lenz <thomas.lenz@egiz.gv.at> | 2018-05-30 06:29:29 +0200 | 
|---|---|---|
| committer | Thomas Lenz <thomas.lenz@egiz.gv.at> | 2018-05-30 06:29:29 +0200 | 
| commit | 52ad604e54cb91073503d708cd0c50ff0121174a (patch) | |
| tree | 3aaaebf8460d79fc99bca243827e4e0987ec4379 /id/server/modules/moa-id-module-sl20_authentication/src | |
| parent | dc2fb6695f44e3e01088e8a986ae1ac98b1743b1 (diff) | |
| download | moa-id-spss-52ad604e54cb91073503d708cd0c50ff0121174a.tar.gz moa-id-spss-52ad604e54cb91073503d708cd0c50ff0121174a.tar.bz2 moa-id-spss-52ad604e54cb91073503d708cd0c50ff0121174a.zip | |
add additional validation to SL20 module
Diffstat (limited to 'id/server/modules/moa-id-module-sl20_authentication/src')
3 files changed, 193 insertions, 11 deletions
| diff --git a/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/sl20/JsonSecurityUtils.java b/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/sl20/JsonSecurityUtils.java index e0965c712..d00ef8a04 100644 --- a/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/sl20/JsonSecurityUtils.java +++ b/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/sl20/JsonSecurityUtils.java @@ -5,6 +5,9 @@ import java.security.KeyStore;  import java.security.PrivateKey;  import java.security.cert.Certificate;  import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Enumeration;  import java.util.List;  import javax.annotation.PostConstruct; @@ -14,6 +17,8 @@ import org.jose4j.jwa.AlgorithmConstraints.ConstraintType;  import org.jose4j.jwe.JsonWebEncryption;  import org.jose4j.jws.AlgorithmIdentifiers;  import org.jose4j.jws.JsonWebSignature; +import org.jose4j.jwx.JsonWebStructure; +import org.jose4j.keys.resolvers.X509VerificationKeyResolver;  import org.jose4j.lang.JoseException;  import org.springframework.beans.factory.annotation.Autowired;  import org.springframework.stereotype.Service; @@ -33,6 +38,7 @@ import at.gv.egovernment.moa.id.commons.utils.X509Utils;  import at.gv.egovernment.moa.logging.Logger;  import at.gv.egovernment.moa.util.FileUtils;  import at.gv.egovernment.moa.util.KeyStoreUtils; +import at.gv.egovernment.moa.util.MiscUtil;  @Service  public class JsonSecurityUtils implements IJOSETools{ @@ -44,6 +50,8 @@ public class JsonSecurityUtils implements IJOSETools{  	private Key encPrivKey = null;  	private X509Certificate[] encCertChain = null; +	private List<X509Certificate> trustedCerts = new ArrayList<X509Certificate>(); +	  	@PostConstruct  	protected void initalize() {  		Logger.info("Initialize SL2.0 authentication security constrains ... "); @@ -83,6 +91,21 @@ public class JsonSecurityUtils implements IJOSETools{  			} +			//load trusted certificates +			Enumeration<String> aliases = keyStore.aliases(); +			while(aliases.hasMoreElements()) { +				String el = aliases.nextElement(); +				Logger.trace("Process TrustStoreEntry: " + el); +				if (keyStore.isCertificateEntry(el)) { +					Certificate cert = keyStore.getCertificate(el);  +					if (cert != null && cert instanceof X509Certificate) +						trustedCerts.add((X509Certificate) cert); +					else +						Logger.info("Can not process entry: " + el + ". Reason: " + cert.toString()); +					 +				} +			} +			  			//some short validation  			if (signPrivKey == null || !(signPrivKey instanceof PrivateKey)) {  				Logger.info("Can NOT open privateKey for SL2.0 signing. KeyStore=" + getKeyStoreFilePath()); @@ -144,18 +167,42 @@ public class JsonSecurityUtils implements IJOSETools{  					SL20Constants.SL20_ALGORITHM_WHITELIST_SIGNING.toArray(new String[SL20Constants.SL20_ALGORITHM_WHITELIST_SIGNING.size()])));  			//load signinc certs +			Key selectedKey = null;  			List<X509Certificate> x5cCerts = jws.getCertificateChainHeaderValue(); -			List<X509Certificate> sortedX5cCerts  = null; -			if (x5cCerts == null || x5cCerts.size() < 1) { -				Logger.info("Signed SL2.0 response contains NO signature certificate"); -				throw new SLCommandoParserException("Signed SL2.0 response contains NO signature certificate"); +			String x5t256 = jws.getX509CertSha256ThumbprintHeaderValue(); +			if (x5cCerts != null) { +				Logger.debug("Found x509 certificate in JOSE header ... "); +				Logger.trace("Sorting received X509 certificates ... "); +				List<X509Certificate> sortedX5cCerts  = X509Utils.sortCertificates(x5cCerts); +				 +				if (trustedCerts.contains(sortedX5cCerts.get(0))) { +					selectedKey = sortedX5cCerts.get(0).getPublicKey(); +					 +				} else { +					Logger.info("Can NOT find JOSE certificate in truststore."); +					Logger.debug("JOSE certificate: " + sortedX5cCerts.get(0).toString()); +					 +				} -			}  -			Logger.trace("Sorting received X509 certificates ... "); -			sortedX5cCerts = X509Utils.sortCertificates(x5cCerts); -							 +			} else if (MiscUtil.isNotEmpty(x5t256)) { +				Logger.debug("Found x5t256 fingerprint in JOSE header .... "); +				X509VerificationKeyResolver x509VerificationKeyResolver = new X509VerificationKeyResolver(trustedCerts); +				selectedKey = x509VerificationKeyResolver.resolveKey(jws, Collections.<JsonWebStructure>emptyList()); +				 +			} else { +				Logger.info("Signed SL2.0 response contains NO signature certificate or NO certificate fingerprint"); +				throw new SLCommandoParserException("Signed SL2.0 response contains NO signature certificate or NO certificate fingerprint"); +				 +			} +					 +			if (selectedKey == null) { +				Logger.info("Can NOT select verification key for JWS. Signature verification FAILED."); +				throw new SLCommandoParserException("Can NOT select verification key for JWS. Signature verification FAILED"); +				 +			} +			  			//set verification key -			jws.setKey(sortedX5cCerts.get(0).getPublicKey()); +			jws.setKey(selectedKey);  			//validate signature  			boolean valid = jws.verifySignature(); @@ -169,7 +216,7 @@ public class JsonSecurityUtils implements IJOSETools{  			//load payLoad  			JsonElement sl20Req = new JsonParser().parse(jws.getPayload()); -			return new VerificationResult(sl20Req.getAsJsonObject(), sortedX5cCerts, valid) ; +			return new VerificationResult(sl20Req.getAsJsonObject(), null, valid) ;  		} catch (JoseException e) {  			Logger.warn("SL2.0 commando signature validation FAILED", e); diff --git a/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/sl20/verifier/QualifiedeIDVerifier.java b/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/sl20/verifier/QualifiedeIDVerifier.java new file mode 100644 index 000000000..7d03a43ac --- /dev/null +++ b/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/sl20/verifier/QualifiedeIDVerifier.java @@ -0,0 +1,132 @@ +package at.gv.egovernment.moa.id.auth.modules.sl20_auth.sl20.verifier; + +import java.io.IOException; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.List; + +import javax.xml.bind.DatatypeConverter; +import javax.xml.transform.TransformerException; + +import org.jaxen.SimpleNamespaceContext; +import org.w3c.dom.Element; + +import at.gv.egovernment.moa.id.auth.builder.SignatureVerificationUtils; +import at.gv.egovernment.moa.id.auth.data.CreateXMLSignatureResponse; +import at.gv.egovernment.moa.id.auth.exception.BuildException; +import at.gv.egovernment.moa.id.auth.exception.ParseException; +import at.gv.egovernment.moa.id.auth.exception.ServiceException; +import at.gv.egovernment.moa.id.auth.exception.ValidateException; +import at.gv.egovernment.moa.id.auth.invoke.SignatureVerificationInvoker; +import at.gv.egovernment.moa.id.auth.parser.VerifyXMLSignatureResponseParser; +import at.gv.egovernment.moa.id.auth.validator.IdentityLinkValidator; +import at.gv.egovernment.moa.id.auth.validator.VerifyXMLSignatureRequestBuilder; +import at.gv.egovernment.moa.id.auth.validator.VerifyXMLSignatureResponseValidator; +import at.gv.egovernment.moa.id.commons.api.AuthConfiguration; +import at.gv.egovernment.moa.id.commons.api.IOAAuthParameters; +import at.gv.egovernment.moa.id.commons.api.data.IIdentityLink; +import at.gv.egovernment.moa.id.commons.api.data.IVerifiyXMLSignatureResponse; +import at.gv.egovernment.moa.id.commons.api.exceptions.ConfigurationException; +import at.gv.egovernment.moa.id.commons.api.exceptions.MOAIDException; +import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.spss.api.impl.VerifyXMLSignatureRequestImpl; +import at.gv.egovernment.moa.util.Constants; +import at.gv.egovernment.moa.util.DOMUtils; +import at.gv.egovernment.moa.util.XPathUtils; + + +public class QualifiedeIDVerifier { + +	 /** Xpath expression to the dsig:Signature element */ +	  private static final String SIGNATURE_XPATH = Constants.DSIG_PREFIX + ":Signature"; +	   +	  private static final String XADES_1_1_1_SIGNINGTIME_PATH = "//" + Constants.XADES_1_1_1_NS_PREFIX + ":SigningTime"; +	  private static final String XADES_1_3_2_SIGNINGTIME_PATH = "//" + Constants.XADES_1_3_2_NS_PREFIX + ":SigningTime"; +	   +	   +	  private static final long MAX_DIFFERENCE_IN_MILLISECONDS = 600000; // 10min +	   + +	  private static SimpleNamespaceContext NS_CONTEXT; +	  static { +	    NS_CONTEXT = new SimpleNamespaceContext(); +	    NS_CONTEXT.addNamespace(Constants.XADES_1_1_1_NS_PREFIX, Constants.XADES_1_1_1_NS_URI); +	    NS_CONTEXT.addNamespace(Constants.XADES_1_2_2_NS_PREFIX, Constants.XADES_1_2_2_NS_URI); +	    NS_CONTEXT.addNamespace(Constants.XADES_1_3_2_NS_PREFIX, Constants.XADES_1_3_2_NS_URI); +	    NS_CONTEXT.addNamespace(Constants.XADES_1_4_1_NS_PREFIX, Constants.XADES_1_4_1_NS_URI); +	  } +	 +	public static boolean verifyIdentityLink(IIdentityLink idl, IOAAuthParameters oaParam, AuthConfiguration authConfig) throws MOAIDException {		 +		// validates the identity link +		IdentityLinkValidator.getInstance().validate(idl); +		 +		// builds a <VerifyXMLSignatureRequest> for a call of MOA-SP +		Element domVerifyXMLSignatureRequest = new VerifyXMLSignatureRequestBuilder() +				.build(idl, authConfig.getMoaSpIdentityLinkTrustProfileID(oaParam.isUseIDLTestTrustStore())); + +		// invokes the call +		Element domVerifyXMLSignatureResponse = SignatureVerificationInvoker.getInstance() +				.verifyXMLSignature(domVerifyXMLSignatureRequest); +		 +		// parses the <VerifyXMLSignatureResponse> +		IVerifiyXMLSignatureResponse verifyXMLSignatureResponse = new VerifyXMLSignatureResponseParser(domVerifyXMLSignatureResponse).parseData(); +				 +		// validates the <VerifyXMLSignatureResponse> +		VerifyXMLSignatureResponseValidator.getInstance().validate( +			verifyXMLSignatureResponse, +			authConfig.getIdentityLinkX509SubjectNames(), +			VerifyXMLSignatureResponseValidator.CHECK_IDENTITY_LINK, +			oaParam); + +		 +		return false; +		 +	} +	 +	public static IVerifiyXMLSignatureResponse verifyAuthBlock(byte[] authblock, IOAAuthParameters oaParam, AuthConfiguration authConfig) throws MOAIDException { +		String trustProfileId = authConfig.getMoaSpAuthBlockTrustProfileID(oaParam.isUseAuthBlockTestTestStore()); +		List<String> verifyTransformsInfoProfileID = null; +		 +		SignatureVerificationUtils sigVerify = new SignatureVerificationUtils(); +		IVerifiyXMLSignatureResponse sigVerifyResult = sigVerify.verify(authblock, trustProfileId , verifyTransformsInfoProfileID); +						 +		// validates the <VerifyXMLSignatureResponse> +		VerifyXMLSignatureResponseValidator.getInstance().validate(sigVerifyResult, +					null, VerifyXMLSignatureResponseValidator.CHECK_AUTH_BLOCK, oaParam); + +		return sigVerifyResult; +				 +	} +	 +	public static boolean checkIDLAgainstAuthblock(IVerifiyXMLSignatureResponse sigVerifyResult, IIdentityLink idl, byte[] authBlock) throws ValidateException { +		 +		try {         +			// compares the public keys from the identityLink with the AuthBlock +			VerifyXMLSignatureResponseValidator.getInstance().validateCertificate(sigVerifyResult, idl); + +			 +			// Compare AuthBlock Data with information stored in session, especially +			// date and time +			validateSigningDateTime(sigVerifyResult); +			 +		} catch ( ValidateException e) { +			Logger.error("Signature verification error. ", e); +			throw e;  +			 +		} +		 +		 +		return false; +		 +	} +	 +	private static boolean validateSigningDateTime( IVerifiyXMLSignatureResponse sigVerifyResult) throws ValidateException { +		Date signingDate = sigVerifyResult.getSigningDateTime(); +		 +		 +			   +		return false; +	  } +	 +} diff --git a/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/tasks/ReceiveQualeIDTask.java b/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/tasks/ReceiveQualeIDTask.java index 698546a4f..90e19326e 100644 --- a/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/tasks/ReceiveQualeIDTask.java +++ b/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/tasks/ReceiveQualeIDTask.java @@ -37,6 +37,7 @@ import at.gv.egovernment.moa.id.auth.modules.sl20_auth.sl20.SL20JSONBuilderUtils  import at.gv.egovernment.moa.id.auth.modules.sl20_auth.sl20.SL20JSONExtractorUtils;  import at.gv.egovernment.moa.id.auth.parser.IdentityLinkAssertionParser;  import at.gv.egovernment.moa.id.commons.MOAIDAuthConstants; +import at.gv.egovernment.moa.id.commons.api.data.IIdentityLink;  import at.gv.egovernment.moa.id.commons.api.exceptions.MOAIDException;  import at.gv.egovernment.moa.id.process.api.ExecutionContext;  import at.gv.egovernment.moa.id.protocols.AbstractAuthProtocolModulController; @@ -128,11 +129,13 @@ public class ReceiveQualeIDTask extends AbstractAuthServletTask {  				//TODO: validate results +				IIdentityLink idl = new IdentityLinkAssertionParser(new ByteArrayInputStream(Base64Utils.decode(idlB64, false))).parseIdentityLink(); +				  				//add into session  				defaultTaskInitialization(request, executionContext); -				moasession.setIdentityLink(new IdentityLinkAssertionParser(new ByteArrayInputStream(Base64Utils.decode(idlB64, false))).parseIdentityLink()); +				moasession.setIdentityLink(idl);  				moasession.setBkuURL(ccsURL);  				//TODO: from AuthBlock  				moasession.setIssueInstant(DateTimeUtils.buildDateTimeUTC(Calendar.getInstance())); | 
