Skip to content

Commit

Permalink
Using char[] for passwords where possible
Browse files Browse the repository at this point in the history
  • Loading branch information
phax committed Oct 22, 2024
1 parent e3719be commit 469f30f
Show file tree
Hide file tree
Showing 23 changed files with 678 additions and 250 deletions.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -78,18 +78,18 @@ public class MainPhase4EuCtpSenderExample
@Nonnull
private static AS4CryptoProperties _buildAs4CryptoProperties ()
{
final AS4CryptoProperties as4SigningProperties = new AS4CryptoProperties ();
as4SigningProperties.setKeyStorePath (System.getenv ("AS4_SIGNING_KEYSTORE_PATH"));
as4SigningProperties.setKeyStoreType (EKeyStoreType.PKCS12);
as4SigningProperties.setKeyStorePassword (System.getenv ("AS4_SIGNING_KEYSTORE_PASSWORD"));
as4SigningProperties.setKeyAlias (System.getenv ("AS4_SIGNING_KEY_ALIAS"));
as4SigningProperties.setKeyPassword (System.getenv ("AS4_SIGNING_KEY_PASSWORD"));
final AS4CryptoProperties ret = new AS4CryptoProperties ();
ret.setKeyStorePath (System.getenv ("AS4_SIGNING_KEYSTORE_PATH"));
ret.setKeyStoreType (EKeyStoreType.PKCS12);
ret.setKeyStorePassword (System.getenv ("AS4_SIGNING_KEYSTORE_PASSWORD"));
ret.setKeyAlias (System.getenv ("AS4_SIGNING_KEY_ALIAS"));
ret.setKeyPassword (System.getenv ("AS4_SIGNING_KEY_PASSWORD"));

// must include the Taxud CA and intermediate certificates
as4SigningProperties.setTrustStorePath (System.getenv ("AS4_SIGNING_TRUST_KEYSTORE_PATH"));
as4SigningProperties.setTrustStoreType (EKeyStoreType.PKCS12);
as4SigningProperties.setTrustStorePassword (System.getenv ("AS4_SIGNING_TRUST_KEYSTORE_PASSWORD"));
return as4SigningProperties;
ret.setTrustStorePath (System.getenv ("AS4_SIGNING_TRUST_KEYSTORE_PATH"));
ret.setTrustStoreType (EKeyStoreType.PKCS12);
ret.setTrustStorePassword (System.getenv ("AS4_SIGNING_TRUST_KEYSTORE_PASSWORD"));
return ret;
}

public static void main (final String [] args)
Expand All @@ -113,8 +113,8 @@ public static void main (final String [] args)
final Phase4EuCtpHttpClientSettings aHttpClientSettings = new Phase4EuCtpHttpClientSettings (aSslKeyStore,
aKeyStorePassword);

final AS4CryptoProperties as4SigningProperties = _buildAs4CryptoProperties ();
final AS4CryptoFactoryProperties cryptoFactoryProperties = new AS4CryptoFactoryProperties (as4SigningProperties);
final AS4CryptoProperties as4CryptoProperties = _buildAs4CryptoProperties ();
final AS4CryptoFactoryProperties cryptoFactoryProperties = new AS4CryptoFactoryProperties (as4CryptoProperties);

// configured on the STI
final String fromPartyID = System.getenv ("AS4_FROM_PARTY_ID");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,10 @@
import com.helger.commons.io.resource.IReadableResource;
import com.helger.commons.io.resourceprovider.ReadableResourceProviderChain;
import com.helger.commons.string.StringParser;
import com.helger.config.Config;
import com.helger.config.ConfigFactory;
import com.helger.config.IConfig;
import com.helger.config.fallback.ConfigWithFallback;
import com.helger.config.fallback.IConfigWithFallback;
import com.helger.config.source.EConfigSourceType;
import com.helger.config.source.MultiConfigurationValueProvider;
import com.helger.config.source.res.ConfigurationSourceProperties;
Expand Down Expand Up @@ -109,9 +110,9 @@ public static MultiConfigurationValueProvider createPhase4ValueProvider ()
}

private static final MultiConfigurationValueProvider VP = createPhase4ValueProvider ();
private static final IConfig DEFAULT_INSTANCE = Config.create (VP);
private static final IConfigWithFallback DEFAULT_INSTANCE = new ConfigWithFallback (VP);
private static final SimpleReadWriteLock RW_LOCK = new SimpleReadWriteLock ();
private static IConfig s_aConfig = DEFAULT_INSTANCE;
private static IConfigWithFallback s_aConfig = DEFAULT_INSTANCE;

