summaryrefslogtreecommitdiff
path: root/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JsonSecurityUtils.java
diff options
context:
space:
mode:
authorThomas Lenz <thomas.lenz@egiz.gv.at>2020-02-14 15:22:13 +0100
committerThomas Lenz <thomas.lenz@egiz.gv.at>2020-02-14 15:22:13 +0100
commitc4e1a45e7958cab402d83f6f4ae208df1bb2ab58 (patch)
tree73d8118a00bc4eaf5e5a9b0981d3c660843f5a38 /eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JsonSecurityUtils.java
parente23226c47807be597bbbae3891dbb94069d56836 (diff)
downloadEAAF-Components-c4e1a45e7958cab402d83f6f4ae208df1bb2ab58.tar.gz
EAAF-Components-c4e1a45e7958cab402d83f6f4ae208df1bb2ab58.tar.bz2
EAAF-Components-c4e1a45e7958cab402d83f6f4ae208df1bb2ab58.zip
add common-code for KeyStore and Credential handling
Diffstat (limited to 'eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JsonSecurityUtils.java')
-rw-r--r--eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JsonSecurityUtils.java271
1 files changed, 131 insertions, 140 deletions
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 0d2c1815..259c21bf 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
@@ -1,17 +1,12 @@
package at.gv.egiz.eaaf.modules.auth.sl20.utils;
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;
import java.security.cert.X509Certificate;
-import java.util.ArrayList;
import java.util.Collections;
-import java.util.Enumeration;
import java.util.List;
import javax.annotation.Nonnull;
@@ -38,9 +33,13 @@ import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonNode;
import at.gv.egiz.eaaf.core.api.idp.IConfiguration;
+import at.gv.egiz.eaaf.core.exception.EaafKeyAccessException;
import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException;
-import at.gv.egiz.eaaf.core.impl.utils.FileUtils;
-import at.gv.egiz.eaaf.core.impl.utils.KeyStoreUtils;
+import at.gv.egiz.eaaf.core.impl.credential.EaafKeyStoreFactory;
+import at.gv.egiz.eaaf.core.impl.credential.EaafKeyStoreUtils;
+import at.gv.egiz.eaaf.core.impl.credential.KeyStoreConfiguration;
+import at.gv.egiz.eaaf.core.impl.credential.KeyStoreConfiguration.KeyStoreType;
+import at.gv.egiz.eaaf.core.impl.data.Pair;
import at.gv.egiz.eaaf.core.impl.utils.X509Utils;
import at.gv.egiz.eaaf.modules.auth.sl20.Constants;
import at.gv.egiz.eaaf.modules.auth.sl20.data.VerificationResult;
@@ -53,88 +52,60 @@ import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SlCommandoParserException;
public class JsonSecurityUtils implements IJoseTools {
private static final Logger log = LoggerFactory.getLogger(JsonSecurityUtils.class);
- @Autowired(required = true)
- IConfiguration authConfig;
- private Key signPrivKey = null;
- private X509Certificate[] signCertChain = null;
-
- private Key encPrivKey = null;
- private X509Certificate[] encCertChain = null;
-
- private List<X509Certificate> trustedCerts = new ArrayList<>();
-
+ private static final String FRIENDLYNAME_KEYSTORE = "SL2.0 KeyStore";
+ private static final String FRIENDLYNAME_TRUSTSTORE = "SL2.0 TrustStore";
+
+ @Autowired(required = true) IConfiguration authConfig;
+ @Autowired(required = true) EaafKeyStoreFactory keystoreFactory;
+
+ private KeyStore keyStore;
+ private KeyStore trustStore;
+
private static JsonMapper mapper = new JsonMapper();
@PostConstruct
- protected void initalize() {
+ protected void initalize() throws SL20Exception {
log.info("Initialize SL2.0 authentication security constrains ... ");
try {
- if (getKeyStoreFilePath() != null) {
- final KeyStore keyStore = KeyStoreUtils.loadKeyStore(getKeyStoreFilePath(), getKeyStorePassword());
-
- // load signing key
- signPrivKey = keyStore.getKey(getSigningKeyAlias(), getSigningKeyPassword().toCharArray());
- final Certificate[] certChainSigning = keyStore.getCertificateChain(getSigningKeyAlias());
- signCertChain = new X509Certificate[certChainSigning.length];
- for (int i = 0; i < certChainSigning.length; i++) {
- if (certChainSigning[i] instanceof X509Certificate) {
- signCertChain[i] = (X509Certificate) certChainSigning[i];
- } else {
- log.warn("NO X509 certificate for signing: " + certChainSigning[i].getType());
- }
-
- }
-
- // load encryption key
- try {
- encPrivKey = keyStore.getKey(getEncryptionKeyAlias(), getEncryptionKeyPassword().toCharArray());
- if (encPrivKey != null) {
- final Certificate[] certChainEncryption = keyStore.getCertificateChain(getEncryptionKeyAlias());
- encCertChain = new X509Certificate[certChainEncryption.length];
- for (int i = 0; i < certChainEncryption.length; i++) {
- if (certChainEncryption[i] instanceof X509Certificate) {
- encCertChain[i] = (X509Certificate) certChainEncryption[i];
- } else {
- log.warn("NO X509 certificate for encryption: " + certChainEncryption[i].getType());
- }
- }
- } else {
- log.info("No encryption key for SL2.0 found. End-to-End encryption is not used.");
- }
-
- } catch (final Exception e) {
- log.warn("No encryption key for SL2.0 found. End-to-End encryption is not used. Reason: " + e.getMessage(),
- e);
-
- }
-
- // load trusted certificates
- trustedCerts = readCertsFromKeyStore(keyStore);
-
- // some short validation
- if (signPrivKey == null || !(signPrivKey instanceof PrivateKey)) {
- log.info("Can NOT open privateKey for SL2.0 signing. KeyStore=" + getKeyStoreFilePath());
- throw new SL20Exception("sl20.03", new Object[] { "Can NOT open private key for signing" });
-
- }
-
- if (signCertChain == null || signCertChain.length == 0) {
- log.info("NO certificate for SL2.0 signing. KeyStore=" + getKeyStoreFilePath());
- throw new SL20Exception("sl20.03", new Object[] { "NO certificate for SL2.0 signing" });
-
- }
-
- log.info("SL2.0 authentication security constrains initialized.");
-
+ //load KeyStore
+ KeyStoreConfiguration keyStoreConfig = buildKeyStoreConfiguration();
+ keyStore = keystoreFactory.buildNewKeyStore(keyStoreConfig);
+
+ //load TrustStore
+ KeyStoreConfiguration trustStoreConfig = buildTrustStoreConfiguration();
+ trustStore = keystoreFactory.buildNewKeyStore(trustStoreConfig);
+
+ //validate KeyStore entries
+ EaafKeyStoreUtils.getPrivateKeyAndCertificates(keyStore, getSigningKeyAlias(),
+ getSigningKeyPassword(), true, FRIENDLYNAME_KEYSTORE);
+ Pair<Key, X509Certificate[]> encCredentials =
+ EaafKeyStoreUtils.getPrivateKeyAndCertificates(keyStore, getEncryptionKeyAlias(),
+ getEncryptionKeyPassword(), false, FRIENDLYNAME_TRUSTSTORE);
+ if (encCredentials == null) {
+ log.info("No encryption key for SL2.0 found. End-to-End encryption is not used.");
+
+ }
+
+ //validate TrustStore
+ List<X509Certificate> trustedCerts = EaafKeyStoreUtils.readCertsFromKeyStore(trustStore);
+ if (trustedCerts.isEmpty()) {
+ log.info("No certificates in TrustStore: {}. Signature validation will FAIL!",
+ FRIENDLYNAME_TRUSTSTORE);
+
} else {
- log.info("NO SL2.0 authentication security configuration. Initialization was skipped");
+ log.info("Find #{} certificates in TrustStore: {}",
+ trustedCerts.size(), FRIENDLYNAME_TRUSTSTORE);
+
}
+
+ log.info("SL2.0 authentication security constrains initialized.");
} catch (final RuntimeException e) {
throw e;
} catch (final Exception e) {
- log.error("SL2.0 security constrains initialization FAILED.", e);
+ log.error("SL2.0 security constrains initialization FAILED.");
+ throw new SL20Exception("sl20.11", new Object[] {e.getMessage()}, e);
}
@@ -153,15 +124,18 @@ public class JsonSecurityUtils implements IJoseTools {
// set signing information
jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.RSA_USING_SHA256);
- jws.setKey(signPrivKey);
+ Pair<Key, X509Certificate[]> signingCred = EaafKeyStoreUtils.getPrivateKeyAndCertificates(keyStore,
+ getSigningKeyAlias(), getSigningKeyPassword(), true, FRIENDLYNAME_KEYSTORE);
+
+ jws.setKey(signingCred.getFirst());
// TODO:
- jws.setCertificateChainHeaderValue(signCertChain);
- jws.setX509CertSha256ThumbprintHeaderValue(signCertChain[0]);
+ jws.setCertificateChainHeaderValue(signingCred.getSecond());
+ jws.setX509CertSha256ThumbprintHeaderValue(signingCred.getSecond()[0]);
return jws.getCompactSerialization();
- } catch (final JoseException e) {
+ } catch (final JoseException | EaafKeyAccessException e) {
log.warn("Can NOT sign SL2.0 command.", e);
throw new SlCommandoBuildException("Can NOT sign SL2.0 command.", e);
@@ -172,7 +146,7 @@ public class JsonSecurityUtils implements IJoseTools {
@Override
public VerificationResult validateSignature(final String serializedContent, final KeyStore trustStore,
final AlgorithmConstraints algconstraints) throws JoseException, IOException, KeyStoreException {
- final List<X509Certificate> trustedCertificates = readCertsFromKeyStore(trustStore);
+ final List<X509Certificate> trustedCertificates = EaafKeyStoreUtils.readCertsFromKeyStore(trustStore);
return validateSignature(serializedContent, trustedCertificates, algconstraints);
}
@@ -244,7 +218,8 @@ public class JsonSecurityUtils implements IJoseTools {
SL20Constants.SL20_ALGORITHM_WHITELIST_SIGNING
.toArray(new String[SL20Constants.SL20_ALGORITHM_WHITELIST_SIGNING.size()]));
- final VerificationResult result = validateSignature(serializedContent, trustedCerts, algConstraints);
+ final VerificationResult result =
+ validateSignature(serializedContent, EaafKeyStoreUtils.readCertsFromKeyStore(trustStore), algConstraints);
if (!result.isValidSigned()) {
log.info("JWS signature invalide. Stopping authentication process ...");
@@ -256,7 +231,7 @@ public class JsonSecurityUtils implements IJoseTools {
log.debug("SL2.0 commando signature validation sucessfull");
return result;
- } catch (JoseException | JsonParseException e) {
+ } catch (JoseException | JsonParseException | KeyStoreException e) {
log.warn("SL2.0 commando signature validation FAILED", e);
throw new SL20SecurityException(new Object[] { e.getMessage() }, e);
@@ -284,6 +259,9 @@ public class JsonSecurityUtils implements IJoseTools {
// set payload
receiverJwe.setCompactSerialization(compactSerialization);
+ Pair<Key, X509Certificate[]> encryptionCred = EaafKeyStoreUtils.getPrivateKeyAndCertificates(keyStore,
+ getEncryptionKeyAlias(), getEncryptionKeyPassword(), true, FRIENDLYNAME_KEYSTORE);
+
// validate key from header against key from config
final List<X509Certificate> x5cCerts = receiverJwe.getCertificateChainHeaderValue();
final String x5t256 = receiverJwe.getX509CertSha256ThumbprintHeaderValue();
@@ -292,7 +270,7 @@ public class JsonSecurityUtils implements IJoseTools {
log.trace("Sorting received X509 certificates ... ");
final List<X509Certificate> sortedX5cCerts = X509Utils.sortCertificates(x5cCerts);
- if (!sortedX5cCerts.get(0).equals(encCertChain[0])) {
+ if (!sortedX5cCerts.get(0).equals(encryptionCred.getSecond()[0])) {
log.info("Certificate from JOSE header does NOT match encryption certificate");
try {
@@ -307,7 +285,7 @@ public class JsonSecurityUtils implements IJoseTools {
} else if (StringUtils.isNotEmpty(x5t256)) {
log.debug("Found x5t256 fingerprint in JOSE header .... ");
- final String certFingerPrint = X509Util.x5tS256(encCertChain[0]);
+ final String certFingerPrint = X509Util.x5tS256(encryptionCred.getSecond()[0]);
if (!certFingerPrint.equals(x5t256)) {
log.info("X5t256 from JOSE header does NOT match encryption certificate");
log.debug("X5t256 from JOSE header: " + x5t256 + " Encrytption cert: " + certFingerPrint);
@@ -324,12 +302,12 @@ public class JsonSecurityUtils implements IJoseTools {
}
// set key
- receiverJwe.setKey(encPrivKey);
+ receiverJwe.setKey(encryptionCred.getFirst());
// decrypt payload
return mapper.getMapper().readTree(receiverJwe.getPlaintextString());
- } catch (final JoseException e) {
+ } catch (final JoseException | EaafKeyAccessException e) {
log.warn("SL2.0 result decryption FAILED", e);
throw new SL20SecurityException(new Object[] { e.getMessage() }, e);
@@ -340,37 +318,74 @@ public class JsonSecurityUtils implements IJoseTools {
} catch (final IOException e) {
log.warn("Decrypted SL2.0 result can not be parsed.", e);
throw new SlCommandoParserException("Decrypted SL2.0 result can not be parsed", e);
+
}
-
}
@Override
public X509Certificate getEncryptionCertificate() {
- // TODO: maybe update after SL2.0 update on encryption certificate parts
- if (encCertChain != null && encCertChain.length > 0) {
- return encCertChain[0];
- } else {
- return null;
+ Pair<Key, X509Certificate[]> encryptionCred;
+ try {
+ encryptionCred = EaafKeyStoreUtils.getPrivateKeyAndCertificates(keyStore,
+ getEncryptionKeyAlias(), getEncryptionKeyPassword(), false, FRIENDLYNAME_KEYSTORE);
+ if (encryptionCred != null && encryptionCred.getSecond().length > 0) {
+ return encryptionCred.getSecond()[0];
+
+ }
+
+ } catch (EaafKeyAccessException e) {
+ log.trace("Exception is skipped because Encryption is not mandatory on this level", e);
+
}
+
+ return null;
+
}
- private String getKeyStoreFilePath() throws EaafConfigurationException, MalformedURLException {
- return FileUtils.makeAbsoluteUrl(authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_KEYSTORE_PATH),
- authConfig.getConfigurationRootDirectory());
+ private KeyStoreConfiguration buildKeyStoreConfiguration() throws EaafConfigurationException {
+ KeyStoreConfiguration config = new KeyStoreConfiguration();
+ config.setFriendlyName(FRIENDLYNAME_KEYSTORE);
+
+ config.setKeyStoreType(authConfig.getBasicConfiguration(
+ authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_KEYSTORE_TYPE),
+ KeyStoreType.JKS.getKeyStoreType()));
+ config.setKeyStoreName(
+ authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_KEYSTORE_NAME));
+ config.setSoftKeyStoreFilePath(
+ authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_KEYSTORE_PATH));
+ config.setSoftKeyStorePassword(
+ authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_KEYSTORE_PASSWORD));
+
+ //validate configuration state
+ config.validate();
+
+ return config;
+
}
-
- private String getKeyStorePassword() {
- String value = authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_KEYSTORE_PASSWORD);
- if (value != null) {
- value = value.trim();
- }
-
- return value;
-
+
+ private KeyStoreConfiguration buildTrustStoreConfiguration() throws EaafConfigurationException {
+ KeyStoreConfiguration config = new KeyStoreConfiguration();
+ config.setFriendlyName(FRIENDLYNAME_TRUSTSTORE);
+
+ config.setKeyStoreType(authConfig.getBasicConfiguration(
+ authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_TRUSTSTORE_TYPE),
+ KeyStoreType.JKS.getKeyStoreType()));
+ config.setKeyStoreName(
+ authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_TRUSTSTORE_NAME));
+ config.setSoftKeyStoreFilePath(
+ authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_TRUSTSTORE_PATH));
+ config.setSoftKeyStorePassword(
+ authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_TRUSTSTORE_PASSWORD));
+
+ //validate configuration state
+ config.validate();
+
+ return config;
}
+
private String getSigningKeyAlias() {
- String value = authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_KEYSTORE_KEY_SIGN_ALIAS).trim();
+ String value = authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_KEYSTORE_KEY_SIGN_ALIAS);
if (value != null) {
value = value.trim();
}
@@ -378,18 +393,17 @@ public class JsonSecurityUtils implements IJoseTools {
return value;
}
- private String getSigningKeyPassword() {
- String value = authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_KEYSTORE_KEY_SIGN_PASSWORD).trim();
+ private char[] getSigningKeyPassword() {
+ String value = authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_KEYSTORE_KEY_SIGN_PASSWORD);
if (value != null) {
- value = value.trim();
+ return value.trim().toCharArray();
}
- return value;
+ return null;
}
private String getEncryptionKeyAlias() {
- String value = authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_KEYSTORE_KEY_ENCRYPTION_ALIAS)
- .trim();
+ String value = authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_KEYSTORE_KEY_ENCRYPTION_ALIAS);
if (value != null) {
value = value.trim();
}
@@ -397,36 +411,13 @@ public class JsonSecurityUtils implements IJoseTools {
return value;
}
- private String getEncryptionKeyPassword() {
- String value = authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_KEYSTORE_KEY_ENCRYPTION_PASSWORD)
- .trim();
+ private char[] getEncryptionKeyPassword() {
+ String value = authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_KEYSTORE_KEY_ENCRYPTION_PASSWORD);
if (value != null) {
- value = value.trim();
- }
-
- return value;
- }
-
- @Nonnull
- private List<X509Certificate> readCertsFromKeyStore(@Nonnull final 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: {}. Reason: {}", el, cert != null ? cert.getType() : "cert is null");
- }
-
- }
+ return value.trim().toCharArray();
}
- return Collections.unmodifiableList(result);
+ return null;
}
}