Skip to content

Commit

Permalink
Improved AS4 crypto factory handling
Browse files Browse the repository at this point in the history
  • Loading branch information
phax committed Oct 22, 2024
1 parent 469f30f commit 47d4e3f
Show file tree
Hide file tree
Showing 23 changed files with 379 additions and 141 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,12 @@
import com.helger.phase4.client.AS4ClientErrorMessage;
import com.helger.phase4.client.AS4ClientReceiptMessage;
import com.helger.phase4.client.AS4ClientSentMessage;
import com.helger.phase4.crypto.AS4CryptoFactoryProperties;
import com.helger.phase4.crypto.AS4CryptoProperties;
import com.helger.phase4.crypto.AS4CryptoFactoryInMemoryKeyStore;
import com.helger.phase4.crypto.AS4KeyStoreDescriptor;
import com.helger.phase4.crypto.AS4TrustStoreDescriptor;
import com.helger.phase4.crypto.ECryptoAlgorithmC14N;
import com.helger.phase4.crypto.ECryptoKeyEncryptionAlgorithm;
import com.helger.phase4.crypto.IAS4CryptoFactory;
import com.helger.phase4.dump.AS4DumpManager;
import com.helger.phase4.dump.AS4IncomingDumperFileBased;
import com.helger.phase4.dump.AS4OutgoingDumperFileBased;
Expand Down Expand Up @@ -76,20 +78,23 @@ public class MainPhase4EuCtpSenderExample
private static final Logger LOGGER = LoggerFactory.getLogger (MainPhase4EuCtpSenderExample.class);

@Nonnull
private static AS4CryptoProperties _buildAs4CryptoProperties ()
private static IAS4CryptoFactory _buildAs4CryptoFactory ()
{
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
ret.setTrustStorePath (System.getenv ("AS4_SIGNING_TRUST_KEYSTORE_PATH"));
ret.setTrustStoreType (EKeyStoreType.PKCS12);
ret.setTrustStorePassword (System.getenv ("AS4_SIGNING_TRUST_KEYSTORE_PASSWORD"));
return ret;
return new AS4CryptoFactoryInMemoryKeyStore (AS4KeyStoreDescriptor.builder ()
.type (EKeyStoreType.PKCS12)
.path (System.getenv ("AS4_SIGNING_KEYSTORE_PATH"))
.password (System.getenv ("AS4_SIGNING_KEYSTORE_PASSWORD"))
.keyAlias (System.getenv ("AS4_SIGNING_KEY_ALIAS"))
.keyPassword (System.getenv ("AS4_SIGNING_KEY_PASSWORD"))
.build (),
// must include the Taxud CA
// and intermediate
// certificates
AS4TrustStoreDescriptor.builder ()
.type (EKeyStoreType.PKCS12)
.path (System.getenv ("AS4_SIGNING_TRUST_KEYSTORE_PATH"))
.password (System.getenv ("AS4_SIGNING_TRUST_KEYSTORE_PASSWORD"))
.build ());
}

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

final AS4CryptoProperties as4CryptoProperties = _buildAs4CryptoProperties ();
final AS4CryptoFactoryProperties cryptoFactoryProperties = new AS4CryptoFactoryProperties (as4CryptoProperties);
final IAS4CryptoFactory cryptoFactoryProperties = _buildAs4CryptoFactory ();

// configured on the STI
final String fromPartyID = System.getenv ("AS4_FROM_PARTY_ID");
Expand Down Expand Up @@ -142,7 +146,7 @@ public static void main (final String [] args)

