From c25837b6683fe65c269cab676b7084c0e6e0794c Mon Sep 17 00:00:00 2001 From: Alex Kehayov Date: Tue, 11 Aug 2026 12:13:14 +0300 Subject: [PATCH] fix: remove the insecure default for crypto.keystorePassword Signed-off-by: Alex Kehayov --- .../hiero/base/crypto/config/CryptoConfig.java | 2 +- .../base/crypto/config/CryptoConfigTest.java | 18 ++++++++++++++++++ .../gossip/modular/PeerCommunicationTests.java | 1 + .../connectivity/ConnectivityTestBase.java | 13 +++++++++---- .../connectivity/SocketFactoryTest.java | 7 ++++++- platform-sdk/docs/consensus-layer/tunables.md | 6 +++--- 6 files changed, 38 insertions(+), 9 deletions(-) diff --git a/platform-sdk/base-crypto/src/main/java/org/hiero/base/crypto/config/CryptoConfig.java b/platform-sdk/base-crypto/src/main/java/org/hiero/base/crypto/config/CryptoConfig.java index 4fbae5fd4e28..e65bcd7ac7f0 100644 --- a/platform-sdk/base-crypto/src/main/java/org/hiero/base/crypto/config/CryptoConfig.java +++ b/platform-sdk/base-crypto/src/main/java/org/hiero/base/crypto/config/CryptoConfig.java @@ -14,4 +14,4 @@ */ @ConfigData("crypto") public record CryptoConfig( - @ConfigProperty(defaultValue = "password") String keystorePassword) {} + @ConfigProperty(defaultValue = "") String keystorePassword) {} diff --git a/platform-sdk/base-crypto/src/test/java/org/hiero/base/crypto/config/CryptoConfigTest.java b/platform-sdk/base-crypto/src/test/java/org/hiero/base/crypto/config/CryptoConfigTest.java index a48765698b98..cd79fd1ab891 100644 --- a/platform-sdk/base-crypto/src/test/java/org/hiero/base/crypto/config/CryptoConfigTest.java +++ b/platform-sdk/base-crypto/src/test/java/org/hiero/base/crypto/config/CryptoConfigTest.java @@ -1,6 +1,7 @@ // SPDX-License-Identifier: Apache-2.0 package org.hiero.base.crypto.config; +import com.swirlds.config.api.Configuration; import com.swirlds.config.api.ConfigurationBuilder; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -15,4 +16,21 @@ public void testDefaultValuesValid() { // then Assertions.assertDoesNotThrow(() -> builder.build(), "All default values of CryptoConfig should be valid"); } + + @Test + public void testNoUsableDefaultKeystorePassword() { + // given + final Configuration configuration = ConfigurationBuilder.create() + .withConfigDataType(CryptoConfig.class) + .build(); + + // when + final CryptoConfig cryptoConfig = configuration.getConfigData(CryptoConfig.class); + + // then + Assertions.assertTrue( + cryptoConfig.keystorePassword() == null + || cryptoConfig.keystorePassword().isBlank(), + "CryptoConfig must not provide a usable default keystore password"); + } } diff --git a/platform-sdk/consensus-gossip-impl/src/test/java/org/hiero/consensus/gossip/impl/gossip/modular/PeerCommunicationTests.java b/platform-sdk/consensus-gossip-impl/src/test/java/org/hiero/consensus/gossip/impl/gossip/modular/PeerCommunicationTests.java index af6f133eac2b..d9626829ff9e 100644 --- a/platform-sdk/consensus-gossip-impl/src/test/java/org/hiero/consensus/gossip/impl/gossip/modular/PeerCommunicationTests.java +++ b/platform-sdk/consensus-gossip-impl/src/test/java/org/hiero/consensus/gossip/impl/gossip/modular/PeerCommunicationTests.java @@ -58,6 +58,7 @@ void testSetup() { configurationBuilder.withValue("socket.timeoutServerAcceptConnect", "100"); configurationBuilder.withValue("socket.timeoutSyncClientSocket", "100"); configurationBuilder.withValue("socket.timeoutSyncClientConnect", "100"); + configurationBuilder.withValue("crypto.keystorePassword", "password"); this.configuration = configurationBuilder.build(); diff --git a/platform-sdk/consensus-gossip-impl/src/test/java/org/hiero/consensus/gossip/impl/network/connectivity/ConnectivityTestBase.java b/platform-sdk/consensus-gossip-impl/src/test/java/org/hiero/consensus/gossip/impl/network/connectivity/ConnectivityTestBase.java index 48c0f2adc2c7..d46b5c5af74f 100644 --- a/platform-sdk/consensus-gossip-impl/src/test/java/org/hiero/consensus/gossip/impl/network/connectivity/ConnectivityTestBase.java +++ b/platform-sdk/consensus-gossip-impl/src/test/java/org/hiero/consensus/gossip/impl/network/connectivity/ConnectivityTestBase.java @@ -12,6 +12,7 @@ import java.util.Objects; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; +import org.hiero.base.crypto.config.CryptoConfig_; import org.hiero.consensus.gossip.config.SocketConfig; import org.hiero.consensus.gossip.config.SocketConfig_; @@ -25,10 +26,14 @@ class ConnectivityTestBase { protected static final byte[] TEST_DATA = new byte[] {1, 2, 3}; static { - TLS_NO_IP_TOS_CONFIG = - new TestConfigBuilder().withValue(SocketConfig_.IP_TOS, "-1").getOrCreateConfig(); - TLS_IP_TOS_CONFIG = - new TestConfigBuilder().withValue(SocketConfig_.IP_TOS, "100").getOrCreateConfig(); + TLS_NO_IP_TOS_CONFIG = new TestConfigBuilder() + .withValue(SocketConfig_.IP_TOS, "-1") + .withValue(CryptoConfig_.KEYSTORE_PASSWORD, "password") + .getOrCreateConfig(); + TLS_IP_TOS_CONFIG = new TestConfigBuilder() + .withValue(SocketConfig_.IP_TOS, "100") + .withValue(CryptoConfig_.KEYSTORE_PASSWORD, "password") + .getOrCreateConfig(); final Configuration configurationNoIpTos = new TestConfigBuilder().withValue(SocketConfig_.IP_TOS, "-1").getOrCreateConfig(); diff --git a/platform-sdk/consensus-gossip-impl/src/test/java/org/hiero/consensus/gossip/impl/network/connectivity/SocketFactoryTest.java b/platform-sdk/consensus-gossip-impl/src/test/java/org/hiero/consensus/gossip/impl/network/connectivity/SocketFactoryTest.java index c6fd09d3584b..ef2fff70f1b9 100644 --- a/platform-sdk/consensus-gossip-impl/src/test/java/org/hiero/consensus/gossip/impl/network/connectivity/SocketFactoryTest.java +++ b/platform-sdk/consensus-gossip-impl/src/test/java/org/hiero/consensus/gossip/impl/network/connectivity/SocketFactoryTest.java @@ -21,6 +21,7 @@ import java.util.Map; import java.util.Random; import java.util.concurrent.atomic.AtomicReference; +import org.hiero.base.crypto.config.CryptoConfig_; import org.hiero.consensus.gossip.config.GossipConfig; import org.hiero.consensus.gossip.config.GossipConfig_; import org.hiero.consensus.gossip.config.NetworkEndpoint; @@ -159,6 +160,7 @@ void bindInterfaceTest( .withValues( GossipConfig_.INTERFACE_BINDINGS, List.of("{ \"nodeId\": 0, \"hostname\": \"localhost\", \"port\": 1234 }")) + .withValue(CryptoConfig_.KEYSTORE_PASSWORD, "password") .getOrCreateConfig(); testInterfaceBinding(node0, roster, keysAndCerts, config, port); } @@ -181,7 +183,9 @@ void bindInterfaceTestWithDefaultConfig( assertTrue(roster.rosterEntries().size() > 1, "Address book must contain at least 2 nodes"); final NodeId node0 = NodeId.of(roster.rosterEntries().getFirst().nodeId()); - final Configuration config = new TestConfigBuilder().getOrCreateConfig(); + final Configuration config = new TestConfigBuilder() + .withValue(CryptoConfig_.KEYSTORE_PASSWORD, "password") + .getOrCreateConfig(); testInterfaceBinding(node0, roster, keysAndCerts, config, port); } @@ -207,6 +211,7 @@ void bindInterfaceTestWithFailingClaimingIp( .withValues( GossipConfig_.INTERFACE_BINDINGS, List.of("{ \"nodeId\": 0, \"hostname\": \"10.123.123.123\", \"port\": 1234 }")) + .withValue(CryptoConfig_.KEYSTORE_PASSWORD, "password") .getOrCreateConfig(); assertThrows(BindException.class, () -> testInterfaceBinding(node0, roster, keysAndCerts, config, port)); diff --git a/platform-sdk/docs/consensus-layer/tunables.md b/platform-sdk/docs/consensus-layer/tunables.md index aa7a1920d3f6..15b99ea234f3 100644 --- a/platform-sdk/docs/consensus-layer/tunables.md +++ b/platform-sdk/docs/consensus-layer/tunables.md @@ -137,9 +137,9 @@ Startup-time OS health probes; values exceeded at startup produce warning logs b Module: `base-crypto`. Source: [CryptoConfig.java](../../base-crypto/src/main/java/org/hiero/base/crypto/config/CryptoConfig.java). -| ID | Key | Type | Default | Effect | Range | Fragility | -|---------|---------------------------|--------|------------|----------------------------------------------------------------------------------------|-------|-----------| -| TUN-050 | `crypto.keystorePassword` | String | `password` | Password protecting the PKCS12 key stores that hold node RSA public/private key pairs. | | — | +| ID | Key | Type | Default | Effect | Range | Fragility | +|---------|---------------------------|--------|---------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------|-----------| +| TUN-050 | `crypto.keystorePassword` | String | `""` | Password protecting the PKCS12 key stores that hold node RSA public/private key pairs. Intentionally no usable default; node key loading and gossip TLS fail fast if it is not configured. | | — | ## BasicCommonConfig (no prefix)