diff options
2 files changed, 136 insertions, 71 deletions
| diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/IJOSETools.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/IJOSETools.java index 35e6de4f..b124ada7 100644 --- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/IJOSETools.java +++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/IJOSETools.java @@ -1,6 +1,15 @@  package at.gv.egiz.eaaf.modules.auth.sl20.utils; +import java.io.IOException; +import java.security.KeyStore; +import java.security.KeyStoreException;  import java.security.cert.X509Certificate; +import java.util.List; + +import javax.annotation.Nonnull; + +import org.jose4j.jwa.AlgorithmConstraints; +import org.jose4j.lang.JoseException;  import com.fasterxml.jackson.databind.JsonNode; @@ -20,14 +29,44 @@ public interface IJOSETools {  	public String createSignature(String payLoad) throws SLCommandoBuildException;  	/** -	 * Validates a JWS signature +	 * Validates a signed SL2.0 message  	 *   	 * @param serializedContent  	 * @return  	 * @throws SLCommandoParserException  	 * @throws SL20Exception   	 */ -	public VerificationResult validateSignature(String serializedContent) throws SL20Exception; +	@Nonnull +	public VerificationResult validateSignature(@Nonnull String serializedContent) throws SL20Exception; +	 +	/** +	 * Validate a JWS signature  +	 *  +	 * @param serializedContent JWS in serialized form +	 * @param trustedCerts trusted X509 certificates +	 * @param constraints signature verification constraints +	 * @return Signature-verification result +	 * @throws JoseException +	 * @throws IOException +	 */ +	@Nonnull +	public VerificationResult validateSignature(@Nonnull String serializedContent, @Nonnull List<X509Certificate> trustedCerts, +			@Nonnull AlgorithmConstraints constraints) throws JoseException, IOException; +	 +	/** +	 * Validate a JWS signature  +	 *  +	 * @param serializedContent JWS in serialized form +	 * @param trustStore with trusted X509 certificates +	 * @param algconstraints signature verification constraints +	 * @return Signature-verification result +	 * @throws JoseException +	 * @throws IOException +	 * @throws KeyStoreException  +	 */ +	@Nonnull +	public VerificationResult validateSignature(@Nonnull String serializedContent, @Nonnull KeyStore trustStore, +			@Nonnull AlgorithmConstraints algconstraints) throws JoseException, IOException, KeyStoreException;  	/**  	 * Get the encryption certificate for SL2.0 End-to-End encryption @@ -44,5 +83,5 @@ public interface IJOSETools {  	 * @throws SL20Exception   	 */  	public JsonNode decryptPayload(String compactSerialization) throws SL20Exception; -	  +  } diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JsonSecurityUtils.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JsonSecurityUtils.java index 33873f43..c07c6081 100644 --- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JsonSecurityUtils.java +++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JsonSecurityUtils.java @@ -4,6 +4,7 @@ import java.io.IOException;  import java.net.MalformedURLException;  import java.security.Key;  import java.security.KeyStore; +import java.security.KeyStoreException;  import java.security.PrivateKey;  import java.security.cert.Certificate;  import java.security.cert.CertificateEncodingException; @@ -13,6 +14,7 @@ import java.util.Collections;  import java.util.Enumeration;  import java.util.List; +import javax.annotation.Nonnull;  import javax.annotation.PostConstruct;  import org.apache.commons.lang3.StringUtils; @@ -28,6 +30,7 @@ import org.jose4j.lang.JoseException;  import org.slf4j.Logger;  import org.slf4j.LoggerFactory;  import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.lang.NonNull;  import org.springframework.stereotype.Service;  import org.springframework.util.Base64Utils; @@ -57,7 +60,7 @@ public class JsonSecurityUtils implements IJOSETools{  	private Key encPrivKey = null;  	private X509Certificate[] encCertChain = null; -	private final List<X509Certificate> trustedCerts = new ArrayList<X509Certificate>(); +	private List<X509Certificate> trustedCerts = new ArrayList<X509Certificate>();  	private static JsonMapper mapper = new JsonMapper(); @@ -100,22 +103,10 @@ public class JsonSecurityUtils implements IJOSETools{  					log.warn("No encryption key for SL2.0 found. End-to-End encryption is not used. Reason: " + e.getMessage(), e);  				} -				 +  				//load trusted certificates -				final Enumeration<String> aliases = keyStore.aliases(); -				while(aliases.hasMoreElements()) { -					final String el = aliases.nextElement(); -					log.trace("Process TrustStoreEntry: " + el); -					if (keyStore.isCertificateEntry(el)) { -						final Certificate cert = keyStore.getCertificate(el);  -						if (cert != null && cert instanceof X509Certificate) -							trustedCerts.add((X509Certificate) cert); -						else -							log.info("Can not process entry: " + el + ". Reason: " + cert.toString()); -						 -					} -				} -	 +				trustedCerts = readCertsFromKeyStore(keyStore); +				  				//some short validation  				if (signPrivKey == null || !(signPrivKey instanceof PrivateKey)) {  					log.info("Can NOT open privateKey for SL2.0 signing. KeyStore=" + getKeyStoreFilePath()); @@ -141,7 +132,6 @@ public class JsonSecurityUtils implements IJOSETools{  	} -	  	@Override  	public String createSignature(String payLoad) throws SLCommandoBuildException {  		try { @@ -172,75 +162,90 @@ public class JsonSecurityUtils implements IJOSETools{  	}  	@Override -	public VerificationResult validateSignature(String serializedContent) throws SL20Exception { -		try { -			final JsonWebSignature jws = new JsonWebSignature(); -			//set payload -			jws.setCompactSerialization(serializedContent); -				 -			//set security constrains -			jws.setAlgorithmConstraints(new AlgorithmConstraints(ConstraintType.WHITELIST,    -					SL20Constants.SL20_ALGORITHM_WHITELIST_SIGNING.toArray(new String[SL20Constants.SL20_ALGORITHM_WHITELIST_SIGNING.size()]))); +	public VerificationResult validateSignature(String serializedContent, KeyStore trustStore, +			AlgorithmConstraints algconstraints) throws JoseException, IOException, KeyStoreException { +		final List<X509Certificate> trustedCertificates = readCertsFromKeyStore(trustStore); +		return validateSignature(serializedContent, trustedCertificates , algconstraints); +		 +	} +	 +	@Override +	@NonNull +	public VerificationResult validateSignature(@Nonnull String serializedContent, @Nonnull List<X509Certificate> trustedCerts, @Nonnull AlgorithmConstraints constraints) throws JoseException, IOException { +		final JsonWebSignature jws = new JsonWebSignature(); +		//set payload +		jws.setCompactSerialization(serializedContent); -			//load signinc certs -			Key selectedKey = null; -			final List<X509Certificate> x5cCerts = jws.getCertificateChainHeaderValue(); -			final String x5t256 = jws.getX509CertSha256ThumbprintHeaderValue(); -			if (x5cCerts != null) { -				log.debug("Found x509 certificate in JOSE header ... "); +		//set security constrains +		jws.setAlgorithmConstraints(constraints); +		 +		//load signinc certs +		Key selectedKey = null; +		final List<X509Certificate> x5cCerts = jws.getCertificateChainHeaderValue(); +		final String x5t256 = jws.getX509CertSha256ThumbprintHeaderValue(); +		if (x5cCerts != null) { +			log.debug("Found x509 certificate in JOSE header ... ");  			log.trace("Sorting received X509 certificates ... "); -				final List<X509Certificate> sortedX5cCerts  = X509Utils.sortCertificates(x5cCerts); -							 -				if (trustedCerts.contains(sortedX5cCerts.get(0))) { -					selectedKey = sortedX5cCerts.get(0).getPublicKey(); +			final List<X509Certificate> sortedX5cCerts  = X509Utils.sortCertificates(x5cCerts); +						 +			if (trustedCerts.contains(sortedX5cCerts.get(0))) { +				selectedKey = sortedX5cCerts.get(0).getPublicKey(); +				 +			} else { +				log.info("Can NOT find JOSE certificate in truststore."); +				try { +					log.debug("Cert: " + Base64Utils.encodeToString(sortedX5cCerts.get(0).getEncoded())); -				} else { -					log.info("Can NOT find JOSE certificate in truststore."); -					log.debug("JOSE certificate: " + sortedX5cCerts.get(0).toString()); -					try { -						log.debug("Cert: " + Base64Utils.encodeToString(sortedX5cCerts.get(0).getEncoded())); -					} catch (final CertificateEncodingException e) { -						e.printStackTrace(); -					} +				} catch (final CertificateEncodingException e) { +					e.printStackTrace();  				} -			} else if (StringUtils.isNotEmpty(x5t256)) { -				log.debug("Found x5t256 fingerprint in JOSE header .... "); -				final X509VerificationKeyResolver x509VerificationKeyResolver = new X509VerificationKeyResolver(trustedCerts); -				selectedKey = x509VerificationKeyResolver.resolveKey(jws, Collections.<JsonWebStructure>emptyList()); +			} +			 +		} else if (StringUtils.isNotEmpty(x5t256)) { +			log.debug("Found x5t256 fingerprint in JOSE header .... "); +			final X509VerificationKeyResolver x509VerificationKeyResolver = new X509VerificationKeyResolver(trustedCerts); +			selectedKey = x509VerificationKeyResolver.resolveKey(jws, Collections.<JsonWebStructure>emptyList()); +			 +		} else { +			throw new JoseException("JWS contains NO signature certificate or NO certificate fingerprint"); +			 +		} -			} else { -				log.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) { +			throw new JoseException("Can NOT select verification key for JWS. Signature verification FAILED"); +			 +		} -			} -					 -			if (selectedKey == null) { -				log.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(selectedKey); -			} +		//load payLoad		 +		return new VerificationResult(mapper.getMapper().readTree(jws.getPayload()), null, jws.verifySignature()) ; +		 +		 +	} + +	@Override +	@Nonnull +	public VerificationResult validateSignature(@Nonnull String serializedContent) throws SL20Exception { +		try { +			final AlgorithmConstraints algConstraints = new AlgorithmConstraints(ConstraintType.WHITELIST,    +					SL20Constants.SL20_ALGORITHM_WHITELIST_SIGNING.toArray(new String[SL20Constants.SL20_ALGORITHM_WHITELIST_SIGNING.size()])); -			//set verification key -			jws.setKey(selectedKey); +			final VerificationResult result = validateSignature(serializedContent, trustedCerts, algConstraints); -			//validate signature -			final boolean valid = jws.verifySignature(); -			if (!valid) { +			if (!result.isValidSigned()) {  				log.info("JWS signature invalide. Stopping authentication process ...");  				log.debug("Received JWS msg: " + serializedContent);  				throw new SL20SecurityException("JWS signature invalide.");  			} -			 -			//load payLoad  			log.debug("SL2.0 commando signature validation sucessfull"); -			final JsonNode sl20Req = mapper.getMapper().readTree(jws.getPayload()); -			 -			return new VerificationResult(sl20Req, null, valid) ; -			 +			return result; +						  		} catch (JoseException | JsonParseException e) {  			log.warn("SL2.0 commando signature validation FAILED", e);  			throw new SL20SecurityException(new Object[]{e.getMessage()}, e); @@ -391,4 +396,25 @@ public class JsonSecurityUtils implements IJOSETools{  		return value;  	} +	@Nonnull +	private List<X509Certificate> readCertsFromKeyStore(@Nonnull KeyStore keyStore) throws KeyStoreException { +		final List<X509Certificate> result = new ArrayList<>(); +		 +		final Enumeration<String> aliases = keyStore.aliases(); +		while(aliases.hasMoreElements()) { +			final String el = aliases.nextElement(); +			log.trace("Process TrustStoreEntry: " + el); +			if (keyStore.isCertificateEntry(el)) { +				final Certificate cert = keyStore.getCertificate(el);  +				if (cert != null && cert instanceof X509Certificate) +					result.add((X509Certificate) cert); +				else +					log.info("Can not process entry: " + el + ". Reason: " + cert.toString()); +				 +			} +		} +		 +		return Collections.unmodifiableList(result); +	} +	  } | 
