summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Lenz <thomas.lenz@egiz.gv.at>2020-06-18 14:39:29 +0200
committerThomas Lenz <thomas.lenz@egiz.gv.at>2020-06-18 14:39:29 +0200
commit0d52fe861a46f8ba595bdd34b106c98096c4304b (patch)
tree566f30e8c6bfebddfa90b7062ec952b1bd945916
parentf39a0a004bbe6b6b126218993767b897efa06745 (diff)
downloadEAAF-Components-0d52fe861a46f8ba595bdd34b106c98096c4304b.tar.gz
EAAF-Components-0d52fe861a46f8ba595bdd34b106c98096c4304b.tar.bz2
EAAF-Components-0d52fe861a46f8ba595bdd34b106c98096c4304b.zip
add symmetric-key functionality into EaafKeyStoreFactory that supports passphrase based symmetric keys and keys from HSM-Facade
-rw-r--r--eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/credential/EaafKeyStoreFactory.java123
-rw-r--r--eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/credential/EaafKeyStoreUtils.java5
-rw-r--r--eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/credential/SymmetricKeyConfiguration.java221
-rw-r--r--eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/SecurePendingRequestIdGenerationStrategy.java57
-rw-r--r--eaaf_core_utils/src/main/resources/messages/eaaf_utils_message.properties2
-rw-r--r--eaaf_core_utils/src/test/java/at/gv/egiz/eaaf/core/test/credentials/EaafKeyStoreFactoryTest.java162
-rw-r--r--eaaf_core_utils/src/test/java/at/gv/egiz/eaaf/core/test/credentials/SymmetricKeyConfigurationTest.java162
7 files changed, 705 insertions, 27 deletions
diff --git a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/credential/EaafKeyStoreFactory.java b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/credential/EaafKeyStoreFactory.java
index 9db38670..711a3517 100644
--- a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/credential/EaafKeyStoreFactory.java
+++ b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/credential/EaafKeyStoreFactory.java
@@ -2,6 +2,7 @@ package at.gv.egiz.eaaf.core.impl.credential;
import java.io.IOException;
import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.security.Key;
@@ -12,13 +13,19 @@ import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Provider;
import java.security.Security;
+import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.KeySpec;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.PostConstruct;
+import javax.crypto.SecretKey;
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.spec.PBEKeySpec;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
@@ -26,10 +33,12 @@ import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
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.exceptions.EaafException;
import at.gv.egiz.eaaf.core.exceptions.EaafFactoryException;
import at.gv.egiz.eaaf.core.impl.credential.KeyStoreConfiguration.KeyStoreType;
+import at.gv.egiz.eaaf.core.impl.credential.SymmetricKeyConfiguration.SymmetricKeyType;
import at.gv.egiz.eaaf.core.impl.data.Pair;
import at.gv.egiz.eaaf.core.impl.utils.FileUtils;
import at.gv.egiz.eaaf.core.impl.utils.KeyStoreUtils;
@@ -53,6 +62,8 @@ public class EaafKeyStoreFactory {
public static final String ERRORCODE_06 = "internal.keystore.06";
public static final String ERRORCODE_07 = "internal.keystore.07";
public static final String ERRORCODE_10 = "internal.keystore.10";
+
+ public static final String ERRORCODE_KEY_00 = "internal.key.00";
private static final String HSM_FACADE_PROVIDER_CLASS = "at.asitplus.hsmfacade.provider.HsmFacadeProvider";
private static final String HSM_FACADE_KEYSTORELOADPARAMETERS_CLASS
@@ -72,6 +83,43 @@ public class EaafKeyStoreFactory {
private boolean isHsmFacadeInitialized = false;
/**
+ * Get a new symmetric key based on a {@link SymmetricKeyConfiguration} object.
+ *
+ * @param config Symmetric key configuration
+ * @return {@link Pair} of a new {@link SecretKey} instance and an optional {@link Provider}.
+ * The {@link SecretKey} is {@link Nonnull}. If the {@link Provider} is not <code>null</code>
+ * this {@link SecretKey} requires a specific {@link Provider} for {@link Key} operations.
+ * @throws EaafException In case of a KeyStore initialization error
+ */
+ @Nonnull
+ public Pair<SecretKey, Provider> buildNewSymmetricKey(SymmetricKeyConfiguration config) throws EaafException {
+ log.trace("Starting symmetric-key generation based on configuration object ... ");
+ if (SymmetricKeyType.PASSPHRASE.equals(config.getKeyType())) {
+ return generatePassPhraseBasedSymmetricKey(config);
+
+ } else if (SymmetricKeyType.HSMFACADE.equals(config.getKeyType())) {
+ if (isHsmFacadeInitialized) {
+ return getSymmetricKeyFromHsmFacade(config);
+
+ } else {
+ log.error("HSMFacade can NOT be used for symmetric Key: {} because {} is not initialized",
+ config.getFriendlyName());
+ throw new EaafConfigurationException(ERRORCODE_00,
+ new Object[] { config.getFriendlyName() });
+
+ }
+
+ } else {
+ log.warn("Symmetric KeyType: {} is unrecognized", config.getKeyType());
+ throw new EaafConfigurationException(ERRORCODE_01,
+ new Object[] { config.getFriendlyName() });
+
+ }
+
+
+ }
+
+ /**
* Get a new KeyStore based on a KeyStore configuration-object.
*
* @param config KeyStore configuration
@@ -241,24 +289,31 @@ public class EaafKeyStoreFactory {
@Nonnull
private Pair<KeyStore, Provider> getKeyStoreFromHsmFacade(KeyStoreConfiguration config)
throws EaafFactoryException, EaafConfigurationException {
- final String keyStoreName = checkConfigurationParameter(config.getKeyStoreName(),
- ERRORCODE_06, config.getFriendlyName(), "KeyStoreName missing for HSM Facade");
+ return getKeyStoreFromHsmFacade(config.getKeyStoreName(), config.getFriendlyName());
+
+ }
+
+ @Nonnull
+ private Pair<KeyStore, Provider> getKeyStoreFromHsmFacade(String keyStoreName, String friendlyName)
+ throws EaafFactoryException, EaafConfigurationException {
+ final String validatedKeyStoreName = checkConfigurationParameter(keyStoreName,
+ ERRORCODE_06, friendlyName, "KeyStoreName missing for HSM Facade");
try {
final KeyStore keyStore = KeyStore.getInstance(HSM_FACADE_KEYSTORE_TYPE, HSM_FACADE_PROVIDER);
- keyStore.load(getHsmFacadeKeyStoreParameter(keyStoreName));
+ keyStore.load(getHsmFacadeKeyStoreParameter(validatedKeyStoreName));
return Pair.newInstance(keyStore, keyStore.getProvider());
} catch (NoSuchAlgorithmException | CertificateException | IOException | KeyStoreException
| NoSuchProviderException | EaafException e) {
log.error("Can not initialize KeyStore: {} with reason: {}",
- config.getFriendlyName(), e.getMessage());
+ friendlyName, e.getMessage());
throw new EaafFactoryException(ERRORCODE_06,
- new Object[] { config.getFriendlyName(), e.getMessage() }, e);
+ new Object[] {friendlyName, e.getMessage() }, e);
}
}
-
+
private KeyStore.LoadStoreParameter getHsmFacadeKeyStoreParameter(String keyStoreName) throws EaafException {
try {
Class<?> clazz = Class.forName(HSM_FACADE_KEYSTORELOADPARAMETERS_CLASS);
@@ -274,6 +329,62 @@ public class EaafKeyStoreFactory {
}
+ @Nonnull
+ private Pair<SecretKey, Provider> generatePassPhraseBasedSymmetricKey(SymmetricKeyConfiguration config)
+ throws EaafConfigurationException {
+ checkConfigurationParameter(config.getSoftKeyPassphrase(),
+ ERRORCODE_KEY_00, config.getFriendlyName(), "passphrase missing");
+ checkConfigurationParameter(config.getSoftKeySalt(),
+ ERRORCODE_KEY_00, config.getFriendlyName(), "salt missing");
+
+ try {
+ final SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBKDF2WITHHMACSHA256");
+ final KeySpec spec = new PBEKeySpec(
+ config.getSoftKeyPassphrase().toCharArray(),
+ config.getSoftKeySalt().getBytes("UTF-8"),
+ 10000, 128);
+ return Pair.newInstance(keyFactory.generateSecret(spec), null);
+
+ } catch (NoSuchAlgorithmException | InvalidKeySpecException | UnsupportedEncodingException e) {
+ log.error("Passphrase based symmetric-key generation FAILED", e);
+ throw new EaafConfigurationException(ERRORCODE_KEY_00,
+ new Object[] { config.getFriendlyName(), e.getMessage() },
+ e);
+
+ }
+ }
+
+ @Nonnull
+ private Pair<SecretKey, Provider> getSymmetricKeyFromHsmFacade(SymmetricKeyConfiguration config)
+ throws EaafFactoryException, EaafConfigurationException, EaafKeyAccessException {
+ Pair<KeyStore, Provider> keyStore = getKeyStoreFromHsmFacade(
+ config.getKeyStoreName(), config.getFriendlyName());
+
+ checkConfigurationParameter(config.getKeyAlias(),
+ ERRORCODE_KEY_00, config.getFriendlyName(), "keyAlias missing");
+
+ try {
+ SecretKey secretKey = (SecretKey) keyStore.getFirst().getKey(config.getKeyAlias(), null);
+ if (secretKey == null) {
+ throw new EaafKeyAccessException(EaafKeyAccessException.ERROR_CODE_09,
+ config.getFriendlyName(), config.getKeyAlias(), "No SecretKey with Alias ");
+
+ }
+
+ return Pair.newInstance(secretKey, keyStore.getSecond());
+
+ } catch (UnrecoverableKeyException | KeyStoreException | NoSuchAlgorithmException e) {
+ throw new EaafKeyAccessException(EaafKeyAccessException.ERROR_CODE_09, e,
+ config.getFriendlyName(), config.getKeyAlias(), e.getMessage());
+
+ } catch (ClassCastException e) {
+ throw new EaafKeyAccessException(EaafKeyAccessException.ERROR_CODE_09,
+ config.getFriendlyName(), config.getKeyAlias(), "Wrong SecretKey type ");
+
+ }
+
+ }
+
private X509Certificate getHsmFacadeTrustSslCertificate() throws EaafConfigurationException {
try {
final String certFilePath = getConfigurationParameter(CONFIG_PROP_HSM_FACADE_SSLTRUST);
diff --git a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/credential/EaafKeyStoreUtils.java b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/credential/EaafKeyStoreUtils.java
index b4b44724..12541222 100644
--- a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/credential/EaafKeyStoreUtils.java
+++ b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/credential/EaafKeyStoreUtils.java
@@ -24,13 +24,13 @@ import lombok.extern.slf4j.Slf4j;
public class EaafKeyStoreUtils {
private static final String ERROR_MSG_REASON = "Maybe 'Alias' is not valid";
private static final String ERROR_MSG_1 = "Can NOT access key: {} in KeyStore: {}. Reason: {}";
- private static final String ERROR_MSG_2 = "Key: {} will be NOT available";
+ private static final String ERROR_MSG_2 = "Key: {} will be NOT available";
/**
* Read all certificates from a {@link KeyStore}.
*
* @param keyStore KeyStore with certificates
- * @return {@link List} of {@link X509Certificate}, but never null
+ * @return Unmodifiable {@link List} of {@link X509Certificate}, but never null
* @throws KeyStoreException In case of an error during KeyStore operations
*/
@Nonnull
@@ -45,6 +45,7 @@ public class EaafKeyStoreUtils {
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");
}
diff --git a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/credential/SymmetricKeyConfiguration.java b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/credential/SymmetricKeyConfiguration.java
new file mode 100644
index 00000000..45b51975
--- /dev/null
+++ b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/credential/SymmetricKeyConfiguration.java
@@ -0,0 +1,221 @@
+package at.gv.egiz.eaaf.core.impl.credential;
+
+import java.util.Map;
+
+import javax.annotation.Nonnull;
+
+import org.apache.commons.lang3.StringUtils;
+
+import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+@Getter
+@Setter
+public class SymmetricKeyConfiguration {
+
+ public static final String PROP_CONFIG_KEY_TYPE =
+ "key.type";
+
+ public static final String PROP_CONFIG_HSMFACADE_NAME =
+ "keystore.name";
+ public static final String PROP_CONFIG_HSM_KEY_ALIAS =
+ "key.alias";
+
+ public static final String PROP_CONFIG_SOFTWARE_KEY_PASSPHRASE =
+ "key.passphrase";
+ public static final String PROP_CONFIG_SOFTWARE_KEY_SALT =
+ "key.salt";
+
+ /**
+ * FriendlyName for this KeyStore. Mainly used for logging.
+ */
+ private String friendlyName;
+
+ /**
+ * General type of the KeyStore that should be generated.
+ */
+ private SymmetricKeyType keyType;
+
+ /**
+ * Name of the KeyStore in HSM Facade.
+ */
+ private String keyStoreName;
+
+ /**
+ * Alias of the Key in HSM Facade keystore.
+ */
+ private String keyAlias;
+
+ /**
+ * Software key passphrase.
+ */
+ private String softKeyPassphrase;
+
+ /**
+ * Software key salt.
+ */
+ private String softKeySalt;
+
+ /**
+ * Build a {@link SymmetricKeyConfiguration} from a configuration map. <br>
+ * <p>
+ * The configuration parameters defined in this class are used to load the
+ * configuration.
+ * </p>
+ *
+ * @param config Configuration
+ * @param friendlyName FriendlyName for this KeyStore
+ * @return Configuration object for {@link EaafKeyStoreFactory}
+ * @throws EaafConfigurationException In case of a configuration error.
+ */
+ public static SymmetricKeyConfiguration buildFromConfigurationMap(Map<String, String> config,
+ String friendlyName) throws EaafConfigurationException {
+
+ final SymmetricKeyConfiguration internalConfig = new SymmetricKeyConfiguration();
+ internalConfig.setFriendlyName(friendlyName);
+
+ final SymmetricKeyType internalKeyStoreType = SymmetricKeyType.fromString(
+ getConfigurationParameter(config, PROP_CONFIG_KEY_TYPE));
+ if (internalKeyStoreType != null) {
+ internalConfig.setKeyType(internalKeyStoreType);
+
+ } else {
+ log.error("Symmetric Key-configuration: {} sets an unknown Keytype: {}",
+ friendlyName, getConfigurationParameter(config, PROP_CONFIG_KEY_TYPE));
+ throw new EaafConfigurationException(EaafKeyStoreFactory.ERRORCODE_01,
+ new Object[] { friendlyName });
+
+ }
+
+ if (internalKeyStoreType.equals(SymmetricKeyType.HSMFACADE)) {
+ log.trace("Set-up HSM-Facade Symmentric-Key ... ");
+ internalConfig.setKeyStoreName(getConfigurationParameter(config, PROP_CONFIG_HSMFACADE_NAME));
+ internalConfig.setKeyAlias(getConfigurationParameter(config, PROP_CONFIG_HSM_KEY_ALIAS));
+
+ } else {
+ log.trace("Set-up software passphrase based symmetric key ... ");
+ internalConfig.setSoftKeyPassphrase(getConfigurationParameter(config, PROP_CONFIG_SOFTWARE_KEY_PASSPHRASE));
+ internalConfig.setSoftKeySalt(getConfigurationParameter(config, PROP_CONFIG_SOFTWARE_KEY_SALT));
+
+ }
+
+ return internalConfig;
+ }
+
+ /**
+ * Set the Type of the symmetric key based on String identifier.
+ *
+ * @param keyType String based KeyStore type
+ * @throws EaafConfigurationException In case of an unknown KeyStore type
+ */
+ public void setKeyType(@Nonnull String keyType) throws EaafConfigurationException {
+ final SymmetricKeyType internalKeyStoreType = SymmetricKeyType.fromString(keyType);
+ if (internalKeyStoreType != null) {
+ setKeyType(internalKeyStoreType);
+
+ } else {
+ log.error("KeyStore: {} sets an unknown KeyStore type: {}",
+ friendlyName, keyType);
+ throw new EaafConfigurationException(EaafKeyStoreFactory.ERRORCODE_01,
+ new Object[] { friendlyName });
+
+ }
+
+ }
+
+ /**
+ * Set the Type of the symmetric Key based on String identifier.
+ *
+ * @param type of tke symmetric key
+ */
+ public void setKeyType(@Nonnull SymmetricKeyType type) {
+ this.keyType = type;
+
+ }
+
+ /**
+ * Validate the internal state of this configuration object.
+ *
+ * @throws EaafConfigurationException In case of a configuration error
+ */
+ public void validate() throws EaafConfigurationException {
+ if (SymmetricKeyType.HSMFACADE.equals(keyType)) {
+ log.trace("Validate HSM-Facade symmetric key ... ");
+ checkConfigurationValue(keyStoreName, EaafKeyStoreFactory.ERRORCODE_07,
+ friendlyName, "Missing 'KeyStoreName' for HSM-Facade");
+ checkConfigurationValue(keyStoreName, EaafKeyStoreFactory.ERRORCODE_07,
+ friendlyName, "Missing 'KeyAlias' for HSM-Facade");
+
+ } else {
+ log.trace("Validate passphrase based symmetric key ... ");
+ checkConfigurationValue(softKeyPassphrase, EaafKeyStoreFactory.ERRORCODE_07,
+ friendlyName, "Missing 'passphrase' for symmetric-key generation");
+ checkConfigurationValue(softKeySalt, EaafKeyStoreFactory.ERRORCODE_07,
+ friendlyName, "Missing 'salt' for symmetric-key generation");
+
+ }
+ }
+
+ public enum SymmetricKeyType {
+ PASSPHRASE("passphrase"), HSMFACADE("hsmfacade");
+
+ private final String keyType;
+
+ SymmetricKeyType(final String keyStoreType) {
+ this.keyType = keyStoreType;
+ }
+
+ /**
+ * Get Type of this Key.
+ *
+ * @return
+ */
+ public String getKeyType() {
+ return this.keyType;
+ }
+
+ /**
+ * Get KeyType from String representation.
+ *
+ * @param s Config parameter
+ * @return
+ */
+ public static SymmetricKeyType fromString(final String s) {
+ try {
+ return SymmetricKeyType.valueOf(s.toUpperCase());
+
+ } catch (IllegalArgumentException | NullPointerException e) {
+ return null;
+ }
+ }
+
+ @Override
+ public String toString() {
+ return getKeyType();
+
+ }
+ }
+
+ @Nonnull
+ private static String getConfigurationParameter(@Nonnull Map<String, String> config,
+ @Nonnull String configParamKey)
+ throws EaafConfigurationException {
+ final String configValue = config.get(configParamKey);
+ checkConfigurationValue(configValue, EaafKeyStoreFactory.ERRORCODE_04, configParamKey);
+ return configValue;
+
+ }
+
+ private static void checkConfigurationValue(String configValue, String errorCode, String... params)
+ throws EaafConfigurationException {
+ if (StringUtils.isEmpty(configValue)) {
+ throw new EaafConfigurationException(errorCode,
+ params);
+
+ }
+
+ }
+}
diff --git a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/SecurePendingRequestIdGenerationStrategy.java b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/SecurePendingRequestIdGenerationStrategy.java
index bc770a8c..ad6471d5 100644
--- a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/SecurePendingRequestIdGenerationStrategy.java
+++ b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/SecurePendingRequestIdGenerationStrategy.java
@@ -1,19 +1,14 @@
package at.gv.egiz.eaaf.core.impl.utils;
import java.io.UnsupportedEncodingException;
-import java.nio.charset.Charset;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
-import java.security.spec.InvalidKeySpecException;
-import java.security.spec.KeySpec;
import java.util.Arrays;
import java.util.Base64;
import javax.annotation.PostConstruct;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
-import javax.crypto.SecretKeyFactory;
-import javax.crypto.spec.PBEKeySpec;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
@@ -32,6 +27,9 @@ import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException;
import at.gv.egiz.eaaf.core.exceptions.EaafException;
import at.gv.egiz.eaaf.core.exceptions.EaafIllegalStateException;
import at.gv.egiz.eaaf.core.exceptions.PendingReqIdValidationException;
+import at.gv.egiz.eaaf.core.impl.credential.EaafKeyStoreFactory;
+import at.gv.egiz.eaaf.core.impl.credential.SymmetricKeyConfiguration;
+import at.gv.egiz.eaaf.core.impl.credential.SymmetricKeyConfiguration.SymmetricKeyType;
/**
* PendingRequestId generation strategy based on signed tokens that facilitates
@@ -45,11 +43,22 @@ public class SecurePendingRequestIdGenerationStrategy
private static final Logger log =
LoggerFactory.getLogger(SecurePendingRequestIdGenerationStrategy.class);
- @Autowired(required = true)
- IConfiguration baseConfig;
+ @Autowired(required = true) IConfiguration baseConfig;
+ @Autowired EaafKeyStoreFactory keyStoreFactory;
+ private static final String FRIENDLYNAME = "pendingRequestId key";
+
+ public static final String CONFIG_PROP_PENDINGREQUESTID_DIGIST_TYPE =
+ "core.pendingrequestid.digist.type";
public static final String CONFIG_PROP_PENDINGREQUESTID_DIGIST_SECRET =
"core.pendingrequestid.digist.secret";
+
+ public static final String CONFIG_PROP_PENDINGREQUESTID_DIGIST_HSM_KEYSTORE =
+ "core.pendingrequestid.digist.keystore.name";
+ public static final String CONFIG_PROP_PENDINGREQUESTID_DIGIST_HSM_ALIAS =
+ "core.pendingrequestid.digist.key.alias";
+
+
public static final String CONFIG_PROP_PENDINGREQUESTID_DIGIST_ALGORITHM =
"core.pendingrequestid.digist.algorithm";
public static final String CONFIG_PROP_PENDINGREQUESTID_MAX_LIFETIME =
@@ -67,7 +76,7 @@ public class SecurePendingRequestIdGenerationStrategy
private final int maxPendingReqIdSize = 1024;
private String digistAlgorithm = null;
private SecretKey key = null;
- private final byte[] salt = "notRequiredInThisScenario".getBytes(Charset.defaultCharset());
+ private final String salt = "notRequiredInThisScenario";
@Override
public String generateExternalPendingRequestId() throws EaafException {
@@ -183,13 +192,6 @@ public class SecurePendingRequestIdGenerationStrategy
private void initialize() throws EaafConfigurationException {
log.debug("Initializing " + this.getClass().getName() + " ... ");
- final String pendingReqIdDigistSecret =
- baseConfig.getBasicConfiguration(CONFIG_PROP_PENDINGREQUESTID_DIGIST_SECRET);
- if (StringUtils.isEmpty(pendingReqIdDigistSecret)) {
- throw new EaafConfigurationException("config.08",
- new Object[] { CONFIG_PROP_PENDINGREQUESTID_DIGIST_SECRET });
- }
-
digistAlgorithm = baseConfig.getBasicConfiguration(
CONFIG_PROP_PENDINGREQUESTID_DIGIST_ALGORITHM, DEFAULT_PENDINGREQUESTID_DIGIST_ALGORITHM);
@@ -197,12 +199,29 @@ public class SecurePendingRequestIdGenerationStrategy
Integer.parseInt(baseConfig.getBasicConfiguration(CONFIG_PROP_PENDINGREQUESTID_MAX_LIFETIME,
DEFAULT_PENDINGREQUESTID_MAX_LIFETIME));
+
+ SymmetricKeyConfiguration secretKeyConfig = new SymmetricKeyConfiguration();
+ secretKeyConfig.setFriendlyName(FRIENDLYNAME);
+ secretKeyConfig.setKeyType(
+ baseConfig.getBasicConfiguration(CONFIG_PROP_PENDINGREQUESTID_DIGIST_TYPE,
+ SymmetricKeyType.PASSPHRASE.name()));
+
+ secretKeyConfig.setSoftKeyPassphrase(
+ baseConfig.getBasicConfiguration(CONFIG_PROP_PENDINGREQUESTID_DIGIST_SECRET));
+ secretKeyConfig.setSoftKeySalt(salt);
+
+ secretKeyConfig.setKeyStoreName(
+ baseConfig.getBasicConfiguration(CONFIG_PROP_PENDINGREQUESTID_DIGIST_HSM_KEYSTORE));
+ secretKeyConfig.setKeyAlias(
+ baseConfig.getBasicConfiguration(CONFIG_PROP_PENDINGREQUESTID_DIGIST_HSM_ALIAS));
+
+ //validate symmetric-key configuration
+ secretKeyConfig.validate();
+
try {
- final SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBKDF2WITHHMACSHA256");
- final KeySpec spec = new PBEKeySpec(pendingReqIdDigistSecret.toCharArray(), salt, 10000, 128);
- key = keyFactory.generateSecret(spec);
+ key = keyStoreFactory.buildNewSymmetricKey(secretKeyConfig).getFirst();
- } catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
+ } catch (EaafException e) {
log.error("Can NOT initialize TokenService with configuration object", e);
throw new EaafConfigurationException("config.09",
new Object[] { CONFIG_PROP_PENDINGREQUESTID_DIGIST_SECRET, "Can NOT generate HMAC key" },
diff --git a/eaaf_core_utils/src/main/resources/messages/eaaf_utils_message.properties b/eaaf_core_utils/src/main/resources/messages/eaaf_utils_message.properties
index e0c86b03..572a3f5a 100644
--- a/eaaf_core_utils/src/main/resources/messages/eaaf_utils_message.properties
+++ b/eaaf_core_utils/src/main/resources/messages/eaaf_utils_message.properties
@@ -13,6 +13,8 @@ internal.keystore.08=Can not access Key: {1} in KeyStore: {0}
internal.keystore.09=Can not access Key: {1} in KeyStore: {0} Reason: {2}
internal.keystore.10=HSM-Facade NOT INITIALIZED. Find HSM-Facade class: {0} put that looks WRONG.
+internal.key.00=Can not generate passphrase based symmetric-key: {0} Reason: {1}
+
internal.httpclient.00=HttpClient:{0} uses http Basic-Auth, but 'Username' is NOT set
internal.httpclient.01=HttpClient:{0} uses X509 client-auth, but 'KeyStoreConfig' is NOT set
internal.httpclient.02=HttpClient:{0} uses KeyStore:{1}, but 'keyPassword' is NOT set
diff --git a/eaaf_core_utils/src/test/java/at/gv/egiz/eaaf/core/test/credentials/EaafKeyStoreFactoryTest.java b/eaaf_core_utils/src/test/java/at/gv/egiz/eaaf/core/test/credentials/EaafKeyStoreFactoryTest.java
index cefb1e7e..fc945fdd 100644
--- a/eaaf_core_utils/src/test/java/at/gv/egiz/eaaf/core/test/credentials/EaafKeyStoreFactoryTest.java
+++ b/eaaf_core_utils/src/test/java/at/gv/egiz/eaaf/core/test/credentials/EaafKeyStoreFactoryTest.java
@@ -7,6 +7,8 @@ import java.security.Provider;
import java.security.cert.X509Certificate;
import java.util.List;
+import javax.crypto.SecretKey;
+
import org.apache.commons.lang3.RandomStringUtils;
import org.junit.Assert;
import org.junit.Before;
@@ -33,6 +35,8 @@ 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.credential.SymmetricKeyConfiguration;
+import at.gv.egiz.eaaf.core.impl.credential.SymmetricKeyConfiguration.SymmetricKeyType;
import at.gv.egiz.eaaf.core.impl.data.Pair;
import at.gv.egiz.eaaf.core.test.dummy.DummyAuthConfigMap;
import io.grpc.StatusRuntimeException;
@@ -372,6 +376,67 @@ public class EaafKeyStoreFactoryTest {
}
@Test
+ @DirtiesContext
+ public void symmetricSoftwareKeyWithOutConfig() {
+ final EaafKeyStoreFactory keyStoreFactory = context.getBean(EaafKeyStoreFactory.class);
+ Assert.assertFalse("HSM Facade state wrong", keyStoreFactory.isHsmFacadeInitialized());
+
+ SymmetricKeyConfiguration keyConfig = new SymmetricKeyConfiguration();
+ keyConfig.setFriendlyName("jUnit test");
+ keyConfig.setKeyType(SymmetricKeyType.PASSPHRASE);
+ try {
+ keyStoreFactory.buildNewSymmetricKey(keyConfig);
+ Assert.fail("Wrong config not detected");
+
+ } catch (final EaafException e) {
+ org.springframework.util.Assert.isInstanceOf(EaafConfigurationException.class, e, "Wong ExceptionType");
+ Assert.assertEquals("wrong errorCode", "internal.key.00", e.getErrorId());
+
+ }
+ }
+
+ @Test
+ @DirtiesContext
+ public void symmetricSoftwareKeyWithOutSalt() {
+ final EaafKeyStoreFactory keyStoreFactory = context.getBean(EaafKeyStoreFactory.class);
+ Assert.assertFalse("HSM Facade state wrong", keyStoreFactory.isHsmFacadeInitialized());
+
+ SymmetricKeyConfiguration keyConfig = new SymmetricKeyConfiguration();
+ keyConfig.setFriendlyName("jUnit test");
+ keyConfig.setKeyType(SymmetricKeyType.PASSPHRASE);
+ keyConfig.setSoftKeyPassphrase(RandomStringUtils.randomAlphanumeric(10));
+ try {
+ keyStoreFactory.buildNewSymmetricKey(keyConfig);
+ Assert.fail("Wrong config not detected");
+
+ } catch (final EaafException e) {
+ org.springframework.util.Assert.isInstanceOf(EaafConfigurationException.class, e, "Wong ExceptionType");
+ Assert.assertEquals("wrong errorCode", "internal.key.00", e.getErrorId());
+
+ }
+ }
+
+ @Test
+ @DirtiesContext
+ public void symmetricSoftwareKeyValid() throws EaafException {
+ final EaafKeyStoreFactory keyStoreFactory = context.getBean(EaafKeyStoreFactory.class);
+ Assert.assertFalse("HSM Facade state wrong", keyStoreFactory.isHsmFacadeInitialized());
+
+ SymmetricKeyConfiguration keyConfig = new SymmetricKeyConfiguration();
+ keyConfig.setFriendlyName("jUnit test");
+ keyConfig.setKeyType(SymmetricKeyType.PASSPHRASE);
+ keyConfig.setSoftKeyPassphrase(RandomStringUtils.randomAlphanumeric(10));
+ keyConfig.setSoftKeySalt(RandomStringUtils.randomAlphanumeric(10));
+
+ Pair<SecretKey, Provider> key = keyStoreFactory.buildNewSymmetricKey(keyConfig);
+ Assert.assertNotNull("Key container is null", key);
+ Assert.assertNotNull("Key is null", key.getFirst());
+ Assert.assertNull("Provider is not null", key.getSecond());
+
+ }
+
+ @Test
+ @DirtiesContext
public void hsmFacadeOnlyHostConfig() {
mapConfig.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_HOST,
RandomStringUtils.randomNumeric(10));
@@ -386,6 +451,7 @@ public class EaafKeyStoreFactoryTest {
}
@Test
+ @DirtiesContext
public void hsmFacadeMissingPort() {
mapConfig.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_HOST,
RandomStringUtils.randomNumeric(10));
@@ -405,6 +471,7 @@ public class EaafKeyStoreFactoryTest {
}
@Test
+ @DirtiesContext
public void hsmFacadeMissingUsername() {
mapConfig.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_HOST,
RandomStringUtils.randomNumeric(10));
@@ -423,6 +490,7 @@ public class EaafKeyStoreFactoryTest {
}
@Test
+ @DirtiesContext
public void hsmFacadeMissingPassword() {
mapConfig.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_HOST,
RandomStringUtils.randomNumeric(10));
@@ -442,6 +510,7 @@ public class EaafKeyStoreFactoryTest {
}
@Test
+ @DirtiesContext
public void hsmFacadeMissingTrustedCertificate() {
mapConfig.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_HOST,
RandomStringUtils.randomNumeric(10));
@@ -463,6 +532,7 @@ public class EaafKeyStoreFactoryTest {
}
@Test
+ @DirtiesContext
public void hsmFacadeMissingTrustedCertificateFile() {
mapConfig.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_HOST,
RandomStringUtils.randomNumeric(10));
@@ -486,6 +556,7 @@ public class EaafKeyStoreFactoryTest {
}
@Test
+ @DirtiesContext
public void hsmFacadeMissingWrongTrustedCertificate() {
mapConfig.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_HOST,
RandomStringUtils.randomNumeric(10));
@@ -579,6 +650,97 @@ public class EaafKeyStoreFactoryTest {
@Test
@DirtiesContext
+ public void symmetricHsmFacadeKeyWithOutConfig() {
+ configureHsmFacade();
+
+ final EaafKeyStoreFactory keyStoreFactory = context.getBean(EaafKeyStoreFactory.class);
+ Assert.assertTrue("HSM Facade state wrong", keyStoreFactory.isHsmFacadeInitialized());
+
+ SymmetricKeyConfiguration keyConfig = new SymmetricKeyConfiguration();
+ keyConfig.setFriendlyName("jUnit test");
+ keyConfig.setKeyType(SymmetricKeyType.HSMFACADE);
+ try {
+ keyStoreFactory.buildNewSymmetricKey(keyConfig);
+ Assert.fail("Wrong config not detected");
+
+ } catch (final EaafException e) {
+ org.springframework.util.Assert.isInstanceOf(EaafConfigurationException.class, e, "Wong ExceptionType");
+ Assert.assertEquals("wrong errorCode", "internal.keystore.06", e.getErrorId());
+
+ }
+ }
+
+ @Test
+ @DirtiesContext
+ public void symmetricHsmFacadeKeyWithOutKeyAlias() {
+ configureHsmFacade();
+
+ final EaafKeyStoreFactory keyStoreFactory = context.getBean(EaafKeyStoreFactory.class);
+ Assert.assertTrue("HSM Facade state wrong", keyStoreFactory.isHsmFacadeInitialized());
+
+ SymmetricKeyConfiguration keyConfig = new SymmetricKeyConfiguration();
+ keyConfig.setFriendlyName("jUnit test");
+ keyConfig.setKeyType(SymmetricKeyType.HSMFACADE);
+ keyConfig.setKeyStoreName("authhandler");
+ try {
+ keyStoreFactory.buildNewSymmetricKey(keyConfig);
+ Assert.fail("Wrong config not detected");
+
+ } catch (final EaafException e) {
+ org.springframework.util.Assert.isInstanceOf(EaafConfigurationException.class, e, "Wong ExceptionType");
+ Assert.assertEquals("wrong errorCode", "internal.key.00", e.getErrorId());
+
+ }
+ }
+
+ @Test
+ @DirtiesContext
+ public void symmetricHsmFacadeKeyWrongKeyAlias() {
+ configureHsmFacade();
+
+ final EaafKeyStoreFactory keyStoreFactory = context.getBean(EaafKeyStoreFactory.class);
+ Assert.assertTrue("HSM Facade state wrong", keyStoreFactory.isHsmFacadeInitialized());
+
+ SymmetricKeyConfiguration keyConfig = new SymmetricKeyConfiguration();
+ keyConfig.setFriendlyName("jUnit test");
+ keyConfig.setKeyType(SymmetricKeyType.HSMFACADE);
+ keyConfig.setKeyStoreName("authhandler");
+ keyConfig.setKeyAlias("notExist");
+
+ try {
+ keyStoreFactory.buildNewSymmetricKey(keyConfig);
+ Assert.fail("Wrong config not detected");
+
+ } catch (final EaafException e) {
+ org.springframework.util.Assert.isInstanceOf(EaafKeyAccessException.class, e, "Wong ExceptionType");
+ Assert.assertEquals("wrong errorCode", "internal.keystore.09", e.getErrorId());
+
+ }
+ }
+
+ @Test
+ @DirtiesContext
+ public void symmetricHsmFacadeKeyValid() throws EaafException {
+ configureHsmFacade();
+
+ final EaafKeyStoreFactory keyStoreFactory = context.getBean(EaafKeyStoreFactory.class);
+ Assert.assertTrue("HSM Facade state wrong", keyStoreFactory.isHsmFacadeInitialized());
+
+ SymmetricKeyConfiguration keyConfig = new SymmetricKeyConfiguration();
+ keyConfig.setFriendlyName("jUnit test");
+ keyConfig.setKeyType(SymmetricKeyType.HSMFACADE);
+ keyConfig.setKeyStoreName("authhandler");
+ keyConfig.setKeyAlias("aes-key-1");
+
+ Pair<SecretKey, Provider> key = keyStoreFactory.buildNewSymmetricKey(keyConfig);
+ Assert.assertNotNull("Key container is null", key);
+ Assert.assertNotNull("Key is null", key.getFirst());
+ Assert.assertNotNull("Provider is null", key.getFirst());
+
+ }
+
+ @Test
+ @DirtiesContext
public void hsmFacadeKeyStoreSuccessASitTestFacade() throws EaafException, KeyStoreException {
configureHsmFacade();
diff --git a/eaaf_core_utils/src/test/java/at/gv/egiz/eaaf/core/test/credentials/SymmetricKeyConfigurationTest.java b/eaaf_core_utils/src/test/java/at/gv/egiz/eaaf/core/test/credentials/SymmetricKeyConfigurationTest.java
new file mode 100644
index 00000000..eb4eb212
--- /dev/null
+++ b/eaaf_core_utils/src/test/java/at/gv/egiz/eaaf/core/test/credentials/SymmetricKeyConfigurationTest.java
@@ -0,0 +1,162 @@
+package at.gv.egiz.eaaf.core.test.credentials;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.commons.lang3.RandomStringUtils;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.BlockJUnit4ClassRunner;
+
+import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException;
+import at.gv.egiz.eaaf.core.impl.credential.SymmetricKeyConfiguration;
+import at.gv.egiz.eaaf.core.impl.credential.SymmetricKeyConfiguration.SymmetricKeyType;
+
+@RunWith(BlockJUnit4ClassRunner.class)
+public class SymmetricKeyConfigurationTest {
+
+ private Map<String, String> config;
+
+ @Before
+ public void testSetup() {
+ config = new HashMap<>();
+
+ }
+
+ @Test
+ public void emptyConfigMap() {
+ try {
+ SymmetricKeyConfiguration.buildFromConfigurationMap(config, "jUnitTest");
+ Assert.fail("Wrong config not detected");
+
+ } catch (final EaafConfigurationException e) {
+ Assert.assertEquals("wrong errorCode", "internal.keystore.04", e.getErrorId());
+ }
+ }
+
+ @Test
+ public void emptyKeyType() {
+ try {
+ config.put("key.type", "");
+
+ SymmetricKeyConfiguration.buildFromConfigurationMap(config, "jUnitTest");
+ Assert.fail("Wrong config not detected");
+
+ } catch (final EaafConfigurationException e) {
+ Assert.assertEquals("wrong errorCode", "internal.keystore.04", e.getErrorId());
+ }
+ }
+
+ @Test
+ public void unknownKeyType() {
+ try {
+ config.put("key.type", "test");
+
+ SymmetricKeyConfiguration.buildFromConfigurationMap(config, "jUnitTest");
+ Assert.fail("Wrong config not detected");
+
+ } catch (final EaafConfigurationException e) {
+ Assert.assertEquals("wrong errorCode", "internal.keystore.01", e.getErrorId());
+ }
+ }
+
+ @Test
+ public void hsmFacadeKeyTypeMissingName() {
+ try {
+ config.put("key.type", "hsmfacade");
+
+ SymmetricKeyConfiguration.buildFromConfigurationMap(config, "jUnitTest");
+ Assert.fail("Wrong config not detected");
+
+ } catch (final EaafConfigurationException e) {
+ Assert.assertEquals("wrong errorCode", "internal.keystore.04", e.getErrorId());
+ }
+ }
+
+ @Test
+ public void hsmFacadeKeyTypeMissingAlias() {
+ try {
+ final String keyStoreName = RandomStringUtils.randomAlphabetic(5);
+ config.put("key.type", "hsmfacade");
+ config.put("keystore.name", keyStoreName);
+
+ SymmetricKeyConfiguration.buildFromConfigurationMap(config, "jUnitTest");
+ Assert.fail("Wrong config not detected");
+
+ } catch (final EaafConfigurationException e) {
+ Assert.assertEquals("wrong errorCode", "internal.keystore.04", e.getErrorId());
+ }
+ }
+
+ @Test
+ public void hsmFacadeKeyTypeSucces() throws EaafConfigurationException {
+ final String keyStoreName = RandomStringUtils.randomAlphabetic(5);
+ final String keyAlias = RandomStringUtils.randomAlphabetic(5);
+ config.put("key.type", "hsmfacade");
+ config.put("keystore.name", keyStoreName);
+ config.put("key.alias", keyAlias);
+
+ final SymmetricKeyConfiguration keyStoreConfig = SymmetricKeyConfiguration.buildFromConfigurationMap(config,
+ "jUnitTest");
+
+ Assert.assertNotNull("KeyStore config object", keyStoreConfig);
+ Assert.assertEquals("Wrong Type", SymmetricKeyType.HSMFACADE, keyStoreConfig.getKeyType());
+ Assert.assertEquals("Wrong KeyStoreName", keyStoreName, keyStoreConfig.getKeyStoreName());
+ Assert.assertEquals("Wrong KeyStoreName", keyAlias, keyStoreConfig.getKeyAlias());
+
+
+ keyStoreConfig.validate();
+
+ }
+
+ @Test
+ public void passphraseKeyTypeMissingPassphrase() {
+ try {
+ config.put("key.type", "passphrase");
+
+ SymmetricKeyConfiguration.buildFromConfigurationMap(config, "jUnitTest");
+ Assert.fail("Wrong config not detected");
+
+ } catch (final EaafConfigurationException e) {
+ Assert.assertEquals("wrong errorCode", "internal.keystore.04", e.getErrorId());
+ }
+ }
+
+ @Test
+ public void passphraseKeyTypeMissingSalt() {
+ try {
+ final String passphrase = RandomStringUtils.randomAlphabetic(5);
+ config.put("key.type", "passphrase");
+ config.put("key.passphrase", passphrase);
+
+ SymmetricKeyConfiguration.buildFromConfigurationMap(config, "jUnitTest");
+ Assert.fail("Wrong config not detected");
+
+ } catch (final EaafConfigurationException e) {
+ Assert.assertEquals("wrong errorCode", "internal.keystore.04", e.getErrorId());
+ }
+ }
+
+ @Test
+ public void passphraseKeyTypeSucces() throws EaafConfigurationException {
+ final String passphrase = RandomStringUtils.randomAlphabetic(5);
+ final String salt = RandomStringUtils.randomAlphabetic(5);
+ config.put("key.type", "passphrase");
+ config.put("key.passphrase", passphrase);
+ config.put("key.salt", salt);
+
+ final SymmetricKeyConfiguration keyStoreConfig = SymmetricKeyConfiguration.buildFromConfigurationMap(config,
+ "jUnitTest");
+
+ Assert.assertNotNull("KeyStore config object", keyStoreConfig);
+ Assert.assertEquals("Wrong Type", SymmetricKeyType.PASSPHRASE, keyStoreConfig.getKeyType());
+ Assert.assertEquals("Wrong KeyStoreName", passphrase, keyStoreConfig.getSoftKeyPassphrase());
+ Assert.assertEquals("Wrong KeyStoreName", salt, keyStoreConfig.getSoftKeySalt());
+
+ keyStoreConfig.validate();
+
+ }
+}
+