diff options
Diffstat (limited to 'eaaf_modules/eaaf_module_auth_sl20')
2 files changed, 161 insertions, 150 deletions
| diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/Constants.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/Constants.java index f607f8cb..11fd41fb 100644 --- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/Constants.java +++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/Constants.java @@ -7,17 +7,37 @@ public class Constants {    public static final String CONFIG_PROP_VDA_AUTHBLOCK_TRANSFORMATION_ID = CONFIG_PROP_PREFIX        + ".vda.authblock.transformation.id"; -  public static final String CONFIG_PROP_SECURITY_KEYSTORE_PATH = CONFIG_PROP_PREFIX + ".security.keystore.path"; -  public static final String CONFIG_PROP_SECURITY_KEYSTORE_PASSWORD = CONFIG_PROP_PREFIX -      + ".security.keystore.password"; -  public static final String CONFIG_PROP_SECURITY_KEYSTORE_KEY_SIGN_ALIAS = CONFIG_PROP_PREFIX + ".security.sign.alias"; -  public static final String CONFIG_PROP_SECURITY_KEYSTORE_KEY_SIGN_PASSWORD = CONFIG_PROP_PREFIX -      + ".security.sign.password"; -  public static final String CONFIG_PROP_SECURITY_KEYSTORE_KEY_ENCRYPTION_ALIAS = CONFIG_PROP_PREFIX -      + ".security.encryption.alias"; -  public static final String CONFIG_PROP_SECURITY_KEYSTORE_KEY_ENCRYPTION_PASSWORD = CONFIG_PROP_PREFIX -      + ".security.encryption.password"; +   +  //KeyStore configuration +  public static final String CONFIG_PROP_SECURITY_KEYSTORE_TYPE =  +      CONFIG_PROP_PREFIX + ".security.keystore.type"; +  public static final String CONFIG_PROP_SECURITY_KEYSTORE_NAME =  +      CONFIG_PROP_PREFIX + ".security.keystore.name"; +  public static final String CONFIG_PROP_SECURITY_KEYSTORE_PATH =  +      CONFIG_PROP_PREFIX + ".security.keystore.path"; +  public static final String CONFIG_PROP_SECURITY_KEYSTORE_PASSWORD =  +      CONFIG_PROP_PREFIX + ".security.keystore.password"; +   +  public static final String CONFIG_PROP_SECURITY_KEYSTORE_KEY_SIGN_ALIAS =  +      CONFIG_PROP_PREFIX + ".security.sign.alias"; +  public static final String CONFIG_PROP_SECURITY_KEYSTORE_KEY_SIGN_PASSWORD =  +      CONFIG_PROP_PREFIX + ".security.sign.password"; +  public static final String CONFIG_PROP_SECURITY_KEYSTORE_KEY_ENCRYPTION_ALIAS =  +      CONFIG_PROP_PREFIX + ".security.encryption.alias"; +  public static final String CONFIG_PROP_SECURITY_KEYSTORE_KEY_ENCRYPTION_PASSWORD =  +      CONFIG_PROP_PREFIX + ".security.encryption.password"; +  //TrustStore configuration +  public static final String CONFIG_PROP_SECURITY_TRUSTSTORE_TYPE =  +      CONFIG_PROP_PREFIX + ".security.truststore.type"; +  public static final String CONFIG_PROP_SECURITY_TRUSTSTORE_NAME =  +      CONFIG_PROP_PREFIX + ".security.truststore.name"; +  public static final String CONFIG_PROP_SECURITY_TRUSTSTORE_PATH =  +      CONFIG_PROP_PREFIX + ".security.truststore.path"; +  public static final String CONFIG_PROP_SECURITY_TRUSTSTORE_PASSWORD =  +      CONFIG_PROP_PREFIX + ".security.truststore.password"; +   +      public static final String CONFIG_PROP_VDA_ENDPOINT_QUALeID_DEFAULT_ELEMENT = "default";    public static final String CONFIG_PROP_VDA_ENDPOINT_QUALeID_DEFAULT = CONFIG_PROP_VDA_ENDPOINT_QUALeID        + CONFIG_PROP_VDA_ENDPOINT_QUALeID_DEFAULT_ELEMENT; 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;    }  } | 