private AS4Configuration ()
{}
Expand All @@ -120,7 +121,7 @@ private AS4Configuration ()
* @return The current global configuration. Never <code>null</code>.
*/
@Nonnull
public static IConfig getConfig ()
public static IConfigWithFallback getConfig ()
{
// Inline for performance
RW_LOCK.readLock ().lock ();
Expand All @@ -142,10 +143,10 @@ public static IConfig getConfig ()
* @return The old value of {@link IConfig}. Never <code>null</code>.
*/
@Nonnull
public static IConfig setConfig (@Nonnull final IConfig aNewConfig)
public static IConfigWithFallback setConfig (@Nonnull final IConfigWithFallback aNewConfig)
{
ValueEnforcer.notNull (aNewConfig, "NewConfig");
final IConfig ret;
final IConfigWithFallback ret;
RW_LOCK.writeLock ().lock ();
try
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,23 @@
*/
package com.helger.phase4.crypto;

import java.security.KeyStore;
import java.security.KeyStore.PrivateKeyEntry;
import java.util.Locale;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;

import org.apache.wss4j.common.crypto.Crypto;
import org.apache.wss4j.common.crypto.Merlin;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.helger.commons.ValueEnforcer;
import com.helger.commons.annotation.Nonempty;
import com.helger.commons.string.StringHelper;
import com.helger.config.IConfig;
import com.helger.config.fallback.IConfigWithFallback;
import com.helger.phase4.config.AS4Configuration;
import com.helger.security.keystore.EKeyStoreType;
import com.helger.security.keystore.KeyStoreHelper;
import com.helger.security.keystore.LoadedKey;
import com.helger.security.keystore.LoadedKeyStore;

/**
* phase4 crypto factory settings based on {@link IConfig}. It can do the same
Expand All @@ -51,11 +52,11 @@
*/
@SuppressWarnings ("javadoc")
@Immutable
public class AS4CryptoFactoryConfiguration extends AbstractAS4CryptoFactory
public class AS4CryptoFactoryConfiguration extends AS4CryptoFactoryInMemoryKeyStore
{
public static final EKeyStoreType DEFAULT_KEYSTORE_TYPE = EKeyStoreType.JKS;
public static final EKeyStoreType DEFAULT_TRUSTSTORE_TYPE = EKeyStoreType.JKS;
public static final String DEFAULT_CONFIG_PREFIX = "org.apache.wss4j.crypto.merlin.";

private static final Logger LOGGER = LoggerFactory.getLogger (AS4CryptoFactoryConfiguration.class);
private static final AS4CryptoFactoryConfiguration DEFAULT_INSTANCE = new AS4CryptoFactoryConfiguration (AS4Configuration.getConfig ());

/**
Expand All @@ -68,149 +69,76 @@ public static AS4CryptoFactoryConfiguration getDefaultInstance ()
return DEFAULT_INSTANCE;
}

private final EKeyStoreType m_eKeyStoreType;
private final String m_sKeyStorePath;
private final String m_sKeyStorePassword;

private final String m_sKeyAlias;
private final String m_sKeyPassword;

private final EKeyStoreType m_eTrustStoreType;
private final String m_sTrustStorePath;
private final String m_sTrustStorePassword;

// Lazy initialized
private Merlin m_aCrypto;
private KeyStore m_aKeyStore;
private KeyStore m_aTrustStore;

/**
* This constructor takes the configuration object and uses the default prefix
* for backwards compatibility. This is kind of the default constructor.
*
* @param aConfig
* The configuration object to be used. May not be <code>null</code>.
*/
public AS4CryptoFactoryConfiguration (@Nonnull final IConfig aConfig)
{
this (aConfig, "org.apache.wss4j.crypto.merlin.");
}

/**
* This constructor takes the configuration object and uses the provided
* configuration prefix. This is kind of the default constructor.
*
* @param aConfig
* The configuration object to be used. May not be <code>null</code>.
* @param sConfigPrefix
* The configuration prefix to be used. May neither be
* <code>null</code> nor empty and must end with a dot ('.').
*/
public AS4CryptoFactoryConfiguration (@Nonnull final IConfig aConfig, @Nonnull @Nonempty final String sConfigPrefix)
public AS4CryptoFactoryConfiguration (@Nonnull final IConfigWithFallback aConfig)
{
ValueEnforcer.notNull (aConfig, "Config");
ValueEnforcer.notEmpty (sConfigPrefix, "ConfigPrefix");
ValueEnforcer.isTrue ( () -> StringHelper.endsWith (sConfigPrefix, '.'), "ConfigPrefix must end with a dot");

// Key Store
m_eKeyStoreType = EKeyStoreType.getFromIDCaseInsensitiveOrDefault (aConfig.getAsString (sConfigPrefix +
"keystore.type"),
DEFAULT_KEYSTORE_TYPE);
m_sKeyStorePath = aConfig.getAsString (sConfigPrefix + "keystore.file");
m_sKeyStorePassword = aConfig.getAsString (sConfigPrefix + "keystore.password");

// Key Store Key
m_sKeyAlias = aConfig.getAsString (sConfigPrefix + "keystore.alias");
m_sKeyPassword = aConfig.getAsString (sConfigPrefix + "keystore.private.password");

// Trust Store
m_eTrustStoreType = EKeyStoreType.getFromIDCaseInsensitiveOrDefault (aConfig.getAsString (sConfigPrefix +
"truststore.type"),
DEFAULT_KEYSTORE_TYPE);
m_sTrustStorePath = aConfig.getAsString (sConfigPrefix + "truststore.file");
m_sTrustStorePassword = aConfig.getAsString (sConfigPrefix + "truststore.password");
this (aConfig, DEFAULT_CONFIG_PREFIX);
}

/**
* Helper method to create a WSS4J {@link Merlin} instance based on the
* configured keystore and truststore.
*
* @return A new {@link Merlin} object.
* @throws IllegalStateException
* if creation failed
*/
@Nonnull
public Merlin createMerlin ()
@Nullable
private static IAS4KeyStoreDescriptor _loadKeyStore (@Nonnull final IConfigWithFallback aConfig,
@Nonnull @Nonempty final String sConfigPrefix)
{
try
final IAS4KeyStoreDescriptor aDescriptor = AS4KeyStoreDescriptor.createFromConfig (aConfig, sConfigPrefix, null);
final LoadedKeyStore aLKS = aDescriptor.loadKeyStore ();
if (aLKS.getKeyStore () == null)
{
final Merlin ret = new Merlin ();
ret.setKeyStore (getKeyStore ());
ret.setTrustStore (getTrustStore ());
return ret;
LOGGER.error ("Failed to load the key store from the properties starting with '" +
sConfigPrefix +
"': " +
aLKS.getErrorText (Locale.ROOT));
}
catch (final RuntimeException ex)
{
throw new IllegalStateException ("Failed to create Merlin object", ex);
}
}

/**
* Lazily create a {@link Merlin} instance using the configured keystore and
* truststore.
*/
@Nonnull
public final Crypto getCrypto (@Nonnull final ECryptoMode eCryptoMode)
{
Merlin ret = m_aCrypto;
if (ret == null)
else
{
// Create only once and cache
ret = m_aCrypto = createMerlin ();
final LoadedKey <PrivateKeyEntry> aLK = aDescriptor.loadKey ();
if (aLK.getKeyEntry () == null)
{
LOGGER.error ("Failed to load the prvate key from the key store properties starting with '" +
sConfigPrefix +
"': " +
aLK.getErrorText (Locale.ROOT));
}
}
return ret;
return aDescriptor;
}

@Nullable
public final KeyStore getKeyStore ()
private static IAS4TrustStoreDescriptor _loadTrustStore (@Nonnull final IConfigWithFallback aConfig,
@Nonnull @Nonempty final String sConfigPrefix)
{
KeyStore ret = m_aKeyStore;
if (ret == null)
final IAS4TrustStoreDescriptor aDescriptor = AS4TrustStoreDescriptor.createFromConfig (aConfig,
sConfigPrefix,
null);
final LoadedKeyStore aLTS = aDescriptor.loadTrustStore ();
if (aLTS.getKeyStore () == null)
{
ret = m_aKeyStore = KeyStoreHelper.loadKeyStore (m_eKeyStoreType, m_sKeyStorePath, m_sKeyStorePassword)
.getKeyStore ();
LOGGER.error ("Failed to load the trust store from the properties starting with '" +
sConfigPrefix +
"': " +
aLTS.getErrorText (Locale.ROOT));
}
return ret;
}

@Nullable
public final String getKeyAlias ()
{
return m_sKeyAlias;
}

@Nullable
public String getKeyPasswordPerAlias (@Nullable final String sSearchKeyAlias)
{
final String sKeyAlias = m_sKeyAlias;

// Use case insensitive compare, depends on the keystore type
if (sKeyAlias != null && sSearchKeyAlias != null && sKeyAlias.equalsIgnoreCase (sSearchKeyAlias))
return m_sKeyPassword;

return null;
return aDescriptor;
}

@Nullable
public final KeyStore getTrustStore ()
/**
* This constructor takes the configuration object and uses the provided
* configuration prefix. This is kind of the default constructor.
*
* @param aConfig
* The configuration object to be used. May not be <code>null</code>.
* @param sConfigPrefix
* The configuration prefix to be used. May neither be
* <code>null</code> nor empty and must end with a dot ('.').
*/
public AS4CryptoFactoryConfiguration (@Nonnull final IConfigWithFallback aConfig,
@Nonnull @Nonempty final String sConfigPrefix)
{
KeyStore ret = m_aTrustStore;
if (ret == null)
{
// Load only once and cache then
ret = m_aTrustStore = KeyStoreHelper.loadKeyStore (m_eTrustStoreType, m_sTrustStorePath, m_sTrustStorePassword)
.getKeyStore ();
}
return ret;
super (_loadKeyStore (aConfig, sConfigPrefix), _loadTrustStore (aConfig, sConfigPrefix));
}
}
Loading

0 comments on commit 469f30f

Please sign in to comment.