private static void _sendPullRequest (final Phase4EuCtpHttpClientSettings aHttpClientSettings,
final String fromPartyID,
final AS4CryptoFactoryProperties cryptoFactoryProperties) throws Phase4Exception
final IAS4CryptoFactory cryptoFactory) throws Phase4Exception
{
final Wrapper <Ebms3UserMessage> aUserMessageHolder = new Wrapper <> ();
final Wrapper <Ebms3SignalMessage> aSignalMessageHolder = new Wrapper <> ();
Expand Down Expand Up @@ -187,7 +191,7 @@ private static void _sendPullRequest (final Phase4EuCtpHttpClientSettings aHttpC
aSignalMessageHolder.set (aEbmsSignalMsg);
aSoapDocHolder.set (aIncomingState.getEffectiveDecryptedSoapDocument ());
})
.cryptoFactory (cryptoFactoryProperties);
.cryptoFactory (cryptoFactory);
final ESuccess eSuccess = prBuilder.sendMessage ();
//
LOGGER.info ("euctp pull request result: " + eSuccess);
Expand Down Expand Up @@ -305,7 +309,7 @@ private static void _sendReceipt (final Wrapper <Ebms3UserMessage> aUserMessageH
private static void _sendConnectionTest (final Phase4EuCtpHttpClientSettings aHttpClientSettings,
final String fromPartyID,
final Wrapper <Ebms3SignalMessage> aSignalMsgHolder,
final AS4CryptoFactoryProperties cryptoFactoryProperties)
final IAS4CryptoFactory cryptoFactory)
{
EAS4UserMessageSendResult eResult;
eResult = Phase4EuCtpSender.builderUserMessage ()
Expand All @@ -320,7 +324,7 @@ private static void _sendConnectionTest (final Phase4EuCtpHttpClientSettings aHt
.service ("http://docs.oasis-open.org/ebxml-msg/ebms/v3.0/ns/core/200704/service")
.action (EuCtpPMode.ACTION_TEST)
.signalMsgConsumer ( (aSignalMsg, aMMD, aState) -> aSignalMsgHolder.set (aSignalMsg))
.cryptoFactory (cryptoFactoryProperties)
.cryptoFactory (cryptoFactory)
// .payload(new
// AS4OutgoingAttachment.Builder().data(aPayloadBytes).mimeTypeXML())
.sendMessageAndCheckForReceipt ();
Expand All @@ -330,7 +334,7 @@ private static void _sendConnectionTest (final Phase4EuCtpHttpClientSettings aHt

private static void _sendENSFilling (final Phase4EuCtpHttpClientSettings aHttpClientSettings,
final String fromPartyID,
final AS4CryptoFactoryProperties cryptoFactoryProperties)
final IAS4CryptoFactory cryptoFactory)
{
// Read XML payload to send
final byte [] aPayloadBytes = StreamHelper.getAllBytes (new ClassPathResource ("/external/examples/base-example.xml"));
Expand All @@ -349,7 +353,7 @@ private static void _sendENSFilling (final Phase4EuCtpHttpClientSettings aHttpCl
.service (EuCtpPMode.DEFAULT_SERVICE_TYPE, EEuCtpService.TRADER_TO_CUSTOMS)
.action (EEuCtpAction.IE3F26)
.signalMsgConsumer ( (aSignalMsg, aMMD, aState) -> aSignalMsgHolder.set (aSignalMsg))
.cryptoFactory (cryptoFactoryProperties)
.cryptoFactory (cryptoFactory)
.conversationID (UUID.randomUUID ().toString ())
.payload (new AS4OutgoingAttachment.Builder ().compressionGZIP ()
.data (aPayloadBytes)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ public static AS4CryptoFactoryConfiguration getDefaultInstance ()
return DEFAULT_INSTANCE;
}

private final IAS4KeyStoreDescriptor m_aKeyStoreDesc;
private final IAS4TrustStoreDescriptor m_aTrustStorDesc;

/**
* This constructor takes the configuration object and uses the default prefix
* for backwards compatibility. This is kind of the default constructor.
Expand All @@ -81,7 +84,7 @@ public AS4CryptoFactoryConfiguration (@Nonnull final IConfigWithFallback aConfig
this (aConfig, DEFAULT_CONFIG_PREFIX);
}

@Nullable
@Nonnull
private static IAS4KeyStoreDescriptor _loadKeyStore (@Nonnull final IConfigWithFallback aConfig,
@Nonnull @Nonempty final String sConfigPrefix)
{
Expand Down Expand Up @@ -112,16 +115,20 @@ private static IAS4KeyStoreDescriptor _loadKeyStore (@Nonnull final IConfigWithF
private static IAS4TrustStoreDescriptor _loadTrustStore (@Nonnull final IConfigWithFallback aConfig,
@Nonnull @Nonempty final String sConfigPrefix)
{
// Load the trust store - may be null
final IAS4TrustStoreDescriptor aDescriptor = AS4TrustStoreDescriptor.createFromConfig (aConfig,
sConfigPrefix,
null);
final LoadedKeyStore aLTS = aDescriptor.loadTrustStore ();
if (aLTS.getKeyStore () == null)
if (aDescriptor != null)
{
LOGGER.error ("Failed to load the trust store from the properties starting with '" +
sConfigPrefix +
"': " +
aLTS.getErrorText (Locale.ROOT));
final LoadedKeyStore aLTS = aDescriptor.loadTrustStore ();
if (aLTS.getKeyStore () == null)
{
LOGGER.error ("Failed to load the trust store from the properties starting with '" +
sConfigPrefix +
"': " +
aLTS.getErrorText (Locale.ROOT));
}
}
return aDescriptor;
}
Expand All @@ -139,6 +146,33 @@ private static IAS4TrustStoreDescriptor _loadTrustStore (@Nonnull final IConfigW
public AS4CryptoFactoryConfiguration (@Nonnull final IConfigWithFallback aConfig,
@Nonnull @Nonempty final String sConfigPrefix)
{
super (_loadKeyStore (aConfig, sConfigPrefix), _loadTrustStore (aConfig, sConfigPrefix));
this (_loadKeyStore (aConfig, sConfigPrefix), _loadTrustStore (aConfig, sConfigPrefix));
}

private AS4CryptoFactoryConfiguration (@Nonnull final IAS4KeyStoreDescriptor aKeyStoreDesc,
@Nonnull final IAS4TrustStoreDescriptor aTrustStorDesc)
{
super (aKeyStoreDesc, aTrustStorDesc);
m_aKeyStoreDesc = aKeyStoreDesc;
m_aTrustStorDesc = aTrustStorDesc;
}

/**
* @return The descriptor used to load the key store. Never <code>null</code>.
*/
@Nonnull
public IAS4KeyStoreDescriptor getKeyStoreDescriptor ()
{
return m_aKeyStoreDesc;
}

/**
* @return The descriptor used to load the trust store. Never
* <code>null</code>.
*/
@Nonnull
public IAS4TrustStoreDescriptor getTrustStoreDescriptor ()
{
return m_aTrustStorDesc;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,15 +54,17 @@ public class AS4CryptoFactoryInMemoryKeyStore extends AbstractAS4CryptoFactory
* @param aKeyStoreDesc
* The key store descriptor. May not be <code>null</code>.
* @param aTrustStoreDesc
* The trust store descriptor. May not be <code>null</code>.
* The trust store descriptor. May be <code>null</code> in which case
* the global JRE CA certs list will be used.
* @since 3.0.0
*/
protected AS4CryptoFactoryInMemoryKeyStore (@Nonnull final IAS4KeyStoreDescriptor aKeyStoreDesc,
@Nonnull final IAS4TrustStoreDescriptor aTrustStoreDesc)
public AS4CryptoFactoryInMemoryKeyStore (@Nonnull final IAS4KeyStoreDescriptor aKeyStoreDesc,
@Nonnull final IAS4TrustStoreDescriptor aTrustStoreDesc)
{
this (aKeyStoreDesc.loadKeyStore ().getKeyStore (),
aKeyStoreDesc.getKeyAlias (),
aKeyStoreDesc.getKeyPassword (),
aTrustStoreDesc.loadTrustStore ().getKeyStore ());
aTrustStoreDesc == null ? null : aTrustStoreDesc.loadTrustStore ().getKeyStore ());
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import com.helger.commons.ValueEnforcer;
import com.helger.commons.annotation.Nonempty;
import com.helger.commons.annotation.ReturnsMutableObject;
import com.helger.commons.builder.IBuilder;
import com.helger.commons.string.StringHelper;
import com.helger.commons.string.ToStringGenerator;
import com.helger.config.fallback.IConfigWithFallback;
Expand Down Expand Up @@ -177,4 +178,103 @@ public static AS4KeyStoreDescriptor createFromConfig (@Nonnull final IConfigWith

return new AS4KeyStoreDescriptor (aType, sPath, aPassword, aProvider, sKeyAlias, aKeyPassword);
}

/**
* @return A new builder for {@link AS4KeyStoreDescriptor} objects. Never
* <code>null</code>.
*/
@Nonnull
public static AS4KeyStoreDescriptorBuilder builder ()
{
return new AS4KeyStoreDescriptorBuilder ();
}

/**
* Builder class for class {@link AS4KeyStoreDescriptor}.
*
* @author Philip Helger
*/
public static class AS4KeyStoreDescriptorBuilder implements IBuilder <AS4KeyStoreDescriptor>
{
private IKeyStoreType m_aType;
private String m_sPath;
private char [] m_aPassword;
private Provider m_aProvider;
private String m_sKeyAlias;
private char [] m_aKeyPassword;

public AS4KeyStoreDescriptorBuilder ()
{}

@Nonnull
public AS4KeyStoreDescriptorBuilder type (@Nullable final IKeyStoreType a)
{
m_aType = a;
return this;
}

@Nonnull
public AS4KeyStoreDescriptorBuilder path (@Nullable final String s)
{
m_sPath = s;
return this;
}

@Nonnull
public AS4KeyStoreDescriptorBuilder password (@Nullable final String s)
{
return password (s == null ? null : s.toCharArray ());
}

@Nonnull
public AS4KeyStoreDescriptorBuilder password (@Nullable final char [] a)
{
m_aPassword = a;
return this;
}

@Nonnull
public AS4KeyStoreDescriptorBuilder provider (@Nullable final Provider a)
{
m_aProvider = a;
return this;
}

@Nonnull
public AS4KeyStoreDescriptorBuilder keyAlias (@Nullable final String s)
{
m_sKeyAlias = s;
return this;
}

@Nonnull
public AS4KeyStoreDescriptorBuilder keyPassword (@Nullable final String s)
{
return keyPassword (s == null ? null : s.toCharArray ());
}

@Nonnull
public AS4KeyStoreDescriptorBuilder keyPassword (@Nullable final char [] a)
{
m_aKeyPassword = a;
return this;
}

@Nonnull
public AS4KeyStoreDescriptor build ()
{
if (m_aType == null)
throw new IllegalStateException ("Type is missing");
if (StringHelper.hasNoText (m_sPath))
throw new IllegalStateException ("Path is empty");
if (m_aPassword == null)
throw new IllegalStateException ("Password is missing");
// Provider may be null
if (StringHelper.hasNoText (m_sKeyAlias))
throw new IllegalStateException ("KeyAlias is empty");
if (m_aKeyPassword == null)
throw new IllegalStateException ("KeyPassword is missing");
return new AS4KeyStoreDescriptor (m_aType, m_sPath, m_aPassword, m_aProvider, m_sKeyAlias, m_aKeyPassword);
}
}
}
Loading

0 comments on commit 47d4e3f

Please sign in to comment.