From 12723ace68b305e31a97eee3957c99aa978d54e0 Mon Sep 17 00:00:00 2001 From: Sally MacFarlane Date: Wed, 24 Apr 2024 08:22:52 +1000 Subject: [PATCH] removed tests for pki qbft and add deprecation notice (#6979) * removed tests for pki qbft and add deprecation notice Signed-off-by: Sally MacFarlane * remove more PKI and CMS creation utils from tests Signed-off-by: Sally MacFarlane --------- Signed-off-by: Sally MacFarlane --- CHANGELOG.md | 1 + .../tests/acceptance/dsl/node/BesuNode.java | 8 - .../dsl/node/ProcessBesuNodeRunner.java | 27 -- .../dsl/node/ThreadBesuNodeRunner.java | 4 - .../node/configuration/BesuNodeFactory.java | 64 ----- .../pki/PkiKeystoreConfigurationFactory.java | 196 -------------- .../acceptance/dsl/privacy/PrivacyNode.java | 1 - .../bft/pki/ParameterizedPkiQbftTestBase.java | 29 --- .../bft/pki/PkiQbftAcceptanceTest.java | 130 ---------- ...PkiQbftAcceptanceTestParameterization.java | 120 --------- .../PkiQbftBlockCreatorTest.java | 162 ------------ .../DefaultKeyStoreWrapperProviderTest.java | 85 ------ ...lockCreationConfigurationProviderTest.java | 75 ------ .../qbft/pki/PkiQbftBlockHashingTest.java | 85 ------ .../qbft/pki/PkiQbftExtraDataCodecTest.java | 243 ------------------ .../pki/cms/CmsCreationAndValidationTest.java | 202 --------------- .../besu/pki/cms/CmsTestKeystores.java | 243 ------------------ .../keystore/BaseKeyStoreFileWrapperTest.java | 156 ----------- .../besu/pki/keystore/CryptoTestUtil.java | 81 ------ .../HardwareKeyStoreFileWrapperTest.java | 119 --------- .../keystore/HardwareKeyStoreWrapperTest.java | 82 ------ .../SoftwareKeyStoreFileWrapperTest.java | 80 ------ .../keystore/SoftwareKeyStoreWrapperTest.java | 198 -------------- .../keystore/partner1client1/keys.p12 | Bin 6068 -> 0 bytes .../keystore/partner1client1/keystore.jks | Bin 6817 -> 0 bytes .../keystore/partner1client1/nss.cfg | 6 - .../keystore/partner1client1/truststore.jks | Bin 3135 -> 0 bytes 27 files changed, 1 insertion(+), 2396 deletions(-) delete mode 100644 acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/pki/PkiKeystoreConfigurationFactory.java delete mode 100644 acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/pki/ParameterizedPkiQbftTestBase.java delete mode 100644 acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/pki/PkiQbftAcceptanceTest.java delete mode 100644 acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/pki/PkiQbftAcceptanceTestParameterization.java delete mode 100644 consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/blockcreation/PkiQbftBlockCreatorTest.java delete mode 100644 consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/pki/DefaultKeyStoreWrapperProviderTest.java delete mode 100644 consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/pki/PkiBlockCreationConfigurationProviderTest.java delete mode 100644 consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/pki/PkiQbftBlockHashingTest.java delete mode 100644 consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/pki/PkiQbftExtraDataCodecTest.java delete mode 100644 pki/src/test/java/org/hyperledger/besu/pki/cms/CmsCreationAndValidationTest.java delete mode 100644 pki/src/test/java/org/hyperledger/besu/pki/cms/CmsTestKeystores.java delete mode 100644 pki/src/test/java/org/hyperledger/besu/pki/keystore/BaseKeyStoreFileWrapperTest.java delete mode 100644 pki/src/test/java/org/hyperledger/besu/pki/keystore/CryptoTestUtil.java delete mode 100644 pki/src/test/java/org/hyperledger/besu/pki/keystore/HardwareKeyStoreFileWrapperTest.java delete mode 100644 pki/src/test/java/org/hyperledger/besu/pki/keystore/HardwareKeyStoreWrapperTest.java delete mode 100644 pki/src/test/java/org/hyperledger/besu/pki/keystore/SoftwareKeyStoreFileWrapperTest.java delete mode 100644 pki/src/test/java/org/hyperledger/besu/pki/keystore/SoftwareKeyStoreWrapperTest.java delete mode 100644 pki/src/test/resources/keystore/partner1client1/keys.p12 delete mode 100644 pki/src/test/resources/keystore/partner1client1/keystore.jks delete mode 100644 pki/src/test/resources/keystore/partner1client1/nss.cfg delete mode 100644 pki/src/test/resources/keystore/partner1client1/truststore.jks diff --git a/CHANGELOG.md b/CHANGELOG.md index 60b94c41090..7bcabc75921 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ ### Upcoming Breaking Changes - Receipt compaction will be enabled by default in a future version of Besu. After this change it will not be possible to downgrade to the previous Besu version. +- PKI-backed QBFT will be removed in a future version of Besu. Other forms of QBFT will remain unchanged. ### Deprecations diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/BesuNode.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/BesuNode.java index 80fbf7f727d..5f30941f232 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/BesuNode.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/BesuNode.java @@ -35,7 +35,6 @@ import org.hyperledger.besu.ethereum.permissioning.PermissioningConfiguration; import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration; import org.hyperledger.besu.metrics.prometheus.MetricsConfiguration; -import org.hyperledger.besu.pki.config.PkiKeyStoreConfiguration; import org.hyperledger.besu.tests.acceptance.dsl.condition.Condition; import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.NodeConfiguration; import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.genesis.GenesisConfigurationProvider; @@ -132,7 +131,6 @@ public class BesuNode implements NodeConfiguration, RunnableNode, AutoCloseable private final List staticNodes; private boolean isDnsEnabled = false; private Optional exitCode = Optional.empty(); - private Optional pkiKeyStoreConfiguration = Optional.empty(); private final boolean isStrictTxReplayProtectionEnabled; private final Map environment; @@ -169,7 +167,6 @@ public BesuNode( final Optional privacyParameters, final List runCommand, final Optional keyPair, - final Optional pkiKeyStoreConfiguration, final boolean isStrictTxReplayProtectionEnabled, final Map environment) throws IOException { @@ -230,7 +227,6 @@ public BesuNode( this.staticNodes = staticNodes; this.isDnsEnabled = isDnsEnabled; privacyParameters.ifPresent(this::setPrivacyParameters); - this.pkiKeyStoreConfiguration = pkiKeyStoreConfiguration; this.environment = environment; LOG.info("Created BesuNode {}", this); } @@ -763,10 +759,6 @@ public List getRunCommand() { return runCommand; } - public Optional getPkiKeyStoreConfiguration() { - return pkiKeyStoreConfiguration; - } - public boolean isStrictTxReplayProtectionEnabled() { return isStrictTxReplayProtectionEnabled; } diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ProcessBesuNodeRunner.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ProcessBesuNodeRunner.java index 2b80ebea568..583992718aa 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ProcessBesuNodeRunner.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ProcessBesuNodeRunner.java @@ -377,33 +377,6 @@ public void startNode(final BesuNode node) { permissioningConfiguration.getNodeSmartContractInterfaceVersion())); }); - node.getPkiKeyStoreConfiguration() - .ifPresent( - pkiConfig -> { - params.add("--Xpki-block-creation-enabled"); - - params.add("--Xpki-block-creation-keystore-certificate-alias"); - params.add(pkiConfig.getCertificateAlias()); - - params.add("--Xpki-block-creation-keystore-type"); - params.add(pkiConfig.getKeyStoreType()); - - params.add("--Xpki-block-creation-keystore-file"); - params.add(pkiConfig.getKeyStorePath().toAbsolutePath().toString()); - - params.add("--Xpki-block-creation-keystore-password-file"); - params.add(pkiConfig.getKeyStorePasswordPath().toAbsolutePath().toString()); - - params.add("--Xpki-block-creation-truststore-type"); - params.add(pkiConfig.getTrustStoreType()); - - params.add("--Xpki-block-creation-truststore-file"); - params.add(pkiConfig.getTrustStorePath().toAbsolutePath().toString()); - - params.add("--Xpki-block-creation-truststore-password-file"); - params.add(pkiConfig.getTrustStorePasswordPath().toAbsolutePath().toString()); - }); - params.addAll(node.getExtraCLIOptions()); params.add("--key-value-storage"); diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ThreadBesuNodeRunner.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ThreadBesuNodeRunner.java index e0805d57283..1493df6f0f5 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ThreadBesuNodeRunner.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ThreadBesuNodeRunner.java @@ -21,7 +21,6 @@ import org.hyperledger.besu.cli.config.EthNetworkConfig; import org.hyperledger.besu.cli.config.NetworkName; import org.hyperledger.besu.config.GenesisConfigFile; -import org.hyperledger.besu.consensus.qbft.pki.PkiBlockCreationConfigurationProvider; import org.hyperledger.besu.controller.BesuController; import org.hyperledger.besu.controller.BesuControllerBuilder; import org.hyperledger.besu.crypto.KeyPairUtil; @@ -253,9 +252,6 @@ public void startNode(final BesuNode node) { .isRevertReasonEnabled(node.isRevertReasonEnabled()) .storageProvider(storageProvider) .gasLimitCalculator(GasLimitCalculator.constant()) - .pkiBlockCreationConfiguration( - node.getPkiKeyStoreConfiguration() - .map(pkiConfig -> new PkiBlockCreationConfigurationProvider().load(pkiConfig))) .evmConfiguration(EvmConfiguration.DEFAULT) .maxPeers(maxPeers) .maxRemotelyInitiatedPeers(15) diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeFactory.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeFactory.java index ff6dc2ac9b1..51244ea9f31 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeFactory.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeFactory.java @@ -39,7 +39,6 @@ import org.hyperledger.besu.tests.acceptance.dsl.node.RunnableNode; import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.genesis.GenesisConfigurationFactory; import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.genesis.GenesisConfigurationFactory.CliqueOptions; -import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.pki.PkiKeystoreConfigurationFactory; import java.io.File; import java.io.IOException; @@ -57,8 +56,6 @@ public class BesuNodeFactory { private final NodeConfigurationFactory node = new NodeConfigurationFactory(); - private final PkiKeystoreConfigurationFactory pkiKeystoreConfigurationFactory = - new PkiKeystoreConfigurationFactory(); public BesuNode create(final BesuNodeConfiguration config) throws IOException { return new BesuNode( @@ -94,7 +91,6 @@ public BesuNode create(final BesuNodeConfiguration config) throws IOException { config.getPrivacyParameters(), config.getRunCommand(), config.getKeyPair(), - config.getPkiKeyStoreConfiguration(), config.isStrictTxReplayProtectionEnabled(), config.getEnvironment()); } @@ -517,31 +513,6 @@ public BesuNode createQbftNode(final String name) throws IOException { .build()); } - public BesuNode createPkiQbftJKSNode(final String name) throws IOException { - return createPkiQbftNode(KeyStoreWrapper.KEYSTORE_TYPE_JKS, name); - } - - public BesuNode createPkiQbftPKCS11Node(final String name) throws IOException { - return createPkiQbftNode(KeyStoreWrapper.KEYSTORE_TYPE_PKCS11, name); - } - - public BesuNode createPkiQbftPKCS12Node(final String name) throws IOException { - return createPkiQbftNode(KeyStoreWrapper.KEYSTORE_TYPE_PKCS12, name); - } - - public BesuNode createPkiQbftNode(final String type, final String name) throws IOException { - return create( - new BesuNodeConfigurationBuilder() - .name(name) - .miningEnabled() - .jsonRpcConfiguration(node.createJsonRpcWithQbftEnabledConfig(false)) - .webSocketConfiguration(node.createWebSocketEnabledConfig()) - .devMode(false) - .genesisConfigProvider(GenesisConfigurationFactory::createQbftGenesisConfig) - .pkiBlockCreationEnabled(pkiKeystoreConfigurationFactory.createPkiConfig(type, name)) - .build()); - } - public BesuNode createCustomGenesisNode( final String name, final String genesisPath, final boolean canBeBootnode) throws IOException { return createCustomGenesisNode(name, genesisPath, canBeBootnode, false); @@ -699,41 +670,6 @@ public BesuNode createQbftNodeWithContractBasedValidators( .build()); } - public BesuNode createPkiQbftJKSNodeWithValidators(final String name, final String... validators) - throws IOException { - return createPkiQbftNodeWithValidators(KeyStoreWrapper.KEYSTORE_TYPE_JKS, name, validators); - } - - public BesuNode createPkiQbftPKCS11NodeWithValidators( - final String name, final String... validators) throws IOException { - return createPkiQbftNodeWithValidators(KeyStoreWrapper.KEYSTORE_TYPE_PKCS11, name, validators); - } - - public BesuNode createPkiQbftPKCS12NodeWithValidators( - final String name, final String... validators) throws IOException { - return createPkiQbftNodeWithValidators(KeyStoreWrapper.KEYSTORE_TYPE_PKCS12, name, validators); - } - - public BesuNode createPkiQbftNodeWithValidators( - final String type, final String name, final String... validators) throws IOException { - - return create( - new BesuNodeConfigurationBuilder() - .name(name) - .miningEnabled() - .jsonRpcConfiguration(node.createJsonRpcWithQbftEnabledConfig(false)) - .webSocketConfiguration(node.createWebSocketEnabledConfig()) - .devMode(false) - .pkiBlockCreationEnabled(pkiKeystoreConfigurationFactory.createPkiConfig(type, name)) - .genesisConfigProvider( - nodes -> - node.createGenesisConfigForValidators( - asList(validators), - nodes, - GenesisConfigurationFactory::createQbftGenesisConfig)) - .build()); - } - public BesuNode createNodeWithStaticNodes(final String name, final List staticNodes) throws IOException { diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/pki/PkiKeystoreConfigurationFactory.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/pki/PkiKeystoreConfigurationFactory.java deleted file mode 100644 index ac7f814d433..00000000000 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/pki/PkiKeystoreConfigurationFactory.java +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file - * except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the - * License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See - * the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.hyperledger.besu.tests.acceptance.dsl.node.configuration.pki; - -import static org.hyperledger.besu.pki.util.TestCertificateUtils.createKeyPair; -import static org.hyperledger.besu.pki.util.TestCertificateUtils.createSelfSignedCertificate; -import static org.hyperledger.besu.pki.util.TestCertificateUtils.issueCertificate; - -import org.hyperledger.besu.pki.config.PkiKeyStoreConfiguration; -import org.hyperledger.besu.pki.keystore.KeyStoreWrapper; -import org.hyperledger.besu.pki.util.TestCertificateUtils; - -import java.io.FileOutputStream; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.security.KeyPair; -import java.security.KeyStore; -import java.security.cert.Certificate; -import java.security.cert.X509Certificate; -import java.time.Instant; -import java.time.temporal.ChronoUnit; -import java.util.Objects; -import java.util.UUID; - -public class PkiKeystoreConfigurationFactory { - - /* - PKCS11 config files - */ - final String NSSCONFIG_PATH_STRING = "/pki-certs/%s/nss.cfg"; - final String NSSPIN_PATH_STRING = "/pki-certs/%s/nsspin.txt"; - final String TRUSTSTORE_PATH_STRING = "/pki-certs/%s/truststore.p12"; - final String CRL_PATH_STRING = "/pki-certs/crl/crl.pem"; - - /* - Software keystore config - */ - public static final String KEYSTORE_DEFAULT_PASSWORD = "password"; - - private KeyPair caKeyPair; - private X509Certificate caCertificate; - private Path trustStoreFile; - private Path passwordFile; - - public PkiKeyStoreConfiguration createPkiConfig(final String type, final String name) { - if (KeyStoreWrapper.KEYSTORE_TYPE_PKCS11.equals(type)) { - return createPKCS11PkiConfig(name); - } else { - return createSoftwareKeyStorePkiConfig(type, name); - } - } - - private PkiKeyStoreConfiguration createPKCS11PkiConfig(final String name) { - final PkiKeyStoreConfiguration.Builder pkiKeyStoreConfigBuilder = - new PkiKeyStoreConfiguration.Builder(); - - try { - pkiKeyStoreConfigBuilder - .withKeyStoreType(KeyStoreWrapper.KEYSTORE_TYPE_PKCS11) - .withKeyStorePath( - PKCS11Utils.initNSSConfigFile( - readResourceAsPath(String.format(NSSCONFIG_PATH_STRING, name)))) - .withKeyStorePasswordPath(readResourceAsPath(String.format(NSSPIN_PATH_STRING, name))) - .withTrustStoreType(KeyStoreWrapper.KEYSTORE_TYPE_PKCS12) - .withTrustStorePath(readResourceAsPath(String.format(TRUSTSTORE_PATH_STRING, name))) - .withTrustStorePasswordPath(readResourceAsPath(String.format(NSSPIN_PATH_STRING, name))) - .withCrlFilePath(readResourceAsPath(CRL_PATH_STRING)) - .withCertificateAlias(name); - - } catch (Exception e) { - throw new RuntimeException(e); - } - - return pkiKeyStoreConfigBuilder.build(); - } - - private PkiKeyStoreConfiguration createSoftwareKeyStorePkiConfig( - final String type, final String name) { - PkiKeyStoreConfiguration.Builder pkiKeyStoreConfigBuilder = - new PkiKeyStoreConfiguration.Builder(); - - pkiKeyStoreConfigBuilder.withTrustStoreType(type); - pkiKeyStoreConfigBuilder.withTrustStorePath(createTrustStore(type)); - pkiKeyStoreConfigBuilder.withTrustStorePasswordPath(passwordFile); - - pkiKeyStoreConfigBuilder.withKeyStoreType(type); - pkiKeyStoreConfigBuilder.withKeyStorePath(createKeyStore(type, name)); - pkiKeyStoreConfigBuilder.withKeyStorePasswordPath(passwordFile); - - pkiKeyStoreConfigBuilder.withCertificateAlias(name); - - return pkiKeyStoreConfigBuilder.build(); - } - - private Path createTrustStore(final String type) { - // Only create the truststore if this is the first time this method is being called - if (caKeyPair == null) { - try { - caKeyPair = createKeyPair(TestCertificateUtils.Algorithm.RSA); - caCertificate = createSelfSignedCertificate("ca", notBefore(), notAfter(), caKeyPair); - - final KeyStore truststore = KeyStore.getInstance(type); - truststore.load(null, null); - truststore.setCertificateEntry("ca", caCertificate); - - final String uniqueId = UUID.randomUUID().toString(); - trustStoreFile = writeKeyStoreFile(truststore, "truststore", uniqueId); - passwordFile = writePasswordFile(KEYSTORE_DEFAULT_PASSWORD, "password", uniqueId); - } catch (final Exception e) { - throw new RuntimeException("Error creating truststore for Acceptance Test", e); - } - } - - return trustStoreFile; - } - - private Path createKeyStore(final String type, final String alias) { - if (caKeyPair == null) { - createTrustStore(type); - } - - final KeyPair kp = createKeyPair(TestCertificateUtils.Algorithm.RSA); - final X509Certificate certificate = - issueCertificate(caCertificate, caKeyPair, "validator", notBefore(), notAfter(), kp, false); - - try { - final KeyStore keyStore = KeyStore.getInstance(type); - keyStore.load(null, null); - keyStore.setKeyEntry( - alias, - kp.getPrivate(), - KEYSTORE_DEFAULT_PASSWORD.toCharArray(), - new Certificate[] {certificate, caCertificate}); - - final String id = UUID.randomUUID().toString(); - return writeKeyStoreFile(keyStore, "keystore", id); - } catch (final Exception e) { - throw new RuntimeException("Error creating keystore for Acceptance Test", e); - } - } - - private Path writeKeyStoreFile( - final KeyStore keyStore, final String prefix, final String suffix) { - try { - final Path file = Files.createTempFile(prefix, suffix != null ? suffix : ""); - file.toFile().deleteOnExit(); - final FileOutputStream keyStoreFOS = new FileOutputStream(file.toFile()); - keyStore.store(keyStoreFOS, KEYSTORE_DEFAULT_PASSWORD.toCharArray()); - - return file; - } catch (final Exception e) { - throw new RuntimeException("Error creating keystore file", e); - } - } - - private Path writePasswordFile(final String password, final String prefix, final String suffix) { - try { - final Path file = Files.createTempFile(prefix, suffix); - file.toFile().deleteOnExit(); - Files.write(file, password.getBytes(StandardCharsets.UTF_8)); - return file; - } catch (final IOException e) { - throw new RuntimeException("Error creating password file", e); - } - } - - private Instant notBefore() { - return Instant.now().minus(1, ChronoUnit.DAYS); - } - - private Instant notAfter() { - return Instant.now().plus(10, ChronoUnit.DAYS); - } - - private Path readResourceAsPath(final String path) throws Exception { - return Path.of(Objects.requireNonNull(this.getClass().getResource(path)).toURI()); - } -} diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/PrivacyNode.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/PrivacyNode.java index 1c0df5ace6d..c9487ebcd67 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/PrivacyNode.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/PrivacyNode.java @@ -130,7 +130,6 @@ public PrivacyNode( besuConfig.getPrivacyParameters(), List.of(), Optional.empty(), - Optional.empty(), besuConfig.isStrictTxReplayProtectionEnabled(), besuConfig.getEnvironment()); } diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/pki/ParameterizedPkiQbftTestBase.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/pki/ParameterizedPkiQbftTestBase.java deleted file mode 100644 index b1ffcff3712..00000000000 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/pki/ParameterizedPkiQbftTestBase.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2020 ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.tests.acceptance.bft.pki; - -import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBaseJunit5; - -import java.util.stream.Stream; - -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.params.provider.Arguments; - -@Disabled("This is not a test class, it offers PKI QBFT parameterization only.") -public abstract class ParameterizedPkiQbftTestBase extends AcceptanceTestBaseJunit5 { - public static Stream factoryFunctions() { - return PkiQbftAcceptanceTestParameterization.getFactories(); - } -} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/pki/PkiQbftAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/pki/PkiQbftAcceptanceTest.java deleted file mode 100644 index 12ae887a510..00000000000 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/pki/PkiQbftAcceptanceTest.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file - * except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the - * License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See - * the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.tests.acceptance.bft.pki; - -import org.hyperledger.besu.tests.acceptance.dsl.account.Account; -import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; - -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.MethodSource; - -public class PkiQbftAcceptanceTest extends ParameterizedPkiQbftTestBase { - - @ParameterizedTest(name = "{index}: {0}") - @MethodSource("factoryFunctions") - public void shouldMineOnSingleNode( - final String testName, final PkiQbftAcceptanceTestParameterization nodeFactory) - throws Exception { - final BesuNode minerNode = nodeFactory.createNode(besu, "miner1"); - cluster.start(minerNode); - - cluster.verify(blockchain.reachesHeight(minerNode, 1)); - - final Account sender = accounts.createAccount("account1"); - final Account receiver = accounts.createAccount("account2"); - - minerNode.execute(accountTransactions.createTransfer(sender, 50)); - cluster.verify(sender.balanceEquals(50)); - - minerNode.execute(accountTransactions.createIncrementalTransfers(sender, receiver, 1)); - cluster.verify(receiver.balanceEquals(1)); - - minerNode.execute(accountTransactions.createIncrementalTransfers(sender, receiver, 2)); - cluster.verify(receiver.balanceEquals(3)); - } - - @ParameterizedTest(name = "{index}: {0}") - @MethodSource("factoryFunctions") - public void shouldMineOnMultipleNodes( - final String testName, final PkiQbftAcceptanceTestParameterization nodeFactory) - throws Exception { - final BesuNode minerNode1 = nodeFactory.createNode(besu, "miner1"); - final BesuNode minerNode2 = nodeFactory.createNode(besu, "miner2"); - final BesuNode minerNode3 = nodeFactory.createNode(besu, "miner3"); - final BesuNode minerNode4 = nodeFactory.createNode(besu, "miner4"); - cluster.start(minerNode1, minerNode2, minerNode3, minerNode4); - - cluster.verify(blockchain.reachesHeight(minerNode1, 1, 85)); - - final Account sender = accounts.createAccount("account1"); - final Account receiver = accounts.createAccount("account2"); - - minerNode1.execute(accountTransactions.createTransfer(sender, 50)); - cluster.verify(sender.balanceEquals(50)); - - minerNode2.execute(accountTransactions.createIncrementalTransfers(sender, receiver, 1)); - cluster.verify(receiver.balanceEquals(1)); - - minerNode3.execute(accountTransactions.createIncrementalTransfers(sender, receiver, 2)); - cluster.verify(receiver.balanceEquals(3)); - - minerNode4.execute(accountTransactions.createIncrementalTransfers(sender, receiver, 3)); - cluster.verify(receiver.balanceEquals(6)); - } - - @ParameterizedTest(name = "{index}: {0}") - @MethodSource("factoryFunctions") - public void shouldMineWithIgnoringANodeInCRL( - final String testName, final PkiQbftAcceptanceTestParameterization nodeFactory) - throws Exception { - final BesuNode minerNode1 = nodeFactory.createNode(besu, "miner1"); - final BesuNode minerNode2 = nodeFactory.createNode(besu, "miner2"); - final BesuNode minerNode3 = nodeFactory.createNode(besu, "miner3"); - final BesuNode minerNode4 = nodeFactory.createNode(besu, "miner4"); - final BesuNode minerNode5 = nodeFactory.createNode(besu, "miner5"); - final BesuNode minerNode6 = nodeFactory.createNode(besu, "miner6"); - try { - cluster.start(minerNode1, minerNode2, minerNode3, minerNode4); - - cluster.startNode(minerNode5); - cluster.startNode(minerNode6); - - cluster.verify(blockchain.reachesHeight(minerNode1, 1, 85)); - - final Account sender = accounts.createAccount("account1"); - final Account receiver = accounts.createAccount("account2"); - - minerNode1.execute(accountTransactions.createTransfer(sender, 50)); - cluster.verify(sender.balanceEquals(50)); - - minerNode2.execute(accountTransactions.createIncrementalTransfers(sender, receiver, 1)); - cluster.verify(receiver.balanceEquals(1)); - - minerNode3.execute(accountTransactions.createIncrementalTransfers(sender, receiver, 2)); - cluster.verify(receiver.balanceEquals(3)); - - minerNode4.execute(accountTransactions.createIncrementalTransfers(sender, receiver, 3)); - cluster.verify(receiver.balanceEquals(6)); - - if (minerNode1.getTLSConfiguration().isEmpty()) { - minerNode1.verify(net.awaitPeerCount(5)); - minerNode5.verify(net.awaitPeerCount(5)); - minerNode6.verify(net.awaitPeerCount(5)); - } else { - minerNode1.verify(net.awaitPeerCount(3)); - minerNode5.verify(net.awaitPeerCount(0)); - minerNode6.verify(net.awaitPeerCount(0)); - } - } finally { - cluster.stopNode(minerNode5); - cluster.stopNode(minerNode6); - minerNode5.close(); - minerNode6.close(); - } - } -} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/pki/PkiQbftAcceptanceTestParameterization.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/pki/PkiQbftAcceptanceTestParameterization.java deleted file mode 100644 index 7bcf09afd38..00000000000 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/pki/PkiQbftAcceptanceTestParameterization.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright 2020 ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file - * except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the - * License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See - * the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.tests.acceptance.bft.pki; - -import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; -import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.BesuNodeFactory; - -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Stream; - -import org.junit.jupiter.params.provider.Arguments; - -public class PkiQbftAcceptanceTestParameterization { - - public static Stream getFactories() { - List args = new ArrayList<>(); - - /* - BLOCK CREATION - */ - - args.add( - Arguments.of( - "qbft-pki-jks", - new PkiQbftAcceptanceTestParameterization( - BesuNodeFactory::createPkiQbftJKSNode, - BesuNodeFactory::createPkiQbftJKSNodeWithValidators))); - - args.add( - Arguments.of( - "qbft-pki-pkcs12", - new PkiQbftAcceptanceTestParameterization( - BesuNodeFactory::createPkiQbftPKCS12Node, - BesuNodeFactory::createPkiQbftPKCS12NodeWithValidators))); - - if (Boolean.getBoolean("acctests.runBesuAsProcess")) { - args.add( - Arguments.of( - "qbft-pki-pkcs11", - new PkiQbftAcceptanceTestParameterization( - BesuNodeFactory::createPkiQbftPKCS11Node, - BesuNodeFactory::createPkiQbftPKCS11NodeWithValidators))); - } - - /* - TLS - */ - - args.add( - Arguments.of( - "qbft-tls-jks", - new PkiQbftAcceptanceTestParameterization( - BesuNodeFactory::createQbftNodeWithTLSJKS, - BesuNodeFactory::createQbftTLSJKSNodeWithValidators))); - - args.add( - Arguments.of( - "qbft-tls-pkcs12", - new PkiQbftAcceptanceTestParameterization( - BesuNodeFactory::createQbftNodeWithTLSPKCS12, - BesuNodeFactory::createQbftTLSPKCS12NodeWithValidators))); - - if (Boolean.getBoolean("acctests.runBesuAsProcess")) { - args.add( - Arguments.of( - "qbft-tls-pkcs11", - new PkiQbftAcceptanceTestParameterization( - BesuNodeFactory::createQbftNodeWithTLSPKCS11, - BesuNodeFactory::createQbftTLSPKCS11NodeWithValidators))); - } - - return args.stream(); - } - - @FunctionalInterface - public interface NodeCreator { - - BesuNode create(BesuNodeFactory factory, String name) throws Exception; - } - - @FunctionalInterface - public interface NodeWithValidatorsCreator { - - BesuNode create(BesuNodeFactory factory, String name, String[] validators) throws Exception; - } - - private final NodeCreator creatorFn; - private final NodeWithValidatorsCreator createorWithValidatorFn; - - public PkiQbftAcceptanceTestParameterization( - final NodeCreator creatorFn, final NodeWithValidatorsCreator createorWithValidatorFn) { - this.creatorFn = creatorFn; - this.createorWithValidatorFn = createorWithValidatorFn; - } - - public BesuNode createNode(BesuNodeFactory factory, String name) throws Exception { - return creatorFn.create(factory, name); - } - - public BesuNode createNodeWithValidators( - BesuNodeFactory factory, String name, String[] validators) throws Exception { - return createorWithValidatorFn.create(factory, name, validators); - } -} diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/blockcreation/PkiQbftBlockCreatorTest.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/blockcreation/PkiQbftBlockCreatorTest.java deleted file mode 100644 index e8282f9de9b..00000000000 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/blockcreation/PkiQbftBlockCreatorTest.java +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.consensus.qbft.blockcreation; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.hyperledger.besu.consensus.common.bft.BftExtraDataFixture.createExtraData; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import org.hyperledger.besu.consensus.common.bft.BftBlockHeaderFunctions; -import org.hyperledger.besu.consensus.common.bft.BftExtraData; -import org.hyperledger.besu.consensus.common.bft.BftProtocolSchedule; -import org.hyperledger.besu.consensus.qbft.QbftExtraDataCodec; -import org.hyperledger.besu.consensus.qbft.pki.PkiQbftBlockHeaderFunctions; -import org.hyperledger.besu.consensus.qbft.pki.PkiQbftExtraData; -import org.hyperledger.besu.consensus.qbft.pki.PkiQbftExtraDataCodec; -import org.hyperledger.besu.datatypes.Hash; -import org.hyperledger.besu.ethereum.blockcreation.BlockCreationTiming; -import org.hyperledger.besu.ethereum.blockcreation.BlockCreator; -import org.hyperledger.besu.ethereum.blockcreation.BlockCreator.BlockCreationResult; -import org.hyperledger.besu.ethereum.blockcreation.txselection.TransactionSelectionResults; -import org.hyperledger.besu.ethereum.core.Block; -import org.hyperledger.besu.ethereum.core.BlockBody; -import org.hyperledger.besu.ethereum.core.BlockHeader; -import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture; -import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec; -import org.hyperledger.besu.ethereum.mainnet.WithdrawalsValidator; -import org.hyperledger.besu.pki.cms.CmsCreator; - -import java.util.Collections; - -import org.apache.tuweni.bytes.Bytes; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -public class PkiQbftBlockCreatorTest { - - private final PkiQbftExtraDataCodec extraDataCodec = new PkiQbftExtraDataCodec(); - - private BlockCreator blockCreator; - private CmsCreator cmsCreator; - private PkiQbftBlockCreator pkiQbftBlockCreator; - private BlockHeaderTestFixture blockHeaderBuilder; - private BlockHeader blockHeader; - private BftProtocolSchedule protocolSchedule; - private ProtocolSpec protocolSpec; - - @BeforeEach - public void before() { - blockCreator = mock(BlockCreator.class); - cmsCreator = mock(CmsCreator.class); - blockHeader = mock(BlockHeader.class); - protocolSchedule = mock(BftProtocolSchedule.class); - protocolSpec = mock(ProtocolSpec.class); - - pkiQbftBlockCreator = - new PkiQbftBlockCreator( - blockCreator, cmsCreator, extraDataCodec, blockHeader, protocolSchedule); - - blockHeaderBuilder = new BlockHeaderTestFixture(); - - when(protocolSchedule.getByBlockNumberOrTimestamp(anyLong(), anyLong())) - .thenReturn(protocolSpec); - } - - @Test - public void createProposalBehaviourWithNonPkiCodecFails() { - assertThatThrownBy( - () -> - new PkiQbftBlockCreator( - blockCreator, - cmsCreator, - new QbftExtraDataCodec(), - blockHeader, - protocolSchedule)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("PkiQbftBlockCreator must use PkiQbftExtraDataCodec"); - } - - @Test - public void cmsInProposedBlockHasValueCreatedByCmsCreator() { - createBlockBeingProposed(); - when(protocolSpec.getWithdrawalsValidator()) - .thenReturn(new WithdrawalsValidator.AllowedWithdrawals()); - - final Bytes cms = Bytes.random(32); - when(cmsCreator.create(any(Bytes.class))).thenReturn(cms); - - final Block proposedBlock = pkiQbftBlockCreator.createBlock(1L).getBlock(); - - final PkiQbftExtraData proposedBlockExtraData = - (PkiQbftExtraData) extraDataCodec.decodeRaw(proposedBlock.getHeader().getExtraData()); - assertThat(proposedBlockExtraData).isInstanceOf(PkiQbftExtraData.class); - assertThat(proposedBlockExtraData.getCms()).isEqualTo(cms); - } - - @Test - public void cmsIsCreatedWithCorrectHashingFunction() { - when(protocolSpec.getWithdrawalsValidator()) - .thenReturn(new WithdrawalsValidator.ProhibitedWithdrawals()); - final Block block = createBlockBeingProposed(); - final Hash expectedHashForCmsCreation = - PkiQbftBlockHeaderFunctions.forCmsSignature(extraDataCodec).hash(block.getHeader()); - - when(cmsCreator.create(any(Bytes.class))).thenReturn(Bytes.random(32)); - - pkiQbftBlockCreator.createBlock(1L); - - verify(cmsCreator).create(eq(expectedHashForCmsCreation)); - } - - @Test - public void proposedBlockHashUsesCommittedSealHeaderFunction() { - createBlockBeingProposed(); - when(cmsCreator.create(any(Bytes.class))).thenReturn(Bytes.random(32)); - - final Block blockWithCms = pkiQbftBlockCreator.createBlock(1L).getBlock(); - - final Hash expectedBlockHash = - BftBlockHeaderFunctions.forCommittedSeal(extraDataCodec).hash(blockWithCms.getHeader()); - - assertThat(blockWithCms.getHash()).isEqualTo(expectedBlockHash); - } - - private Block createBlockBeingProposed() { - final BftExtraData originalExtraData = - createExtraData(blockHeaderBuilder.buildHeader(), extraDataCodec); - final BlockHeader blockHeaderWithExtraData = - blockHeaderBuilder.extraData(extraDataCodec.encode(originalExtraData)).buildHeader(); - final Block block = - new Block( - blockHeaderWithExtraData, - new BlockBody(Collections.emptyList(), Collections.emptyList())); - when(blockCreator.createBlock(eq(1L))) - .thenReturn( - new BlockCreationResult( - block, new TransactionSelectionResults(), new BlockCreationTiming())); - when(blockCreator.createEmptyWithdrawalsBlock(anyLong())) - .thenReturn( - new BlockCreationResult( - block, new TransactionSelectionResults(), new BlockCreationTiming())); - - return block; - } -} diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/pki/DefaultKeyStoreWrapperProviderTest.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/pki/DefaultKeyStoreWrapperProviderTest.java deleted file mode 100644 index f5c91305cda..00000000000 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/pki/DefaultKeyStoreWrapperProviderTest.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file - * except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the - * License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See - * the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.hyperledger.besu.consensus.qbft.pki; - -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoInteractions; - -import org.hyperledger.besu.consensus.qbft.pki.DefaultKeyStoreWrapperProvider.HardwareKeyStoreWrapperProvider; -import org.hyperledger.besu.consensus.qbft.pki.DefaultKeyStoreWrapperProvider.SoftwareKeyStoreWrapperProvider; -import org.hyperledger.besu.pki.keystore.KeyStoreWrapper; - -import java.nio.file.Path; - -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -@ExtendWith(MockitoExtension.class) -public class DefaultKeyStoreWrapperProviderTest { - - @Mock private HardwareKeyStoreWrapperProvider hardwareKeyStoreWrapperProvider; - @Mock private SoftwareKeyStoreWrapperProvider softwareKeyStoreWrapperProvider; - @InjectMocks private DefaultKeyStoreWrapperProvider keyStoreWrapperProvider; - - private final Path keystorePath = Path.of("/keystore"); - private final String keystorePassword = "pwd"; - private final Path crlPath = Path.of("/crl"); - - @Test - public void configWithTypePKCS11UsesHardwareKeyStoreProvider() { - keyStoreWrapperProvider.apply( - KeyStoreWrapper.KEYSTORE_TYPE_PKCS11, keystorePath, keystorePassword, crlPath); - - verify(hardwareKeyStoreWrapperProvider) - .get(eq(keystorePassword), eq(keystorePath), eq(crlPath)); - verifyNoInteractions(softwareKeyStoreWrapperProvider); - } - - @Test - public void configWithTypePKCS12UsesSoftwareKeyStoreProvider() { - keyStoreWrapperProvider.apply( - KeyStoreWrapper.KEYSTORE_TYPE_PKCS12, keystorePath, keystorePassword, crlPath); - - verify(softwareKeyStoreWrapperProvider) - .get( - eq(KeyStoreWrapper.KEYSTORE_TYPE_PKCS12), - eq(keystorePath), - eq(keystorePassword), - eq(crlPath)); - verifyNoInteractions(hardwareKeyStoreWrapperProvider); - } - - @Test - public void configWithTypeJKSUsesSoftwareKeyStoreProvider() { - keyStoreWrapperProvider.apply( - KeyStoreWrapper.KEYSTORE_TYPE_JKS, keystorePath, keystorePassword, crlPath); - - verify(softwareKeyStoreWrapperProvider) - .get( - eq(KeyStoreWrapper.KEYSTORE_TYPE_JKS), - eq(keystorePath), - eq(keystorePassword), - eq(crlPath)); - verifyNoInteractions(hardwareKeyStoreWrapperProvider); - } -} diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/pki/PkiBlockCreationConfigurationProviderTest.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/pki/PkiBlockCreationConfigurationProviderTest.java deleted file mode 100644 index 27ccfe1bcfe..00000000000 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/pki/PkiBlockCreationConfigurationProviderTest.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.hyperledger.besu.consensus.qbft.pki; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.ArgumentMatchers.isNull; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.when; - -import org.hyperledger.besu.pki.config.PkiKeyStoreConfiguration; -import org.hyperledger.besu.pki.keystore.KeyStoreWrapper; - -import java.nio.file.Path; - -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -@ExtendWith(MockitoExtension.class) -public class PkiBlockCreationConfigurationProviderTest { - - @Mock KeyStoreWrapperProvider keyStoreWrapperProvider; - @Mock KeyStoreWrapper keyStoreWrapper; - @Mock KeyStoreWrapper trustStoreWrapper; - - @Test - public void pkiBlockCreationConfigurationIsLoadedCorrectly() { - when(keyStoreWrapperProvider.apply(any(), eq(Path.of("/tmp/keystore")), eq("pwd"), isNull())) - .thenReturn(keyStoreWrapper); - when(keyStoreWrapperProvider.apply( - any(), eq(Path.of("/tmp/truststore")), eq("pwd"), eq(Path.of("/tmp/crl")))) - .thenReturn(trustStoreWrapper); - - final PkiKeyStoreConfiguration pkiKeyStoreConfiguration = - spy( - new PkiKeyStoreConfiguration.Builder() - .withKeyStorePath(Path.of("/tmp/keystore")) - .withKeyStorePasswordPath(Path.of("/tmp/password")) - .withTrustStorePath(Path.of("/tmp/truststore")) - .withTrustStorePasswordPath(Path.of("/tmp/password")) - .withCertificateAlias("anAlias") - .withCrlFilePath(Path.of("/tmp/crl")) - .build()); - doReturn("pwd").when(pkiKeyStoreConfiguration).getKeyStorePassword(); - doReturn("pwd").when(pkiKeyStoreConfiguration).getTrustStorePassword(); - - final PkiBlockCreationConfigurationProvider pkiBlockCreationConfigProvider = - new PkiBlockCreationConfigurationProvider(keyStoreWrapperProvider); - - final PkiBlockCreationConfiguration pkiBlockCreationConfiguration = - pkiBlockCreationConfigProvider.load(pkiKeyStoreConfiguration); - - assertThat(pkiBlockCreationConfiguration).isNotNull(); - assertThat(pkiBlockCreationConfiguration.getKeyStore()).isNotNull(); - assertThat(pkiBlockCreationConfiguration.getTrustStore()).isNotNull(); - assertThat(pkiBlockCreationConfiguration.getCertificateAlias()).isEqualTo("anAlias"); - } -} diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/pki/PkiQbftBlockHashingTest.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/pki/PkiQbftBlockHashingTest.java deleted file mode 100644 index 45ec1a780df..00000000000 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/pki/PkiQbftBlockHashingTest.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file - * except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the - * License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See - * the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.hyperledger.besu.consensus.qbft.pki; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; - -import org.hyperledger.besu.consensus.common.bft.BftBlockHashing; -import org.hyperledger.besu.consensus.common.bft.BftExtraData; -import org.hyperledger.besu.consensus.common.bft.BftExtraDataFixture; -import org.hyperledger.besu.datatypes.Hash; -import org.hyperledger.besu.ethereum.core.BlockHeader; -import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture; - -import org.apache.tuweni.bytes.Bytes; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -public class PkiQbftBlockHashingTest { - - private PkiQbftExtraDataCodec pkiExtraDataCodec = new PkiQbftExtraDataCodec(); - private PkiQbftBlockHashing pkiQbftBlockHashing; - - @BeforeEach - public void before() { - pkiExtraDataCodec = spy(new PkiQbftExtraDataCodec()); - pkiQbftBlockHashing = new PkiQbftBlockHashing(pkiExtraDataCodec); - } - - @Test - public void blockHashingUsesCorrectEncodingWithoutCmsMethodInCodec() { - final PkiQbftExtraData pkiQbftExtraData = createPkiQbftExtraData(); - final BlockHeader headerWithExtraData = - new BlockHeaderTestFixture() - .number(1L) - .extraData(pkiExtraDataCodec.encode(pkiQbftExtraData)) - .buildHeader(); - - // Expected hash using the extraData encoded by the encodeWithoutCms method of the codec - final Hash expectedHash = - Hash.hash( - BftBlockHashing.serializeHeader( - headerWithExtraData, - () -> pkiExtraDataCodec.encodeWithoutCms(pkiQbftExtraData), - pkiExtraDataCodec)); - - final Hash hash = - pkiQbftBlockHashing.calculateHashOfBftBlockForCmsSignature(headerWithExtraData); - - assertThat(hash).isEqualTo(expectedHash); - - /* - Verify that the encodeWithoutCms method was called twice, once when calculating the - expected hash and a second time as part of the hash calculation on - calculateHashOfBftBlockForCmsSignature - */ - verify(pkiExtraDataCodec, times(2)).encodeWithoutCms(any(PkiQbftExtraData.class)); - } - - private PkiQbftExtraData createPkiQbftExtraData() { - final BlockHeader blockHeader = new BlockHeaderTestFixture().buildHeader(); - final BftExtraData extraData = - BftExtraDataFixture.createExtraData(blockHeader, pkiExtraDataCodec); - return new PkiQbftExtraData(extraData, Bytes.random(32)); - } -} diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/pki/PkiQbftExtraDataCodecTest.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/pki/PkiQbftExtraDataCodecTest.java deleted file mode 100644 index 32fc034b8e8..00000000000 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/pki/PkiQbftExtraDataCodecTest.java +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Copyright 2020 ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.hyperledger.besu.consensus.qbft.pki; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.hyperledger.besu.consensus.qbft.QbftExtraDataCodecTestUtils.createNonEmptyVanityData; - -import org.hyperledger.besu.consensus.common.bft.BftExtraData; -import org.hyperledger.besu.consensus.common.bft.Vote; -import org.hyperledger.besu.crypto.SECPSignature; -import org.hyperledger.besu.crypto.SignatureAlgorithm; -import org.hyperledger.besu.crypto.SignatureAlgorithmFactory; -import org.hyperledger.besu.datatypes.Address; -import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput; - -import java.math.BigInteger; -import java.util.Arrays; -import java.util.List; -import java.util.Optional; -import java.util.Random; -import java.util.function.Supplier; - -import com.google.common.base.Suppliers; -import org.apache.tuweni.bytes.Bytes; -import org.junit.jupiter.api.Test; - -public class PkiQbftExtraDataCodecTest { - - private static final Supplier SIGNATURE_ALGORITHM = - Suppliers.memoize(SignatureAlgorithmFactory::getInstance); - - // Arbitrary bytes representing a non-empty CMS - private final Bytes cms = Bytes.fromHexString("0x01"); - - private final String RAW_EXCLUDE_COMMIT_SEALS_AND_ROUND_NUMBER_ENCODED_STRING = - "0xf867a00102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20ea940000000000000000" - + "000000000000000000000001940000000000000000000000000000000000000002d7940000000000000000" - + "00000000000000000000000181ff80c001"; - - private final String RAW_EXCLUDE_COMMIT_SEALS_ENCODED_STRING = - "0xf86aa00102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20ea940000000000000000" - + "000000000000000000000001940000000000000000000000000000000000000002d7940000000000000000" - + "00000000000000000000000181ff83fedcbac001"; - - private final String RAW_ALL_ENCODED_STRING = - "0xf8f1a00102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20ea940000000000000000" - + "000000000000000000000001940000000000000000000000000000000000000002d7940000000000000000" - + "00000000000000000000000181ff83fedcbaf886b841000000000000000000000000000000000000000000" - + "0000000000000000000001000000000000000000000000000000000000000000000000000000000000000a" - + "00b841000000000000000000000000000000000000000000000000000000000000000a0000000000000000" - + "0000000000000000000000000000000000000000000000010001"; - - private final String RAW_QBFT_EXTRA_DATA = - "0xf8f0a00102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20ea940000000000000000" - + "000000000000000000000001940000000000000000000000000000000000000002d7940000000000000000" - + "00000000000000000000000181ff83fedcbaf886b841000000000000000000000000000000000000000000" - + "0000000000000000000001000000000000000000000000000000000000000000000000000000000000000a" - + "00b841000000000000000000000000000000000000000000000000000000000000000a0000000000000000" - + "00000000000000000000000000000000000000000000000100"; - - private final PkiQbftExtraDataCodec bftExtraDataCodec = new PkiQbftExtraDataCodec(); - - @Test - public void fullyPopulatedDataProducesCorrectlyFormedExtraDataObject() { - final List
validators = - Arrays.asList(Address.fromHexString("1"), Address.fromHexString("2")); - final int round = 0x00FEDCBA; - final List committerSeals = - Arrays.asList( - SIGNATURE_ALGORITHM.get().createSignature(BigInteger.ONE, BigInteger.TEN, (byte) 0), - SIGNATURE_ALGORITHM.get().createSignature(BigInteger.TEN, BigInteger.ONE, (byte) 0)); - - // Create randomised vanity data. - final byte[] vanity_bytes = createNonEmptyVanityData(); - new Random().nextBytes(vanity_bytes); - final Bytes vanity_data = Bytes.wrap(vanity_bytes); - - final BytesValueRLPOutput encoder = new BytesValueRLPOutput(); - encoder.startList(); // start extra data list - // vanity data - encoder.writeBytes(vanity_data); - // validators - encoder.writeList(validators, (validator, rlp) -> rlp.writeBytes(validator)); - // votes - encoder.startList(); - encoder.writeBytes(Address.fromHexString("1")); - encoder.writeByte(Vote.ADD_BYTE_VALUE); - encoder.endList(); - // rounds - encoder.writeIntScalar(round); - // committer seals - encoder.writeList(committerSeals, (committer, rlp) -> rlp.writeBytes(committer.encodedBytes())); - // cms - encoder.writeBytes(cms); - encoder.endList(); // end extra data list - - final Bytes bufferToInject = encoder.encoded(); - - final PkiQbftExtraData extraData = - (PkiQbftExtraData) bftExtraDataCodec.decodeRaw(bufferToInject); - - assertThat(extraData.getVanityData()).isEqualTo(vanity_data); - assertThat(extraData.getRound()).isEqualTo(round); - assertThat(extraData.getSeals()).isEqualTo(committerSeals); - assertThat(extraData.getValidators()).isEqualTo(validators); - assertThat(extraData.getCms()).isEqualTo(cms); - } - - @Test - public void decodingQbftExtraDataDelegatesToQbftCodec() { - final List
validators = - Arrays.asList(Address.fromHexString("1"), Address.fromHexString("2")); - final int round = 0x00FEDCBA; - final List committerSeals = - Arrays.asList( - SIGNATURE_ALGORITHM.get().createSignature(BigInteger.ONE, BigInteger.TEN, (byte) 0), - SIGNATURE_ALGORITHM.get().createSignature(BigInteger.TEN, BigInteger.ONE, (byte) 0)); - - // Create randomised vanity data. - final byte[] vanity_bytes = createNonEmptyVanityData(); - new Random().nextBytes(vanity_bytes); - final Bytes vanity_data = Bytes.wrap(vanity_bytes); - - final BytesValueRLPOutput encoder = new BytesValueRLPOutput(); - encoder.startList(); // start extra data list - // vanity data - encoder.writeBytes(vanity_data); - // validators - encoder.writeList(validators, (validator, rlp) -> rlp.writeBytes(validator)); - // votes - encoder.startList(); - encoder.writeBytes(Address.fromHexString("1")); - encoder.writeByte(Vote.ADD_BYTE_VALUE); - encoder.endList(); - // rounds - encoder.writeIntScalar(round); - // committer seals - encoder.writeList(committerSeals, (committer, rlp) -> rlp.writeBytes(committer.encodedBytes())); - // Not including the CMS in the list (to generate a non-pki QBFT extra data) - encoder.endList(); // end extra data list - - final Bytes bufferToInject = encoder.encoded(); - - final PkiQbftExtraData extraData = - (PkiQbftExtraData) bftExtraDataCodec.decodeRaw(bufferToInject); - - assertThat(extraData.getVanityData()).isEqualTo(vanity_data); - assertThat(extraData.getRound()).isEqualTo(round); - assertThat(extraData.getSeals()).isEqualTo(committerSeals); - assertThat(extraData.getValidators()).isEqualTo(validators); - assertThat(extraData.getCms()).isEqualTo(Bytes.EMPTY); - } - - /* - When encoding for blockchain, we ignore commit seals and round number, but we include the CMS - */ - @Test - public void encodingForBlockchainShouldIncludeCms() { - final Bytes expectedRawDecoding = - Bytes.fromHexString(RAW_EXCLUDE_COMMIT_SEALS_AND_ROUND_NUMBER_ENCODED_STRING); - final Bytes encoded = - bftExtraDataCodec.encodeWithoutCommitSealsAndRoundNumber(getDecodedExtraData(cms)); - - assertThat(encoded).isEqualTo(expectedRawDecoding); - } - - @Test - public void encodingWithoutCommitSealsShouldIncludeCms() { - final Bytes expectedRawDecoding = Bytes.fromHexString(RAW_EXCLUDE_COMMIT_SEALS_ENCODED_STRING); - final Bytes encoded = bftExtraDataCodec.encodeWithoutCommitSeals(getDecodedExtraData(cms)); - - assertThat(encoded).isEqualTo(expectedRawDecoding); - } - - @Test - public void encodingWithAllShouldIncludeCms() { - final Bytes expectedRawDecoding = Bytes.fromHexString(RAW_ALL_ENCODED_STRING); - final Bytes encoded = bftExtraDataCodec.encode(getDecodedExtraData(cms)); - - assertThat(encoded).isEqualTo(expectedRawDecoding); - } - - /* - When encoding for proposal, we include commit seals and round number, but we ignore the CMS - */ - @Test - public void encodingForCreatingCmsProposal() { - final Bytes expectedRawDecoding = Bytes.fromHexString(RAW_QBFT_EXTRA_DATA); - final Bytes encoded = bftExtraDataCodec.encodeWithoutCms(getDecodedExtraData(cms)); - - assertThat(encoded).isEqualTo(expectedRawDecoding); - } - - /* - When encoding non-pki extra data, we delegate to the regular QBFT encoder - */ - @Test - public void encodingQbftExtraData() { - final Bytes expectedRawDecoding = Bytes.fromHexString(RAW_QBFT_EXTRA_DATA); - final PkiQbftExtraData pkiBftExtraData = getDecodedExtraData(cms); - final BftExtraData bftExtraData = - new BftExtraData( - pkiBftExtraData.getVanityData(), - pkiBftExtraData.getSeals(), - pkiBftExtraData.getVote(), - pkiBftExtraData.getRound(), - pkiBftExtraData.getValidators()); - - final Bytes encoded = bftExtraDataCodec.encode(bftExtraData); - - assertThat(encoded).isEqualTo(expectedRawDecoding); - } - - private static PkiQbftExtraData getDecodedExtraData(final Bytes cms) { - final List
validators = - Arrays.asList(Address.fromHexString("1"), Address.fromHexString("2")); - final Optional vote = Optional.of(Vote.authVote(Address.fromHexString("1"))); - final int round = 0x00FEDCBA; - final List committerSeals = - Arrays.asList( - SIGNATURE_ALGORITHM.get().createSignature(BigInteger.ONE, BigInteger.TEN, (byte) 0), - SIGNATURE_ALGORITHM.get().createSignature(BigInteger.TEN, BigInteger.ONE, (byte) 0)); - - // Create a byte buffer with no data. - final byte[] vanity_bytes = createNonEmptyVanityData(); - final Bytes vanity_data = Bytes.wrap(vanity_bytes); - - return new PkiQbftExtraData(vanity_data, committerSeals, vote, round, validators, cms); - } -} diff --git a/pki/src/test/java/org/hyperledger/besu/pki/cms/CmsCreationAndValidationTest.java b/pki/src/test/java/org/hyperledger/besu/pki/cms/CmsCreationAndValidationTest.java deleted file mode 100644 index 2daf9b576be..00000000000 --- a/pki/src/test/java/org/hyperledger/besu/pki/cms/CmsCreationAndValidationTest.java +++ /dev/null @@ -1,202 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.hyperledger.besu.pki.cms; - -import static org.hyperledger.besu.pki.util.TestCertificateUtils.Algorithm.EC; -import static org.hyperledger.besu.pki.util.TestCertificateUtils.Algorithm.RSA; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import org.hyperledger.besu.pki.util.TestCertificateUtils.Algorithm; - -import java.security.PrivateKey; -import java.security.PublicKey; -import java.security.cert.X509Certificate; - -import org.apache.tuweni.bytes.Bytes; -import org.bouncycastle.cert.jcajce.JcaX509CertificateHolder; -import org.bouncycastle.cms.CMSProcessableByteArray; -import org.bouncycastle.cms.CMSSignedData; -import org.bouncycastle.cms.CMSSignedDataGenerator; -import org.bouncycastle.cms.CMSTypedData; -import org.bouncycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder; -import org.bouncycastle.operator.ContentSigner; -import org.bouncycastle.operator.DigestCalculatorProvider; -import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; -import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.EnumSource; - -public class CmsCreationAndValidationTest { - - private static final CmsTestKeystores rsaTestKeystores = new CmsTestKeystores(RSA); - private static final CmsTestKeystores ecTestKeystores = new CmsTestKeystores(EC); - - private CmsTestKeystores getCmsTestKeystores(final Algorithm algorithm) { - return switch (algorithm) { - case RSA -> rsaTestKeystores; - case EC -> ecTestKeystores; - }; - } - - @ParameterizedTest - @EnumSource(value = Algorithm.class) - public void cmsValidationWithEmptyCmsMessage(final Algorithm algorithm) { - final Bytes data = Bytes.random(32); - - assertFalse(getCmsTestKeystores(algorithm).getCmsValidator().validate(Bytes.EMPTY, data)); - } - - @ParameterizedTest - @EnumSource(value = Algorithm.class) - public void cmsValidationWithTrustedSelfSignedCertificate(final Algorithm algorithm) { - final CmsCreator cmsCreator = - new CmsCreator(getCmsTestKeystores(algorithm).getKeystoreWrapper(), "trusted_selfsigned"); - final Bytes data = Bytes.random(32); - - final Bytes cms = cmsCreator.create(data); - - assertTrue(getCmsTestKeystores(algorithm).getCmsValidator().validate(cms, data)); - } - - @ParameterizedTest - @EnumSource(value = Algorithm.class) - public void cmsValidationWithUntrustedSelfSignedCertificate(final Algorithm algorithm) { - final CmsCreator cmsCreator = - new CmsCreator(getCmsTestKeystores(algorithm).getKeystoreWrapper(), "untrusted_selfsigned"); - final Bytes data = Bytes.random(32); - - final Bytes cms = cmsCreator.create(data); - - assertFalse(getCmsTestKeystores(algorithm).getCmsValidator().validate(cms, data)); - } - - @ParameterizedTest - @EnumSource(value = Algorithm.class) - public void cmsValidationWithTrustedChain(final Algorithm algorithm) { - final CmsCreator cmsCreator = - new CmsCreator(getCmsTestKeystores(algorithm).getKeystoreWrapper(), "trusted"); - final Bytes data = Bytes.random(32); - - final Bytes cms = cmsCreator.create(data); - - assertTrue(getCmsTestKeystores(algorithm).getCmsValidator().validate(cms, data)); - } - - @ParameterizedTest - @EnumSource(value = Algorithm.class) - public void cmsValidationWithUntrustedChain(final Algorithm algorithm) { - final CmsCreator cmsCreator = - new CmsCreator(getCmsTestKeystores(algorithm).getKeystoreWrapper(), "untrusted"); - final Bytes data = Bytes.random(32); - - final Bytes cms = cmsCreator.create(data); - - assertFalse(getCmsTestKeystores(algorithm).getCmsValidator().validate(cms, data)); - } - - @ParameterizedTest - @EnumSource(value = Algorithm.class) - public void cmsValidationWithExpiredCertificate(final Algorithm algorithm) { - final CmsCreator cmsCreator = - new CmsCreator(getCmsTestKeystores(algorithm).getKeystoreWrapper(), "expired"); - final Bytes data = Bytes.random(32); - - final Bytes cms = cmsCreator.create(data); - - assertFalse(getCmsTestKeystores(algorithm).getCmsValidator().validate(cms, data)); - } - - @ParameterizedTest - @EnumSource(value = Algorithm.class) - public void cmsValidationWithRevokedCertificate(final Algorithm algorithm) { - final CmsCreator cmsCreator = - new CmsCreator(getCmsTestKeystores(algorithm).getKeystoreWrapper(), "revoked"); - final Bytes data = Bytes.random(32); - - final Bytes cms = cmsCreator.create(data); - - assertFalse(getCmsTestKeystores(algorithm).getCmsValidator().validate(cms, data)); - } - - @ParameterizedTest - @EnumSource(value = Algorithm.class) - public void cmsValidationWithoutCRLConfigDisablesCRLCheck(final Algorithm algorithm) { - final CmsCreator cmsCreator = - new CmsCreator(getCmsTestKeystores(algorithm).getKeystoreWrapper(), "revoked"); - final Bytes data = Bytes.random(32); - - final Bytes cms = cmsCreator.create(data); - - CmsValidator cmsValidator = getCmsTestKeystores(algorithm).getCmsValidatorWithoutCrl(); - - // Because we don't have a CRL CertStore, revocation is not checked - assertTrue(cmsValidator.validate(cms, data)); - } - - @ParameterizedTest - @EnumSource(value = Algorithm.class) - public void cmsValidationWithWrongSignedData(final Algorithm algorithm) { - final CmsCreator cmsCreator = - new CmsCreator(getCmsTestKeystores(algorithm).getKeystoreWrapper(), "trusted"); - final Bytes otherData = Bytes.random(32); - final Bytes cms = cmsCreator.create(otherData); - - final Bytes expectedData = Bytes.random(32); - assertFalse(getCmsTestKeystores(algorithm).getCmsValidator().validate(cms, expectedData)); - } - - @ParameterizedTest - @EnumSource(value = Algorithm.class) - public void cmsValidationWithInvalidSignature(final Algorithm algorithm) throws Exception { - // Create a CMS message signed with a certificate, but create SignerInfo using another - // certificate to trigger the signature verification to fail. - - final PrivateKey privateKey = - getCmsTestKeystores(algorithm).getKeystoreWrapper().getPrivateKey("trusted"); - final PublicKey publicKey = - getCmsTestKeystores(algorithm).getKeystoreWrapper().getPublicKey("trusted"); - final X509Certificate signerCertificate = - (X509Certificate) - getCmsTestKeystores(algorithm).getKeystoreWrapper().getCertificate("trusted"); - final X509Certificate otherCertificate = - (X509Certificate) - getCmsTestKeystores(algorithm) - .getKeystoreWrapper() - .getCertificate("trusted_selfsigned"); - - final ContentSigner contentSigner = - new JcaContentSignerBuilder(CmsCreator.getPreferredSignatureAlgorithm(publicKey)) - .build(privateKey); - - final CMSSignedDataGenerator cmsGenerator = new CMSSignedDataGenerator(); - cmsGenerator.addCertificate(new JcaX509CertificateHolder(signerCertificate)); - cmsGenerator.addCertificate(new JcaX509CertificateHolder(otherCertificate)); - - final DigestCalculatorProvider digestCalculatorProvider = - new JcaDigestCalculatorProviderBuilder().setProvider("BC").build(); - cmsGenerator.addSignerInfoGenerator( - new JcaSignerInfoGeneratorBuilder(digestCalculatorProvider) - .build(contentSigner, otherCertificate)); - - final Bytes expectedData = Bytes.random(32); - final CMSTypedData cmsData = new CMSProcessableByteArray(expectedData.toArray()); - final CMSSignedData cmsSignedData = cmsGenerator.generate(cmsData, true); - final Bytes cmsBytes = Bytes.wrap(cmsSignedData.getEncoded()); - - assertFalse(getCmsTestKeystores(algorithm).getCmsValidator().validate(cmsBytes, expectedData)); - } -} diff --git a/pki/src/test/java/org/hyperledger/besu/pki/cms/CmsTestKeystores.java b/pki/src/test/java/org/hyperledger/besu/pki/cms/CmsTestKeystores.java deleted file mode 100644 index 3a2d4c04f8f..00000000000 --- a/pki/src/test/java/org/hyperledger/besu/pki/cms/CmsTestKeystores.java +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Copyright Hyperledger Besu Contributors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.pki.cms; - -import static org.hyperledger.besu.pki.util.TestCertificateUtils.createCRL; -import static org.hyperledger.besu.pki.util.TestCertificateUtils.createKeyPair; -import static org.hyperledger.besu.pki.util.TestCertificateUtils.createSelfSignedCertificate; -import static org.hyperledger.besu.pki.util.TestCertificateUtils.issueCertificate; - -import org.hyperledger.besu.pki.keystore.KeyStoreWrapper; -import org.hyperledger.besu.pki.keystore.SoftwareKeyStoreWrapper; -import org.hyperledger.besu.pki.util.TestCertificateUtils.Algorithm; - -import java.security.KeyPair; -import java.security.KeyStore; -import java.security.cert.Certificate; -import java.security.cert.X509CRL; -import java.security.cert.X509Certificate; -import java.time.Instant; -import java.time.temporal.ChronoUnit; -import java.util.Collections; -import java.util.List; -import java.util.Set; - -public class CmsTestKeystores { - private KeyStore keystore; - private KeyStore truststore; - private List CRLs; - - private KeyStoreWrapper keystoreWrapper; - private KeyStoreWrapper truststoreWrapper; - private KeyStoreWrapper truststoreWrapperWithoutCrl; - private CmsValidator cmsValidator; - private CmsValidator cmsValidatorWithoutCrl; - - public CmsTestKeystores(final Algorithm algorithm) { - try { - init(algorithm); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - public void init(final Algorithm algorithm) throws Exception { - final Instant notBefore = Instant.now().minus(1, ChronoUnit.DAYS); - final Instant notAfter = Instant.now().plus(1, ChronoUnit.DAYS); - - /* - Create self-signed certificate - */ - final KeyPair selfsignedKeyPair = createKeyPair(algorithm); - final X509Certificate selfsignedCertificate = - createSelfSignedCertificate("selfsigned", notBefore, notAfter, selfsignedKeyPair); - - /* - Create trusted chain (ca -> interca -> partneraca -> partneravalidator) - */ - final KeyPair caKeyPair = createKeyPair(algorithm); - final X509Certificate caCertificate = - createSelfSignedCertificate("ca", notBefore, notAfter, caKeyPair); - - final KeyPair interCAKeyPair = createKeyPair(algorithm); - final X509Certificate interCACertificate = - issueCertificate( - caCertificate, caKeyPair, "interca", notBefore, notAfter, interCAKeyPair, true); - - final KeyPair partnerACAPair = createKeyPair(algorithm); - final X509Certificate partnerACACertificate = - issueCertificate( - interCACertificate, - interCAKeyPair, - "partneraca", - notBefore, - notAfter, - partnerACAPair, - true); - - final KeyPair parterAValidatorKeyPair = createKeyPair(algorithm); - final X509Certificate partnerAValidatorCertificate = - issueCertificate( - partnerACACertificate, - partnerACAPair, - "partneravalidator", - notBefore, - notAfter, - parterAValidatorKeyPair, - false); - - /* - Create expired certificate - */ - final KeyPair expiredKeyPair = createKeyPair(algorithm); - final X509Certificate expiredCertificate = - issueCertificate( - caCertificate, - caKeyPair, - "expired", - notBefore, - notBefore.plus(1, ChronoUnit.SECONDS), - expiredKeyPair, - true); - - /* - Create revoked and revoked certificates - */ - final KeyPair revokedKeyPair = createKeyPair(algorithm); - final X509Certificate revokedCertificate = - issueCertificate( - caCertificate, caKeyPair, "revoked", notBefore, notAfter, revokedKeyPair, true); - - /* - Create untrusted chain (untrusted_selfsigned -> unstrusted_partner) - */ - final KeyPair untrustedSelfSignedKeyPair = createKeyPair(algorithm); - final X509Certificate untrustedSelfsignedCertificate = - createSelfSignedCertificate( - "untrusted_selfsigned", notBefore, notAfter, untrustedSelfSignedKeyPair); - - final KeyPair untrustedIntermediateKeyPair = createKeyPair(algorithm); - final X509Certificate untrustedIntermediateCertificate = - issueCertificate( - untrustedSelfsignedCertificate, - untrustedSelfSignedKeyPair, - "unstrusted_partner", - notBefore, - notAfter, - untrustedIntermediateKeyPair, - true); - - /* - Create truststore wrapper with 3 trusted certificates: 'ca', 'interca' and 'selfsigned' - */ - truststore = KeyStore.getInstance("PKCS12"); - truststore.load(null, null); - - truststore.setCertificateEntry("ca", caCertificate); - truststore.setCertificateEntry("interca", interCACertificate); - truststore.setCertificateEntry("selfsigned", selfsignedCertificate); - - /* - Create keystore with certificates used in tests - */ - keystore = KeyStore.getInstance("PKCS12"); - keystore.load(null, null); - - keystore.setKeyEntry( - "trusted_selfsigned", - selfsignedKeyPair.getPrivate(), - "".toCharArray(), - new Certificate[] {selfsignedCertificate}); - keystore.setKeyEntry( - "untrusted_selfsigned", - untrustedSelfSignedKeyPair.getPrivate(), - "".toCharArray(), - new Certificate[] {untrustedSelfsignedCertificate}); - keystore.setKeyEntry( - "expired", - expiredKeyPair.getPrivate(), - "".toCharArray(), - new Certificate[] {expiredCertificate}); - keystore.setKeyEntry( - "revoked", - revokedKeyPair.getPrivate(), - "".toCharArray(), - new Certificate[] {revokedCertificate}); - keystore.setKeyEntry( - "trusted", - parterAValidatorKeyPair.getPrivate(), - "".toCharArray(), - new Certificate[] {partnerAValidatorCertificate, partnerACACertificate}); - keystore.setKeyEntry( - "untrusted", - untrustedIntermediateKeyPair.getPrivate(), - "".toCharArray(), - new Certificate[] {untrustedIntermediateCertificate, untrustedSelfsignedCertificate}); - - /* - Create CRLs for all CA certificates (mostly empty, only ca has one revoked certificate) - */ - final X509CRL caCRL = createCRL(caCertificate, caKeyPair, Set.of(revokedCertificate)); - final X509CRL intercaCRL = - createCRL(interCACertificate, interCAKeyPair, Collections.emptyList()); - final X509CRL partnerACACRL = - createCRL(partnerACACertificate, partnerACAPair, Collections.emptyList()); - final X509CRL selfsignedCRL = - createCRL(selfsignedCertificate, selfsignedKeyPair, Collections.emptyList()); - CRLs = List.of(caCRL, intercaCRL, partnerACACRL, selfsignedCRL); - - keystoreWrapper = new SoftwareKeyStoreWrapper(null, keystore, ""); - - truststoreWrapper = new SoftwareKeyStoreWrapper(CRLs, truststore, ""); - - truststoreWrapperWithoutCrl = new SoftwareKeyStoreWrapper(null, truststore, ""); - - cmsValidator = new CmsValidator(truststoreWrapper); - - cmsValidatorWithoutCrl = new CmsValidator(truststoreWrapperWithoutCrl); - } - - public KeyStore getKeystore() { - return keystore; - } - - public KeyStore getTruststore() { - return truststore; - } - - public List getCRLs() { - return CRLs; - } - - public KeyStoreWrapper getKeystoreWrapper() { - return keystoreWrapper; - } - - public KeyStoreWrapper getTruststoreWrapper() { - return truststoreWrapper; - } - - public CmsValidator getCmsValidator() { - return cmsValidator; - } - - public KeyStoreWrapper getTruststoreWrapperWithoutCrl() { - return truststoreWrapperWithoutCrl; - } - - public CmsValidator getCmsValidatorWithoutCrl() { - return cmsValidatorWithoutCrl; - } -} diff --git a/pki/src/test/java/org/hyperledger/besu/pki/keystore/BaseKeyStoreFileWrapperTest.java b/pki/src/test/java/org/hyperledger/besu/pki/keystore/BaseKeyStoreFileWrapperTest.java deleted file mode 100644 index 3cbeff8985a..00000000000 --- a/pki/src/test/java/org/hyperledger/besu/pki/keystore/BaseKeyStoreFileWrapperTest.java +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.pki.keystore; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; - -import java.nio.file.Path; -import java.security.cert.Certificate; - -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.MethodSource; - -public abstract class BaseKeyStoreFileWrapperTest { - protected static final String KEYSTORE_VALID_KEY_ALIAS = "partner1client1"; - protected static final String KEYSTORE_INVALID_KEY_ALIAS = "partner1clientinvalid"; - protected static final String TRUSTSTORE_VALID_CERTIFICATE_ALIAS = "interca"; - protected static final String TRUSTSTORE_INVALID_CERTIFICATE_ALIAS = "interca-invalid"; - - protected static Path toPath(final String path) throws Exception { - return null == path - ? null - : Path.of(BaseKeyStoreFileWrapperTest.class.getResource(path).toURI()); - } - - @ParameterizedTest - @MethodSource("data") - public void getPublicKey_WithValidAlias_ReturnsExpectedValue( - final KeyStoreWrapperTestParameter keyStoreWrapperTestParameter) { - assertNotNull( - keyStoreWrapperTestParameter.keyStoreWrapper.getPublicKey(KEYSTORE_VALID_KEY_ALIAS)); - } - - @ParameterizedTest - @MethodSource("data") - public void getPublicKey_WithInvalidAlias_ReturnsExpectedValue( - final KeyStoreWrapperTestParameter keyStoreWrapperTestParameter) { - assertNull( - keyStoreWrapperTestParameter.keyStoreWrapper.getPublicKey(KEYSTORE_INVALID_KEY_ALIAS)); - } - - @ParameterizedTest - @MethodSource("data") - public void getPrivateKey_WithValidAlias_ReturnsExpectedValue( - final KeyStoreWrapperTestParameter keyStoreWrapperTestParameter) { - assertNotNull( - keyStoreWrapperTestParameter.keyStoreWrapper.getPrivateKey(KEYSTORE_VALID_KEY_ALIAS), - "Private key is not null"); - } - - @ParameterizedTest - @MethodSource("data") - public void getPrivateKey_WithInvalidAlias_ReturnsExpectedValue( - final KeyStoreWrapperTestParameter keyStoreWrapperTestParameter) { - assertNull( - keyStoreWrapperTestParameter.keyStoreWrapper.getPrivateKey(KEYSTORE_INVALID_KEY_ALIAS), - "Private key is null"); - } - - @ParameterizedTest - @MethodSource("data") - public void getCertificate_WithValidAlias_ReturnsExpectedValue( - final KeyStoreWrapperTestParameter keyStoreWrapperTestParameter) { - assertNotNull( - keyStoreWrapperTestParameter.keyStoreWrapper.getCertificate(KEYSTORE_VALID_KEY_ALIAS), - "Certificate is not null"); - } - - @ParameterizedTest - @MethodSource("data") - public void getCertificate_WithInvalidAlias_ReturnsExpectedValue( - final KeyStoreWrapperTestParameter keyStoreWrapperTestParameter) { - assertNull( - keyStoreWrapperTestParameter.keyStoreWrapper.getCertificate(KEYSTORE_INVALID_KEY_ALIAS), - "Certificate is null"); - } - - @ParameterizedTest - @MethodSource("data") - public void getCertificateChain_WithValidAlias_ReturnsExpectedValue( - final KeyStoreWrapperTestParameter keyStoreWrapperTestParameter) { - assertNotNull( - keyStoreWrapperTestParameter.keyStoreWrapper.getCertificateChain(KEYSTORE_VALID_KEY_ALIAS), - "Certificate chain is not null"); - } - - @ParameterizedTest - @MethodSource("data") - public void getCertificateChain_WithInvalidAlias_ReturnsExpectedValue( - final KeyStoreWrapperTestParameter keyStoreWrapperTestParameter) { - assertNull( - keyStoreWrapperTestParameter.keyStoreWrapper.getCertificateChain( - KEYSTORE_INVALID_KEY_ALIAS), - "Certificate is null"); - } - - @ParameterizedTest - @MethodSource("data") - public void getCertificate_FromTruststore_WithValidAlias_ReturnsExpectedValue( - final KeyStoreWrapperTestParameter keyStoreWrapperTestParameter) { - final Certificate certificate = - keyStoreWrapperTestParameter.keyStoreWrapper.getCertificate( - TRUSTSTORE_VALID_CERTIFICATE_ALIAS); - if (keyStoreWrapperTestParameter.keystoreWrapperConfiguredWithTruststore) { - assertNotNull(certificate, "Certificate is not null"); - } else { - assertNull(certificate, "Certificate is null"); - } - } - - @ParameterizedTest - @MethodSource("data") - public void getCertificate_FromTruststore_WithInvalidAlias_ReturnsExpectedValue( - final KeyStoreWrapperTestParameter keyStoreWrapperTestParameter) { - assertNull( - keyStoreWrapperTestParameter.keyStoreWrapper.getPrivateKey( - TRUSTSTORE_INVALID_CERTIFICATE_ALIAS), - "Certificate is null"); - } - - @ParameterizedTest - @MethodSource("data") - public void getCRLS_Check(final KeyStoreWrapperTestParameter keyStoreWrapperTestParameter) { - assertNotNull(keyStoreWrapperTestParameter.keyStoreWrapper.getCRLs(), "CRLs is not null"); - assertEquals( - keyStoreWrapperTestParameter.keyStoreWrapper.getCRLs().size(), 2, "CRLs size matches"); - } - - public static class KeyStoreWrapperTestParameter { - public String keyStoreWrapperDescription; - public boolean keystoreWrapperConfiguredWithTruststore; - public KeyStoreWrapper keyStoreWrapper; - - public KeyStoreWrapperTestParameter( - final String keyStoreWrapperDescription, - final boolean keystoreWrapperConfiguredWithTruststore, - final KeyStoreWrapper keyStoreWrapper) { - this.keyStoreWrapperDescription = keyStoreWrapperDescription; - this.keystoreWrapperConfiguredWithTruststore = keystoreWrapperConfiguredWithTruststore; - this.keyStoreWrapper = keyStoreWrapper; - } - } -} diff --git a/pki/src/test/java/org/hyperledger/besu/pki/keystore/CryptoTestUtil.java b/pki/src/test/java/org/hyperledger/besu/pki/keystore/CryptoTestUtil.java deleted file mode 100644 index 4176cac0faa..00000000000 --- a/pki/src/test/java/org/hyperledger/besu/pki/keystore/CryptoTestUtil.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.pki.keystore; - -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.util.Optional; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class CryptoTestUtil { - - private static final Logger LOG = LoggerFactory.getLogger(CryptoTestUtil.class); - - private CryptoTestUtil() {} - - public static boolean isNSSLibInstalled() { - try { - final String nssLibPath = getNSSLibPath(); - return nssLibPath != null && !nssLibPath.trim().isEmpty(); - } catch (final Exception e) { - LOG.info("NSS library does not seem to be installed!", e); - } - return false; - } - - public static String getNSSLibPath() throws IOException, InterruptedException { - String nssLibPath = ""; - final String centOS_nssPathCmd = - "whereis libnssdbm3 | grep -o \"\\/.*libnssdbm3\\.[0-9a-z]* \" | sed 's/\\/libnssdbm3.*//g'"; - final String debian_nssPathCmd = - "whereis libnss3 | grep -o \".*libnss3.[0-9a-z]\" | sed 's/lib.* \\(\\/.*\\)\\/lib.*/\\1/'"; - final String macOS_nssPathCmd = "dirname `which certutil` | sed 's/bin/lib/g'"; - - nssLibPath = executeSystemCmd(centOS_nssPathCmd).orElse(nssLibPath); - LOG.info("centOS_nssPathCmd: {}", nssLibPath); - if ("".equals(nssLibPath)) { - nssLibPath = executeSystemCmd(debian_nssPathCmd).orElse(nssLibPath); - LOG.info("debian_nssPathCmd: {}", nssLibPath); - } - if ("".equals(nssLibPath)) { - nssLibPath = executeSystemCmd(macOS_nssPathCmd).orElse(nssLibPath); - LOG.info("macOS_nssPathCmd: {}", nssLibPath); - } - LOG.info("Detected NSS library path: {}", nssLibPath); - return nssLibPath; - } - - public static Optional executeSystemCmd(final String cmd) - throws IOException, InterruptedException { - final Process p = Runtime.getRuntime().exec(new String[] {"/bin/sh", "-c", cmd}); - try { - if (p.waitFor() == 0) { - final java.util.Scanner s = - new java.util.Scanner(p.getInputStream(), StandardCharsets.UTF_8.name()) - .useDelimiter("\\A"); - if (s.hasNext()) { - return Optional.of(s.next().replace("\r", "").replace("\n", "")); - } - } - } finally { - if (p != null) { - p.destroy(); - } - } - return Optional.empty(); - } -} diff --git a/pki/src/test/java/org/hyperledger/besu/pki/keystore/HardwareKeyStoreFileWrapperTest.java b/pki/src/test/java/org/hyperledger/besu/pki/keystore/HardwareKeyStoreFileWrapperTest.java deleted file mode 100644 index 31eb03126c5..00000000000 --- a/pki/src/test/java/org/hyperledger/besu/pki/keystore/HardwareKeyStoreFileWrapperTest.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.pki.keystore; - -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assumptions.assumeTrue; - -import org.hyperledger.besu.pki.PkiException; - -import java.nio.file.Path; -import java.security.Provider; -import java.security.Security; -import java.util.Collection; -import java.util.List; -import java.util.Optional; -import java.util.stream.Stream; - -import org.junit.jupiter.api.Assumptions; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.condition.OS; - -public class HardwareKeyStoreFileWrapperTest extends BaseKeyStoreFileWrapperTest { - - private static final String config = "/keystore/partner1client1/nss.cfg"; - private static final String crl = "/keystore/partner1client1/crl.pem"; - private static final String configName = "NSScrypto-partner1client1"; - private static final String validKeystorePassword = "test123"; - private static KeyStoreWrapperTestParameter keyStoreWrapperTestParameter; - - @BeforeAll - public static void setup() { - keyStoreWrapperTestParameter = - new KeyStoreWrapperTestParameter( - "HardwareKeyStoreWrapper[PKCS11 keystore/truststore]", - true, - CryptoTestUtil.isNSSLibInstalled() ? getHardwareKeyStoreWrapper(configName) : null); - } - - public static Collection data() { - return List.of(keyStoreWrapperTestParameter); - } - - private static KeyStoreWrapper getHardwareKeyStoreWrapper(final String cfgName) { - try { - final Path path = toPath(config); - final Path crlPath = toPath(crl); - final Optional existingProvider = - Stream.of(Security.getProviders()) - .filter(p -> p.getName().equals("SunPKCS11" + cfgName)) - .findAny(); - return existingProvider - .map(provider -> new HardwareKeyStoreWrapper(validKeystorePassword, provider, crlPath)) - .orElseGet(() -> new HardwareKeyStoreWrapper(validKeystorePassword, path, crlPath)); - } catch (final Exception e) { - // nss3 is difficult to setup on mac, don't let it break unit tests for dev machines. - Assumptions.assumeFalse( - OS.MAC.isCurrentOs(), - "Failed to initialize hardware keystore: " + e.getLocalizedMessage()); - // Not a mac, probably a production build. Full failure. - throw new PkiException("Failed to initialize hardware keystore", e); - } - } - - @BeforeEach - public void beforeMethod() { - assumeTrue( - CryptoTestUtil.isNSSLibInstalled(), - "Test ignored due to NSS library not being installed/detected."); - } - - @Test - public void getPkcs11Provider() throws Exception { - final HardwareKeyStoreWrapper sut = - (HardwareKeyStoreWrapper) getHardwareKeyStoreWrapper(configName); - assertThrows( - IllegalArgumentException.class, () -> sut.getPkcs11ProviderForConfig("no-library")); - } - - @Test - public void init_keystorePassword_config() throws Exception { - new HardwareKeyStoreWrapper(validKeystorePassword, toPath(config), toPath(crl)); - } - - @Test - public void init_keystorePassword_config_invalid() throws Exception { - final String config = "invalid"; - assertThrows( - NullPointerException.class, - () -> new HardwareKeyStoreWrapper(validKeystorePassword, toPath(config), toPath(crl))); - } - - @Test - public void init_keystorePassword_config_missing_pw() throws Exception { - assertThrows( - PkiException.class, () -> new HardwareKeyStoreWrapper(null, toPath(config), toPath(crl))); - } - - @Test - public void init_keystorePassword_provider_missing_pw() throws Exception { - final Provider p = null; - assertThrows( - PkiException.class, - () -> new HardwareKeyStoreWrapper(validKeystorePassword, p, toPath(crl))); - } -} diff --git a/pki/src/test/java/org/hyperledger/besu/pki/keystore/HardwareKeyStoreWrapperTest.java b/pki/src/test/java/org/hyperledger/besu/pki/keystore/HardwareKeyStoreWrapperTest.java deleted file mode 100644 index 1d72a0537f4..00000000000 --- a/pki/src/test/java/org/hyperledger/besu/pki/keystore/HardwareKeyStoreWrapperTest.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.hyperledger.besu.pki.keystore; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.mockito.Mockito.when; - -import java.security.KeyStore; -import java.security.PrivateKey; -import java.security.PublicKey; -import java.security.cert.Certificate; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -@ExtendWith(MockitoExtension.class) -public class HardwareKeyStoreWrapperTest { - - private static final String KEY_ALIAS = "keyalias"; - private static final String CERTIFICATE_ALIAS = "certalias"; - private static final char[] PASSWORD = "password".toCharArray(); - - @Mock private KeyStore keyStore; - @Mock private PrivateKey privateKey; - @Mock private PublicKey publicKey; - @Mock private Certificate certificate; - - private HardwareKeyStoreWrapper keyStoreWrapper; - - @BeforeEach - public void before() { - keyStoreWrapper = new HardwareKeyStoreWrapper(null, keyStore, new String(PASSWORD)); - } - - @Test - public void getPrivateKey() throws Exception { - when(keyStore.getKey(KEY_ALIAS, PASSWORD)).thenReturn(privateKey); - - assertNotNull(keyStoreWrapper.getPrivateKey(KEY_ALIAS)); - } - - @Test - public void getPublicKey() throws Exception { - // Get public key from certificate - when(keyStore.getCertificate(KEY_ALIAS)).thenReturn(certificate); - when(certificate.getPublicKey()).thenReturn(publicKey); - - assertNotNull(keyStoreWrapper.getPublicKey(KEY_ALIAS)); - } - - @Test - public void getCertificate() throws Exception { - when(keyStore.getCertificate(CERTIFICATE_ALIAS)).thenReturn(certificate); - - assertNotNull(keyStoreWrapper.getCertificate(CERTIFICATE_ALIAS)); - } - - @Test - public void getCertificateChain() throws Exception { - when(keyStore.getCertificateChain(CERTIFICATE_ALIAS)) - .thenReturn(new Certificate[] {certificate}); - - assertEquals(keyStoreWrapper.getCertificateChain(CERTIFICATE_ALIAS).length, 1); - } -} diff --git a/pki/src/test/java/org/hyperledger/besu/pki/keystore/SoftwareKeyStoreFileWrapperTest.java b/pki/src/test/java/org/hyperledger/besu/pki/keystore/SoftwareKeyStoreFileWrapperTest.java deleted file mode 100644 index 2550d070f72..00000000000 --- a/pki/src/test/java/org/hyperledger/besu/pki/keystore/SoftwareKeyStoreFileWrapperTest.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.pki.keystore; - -import org.hyperledger.besu.pki.PkiException; - -import java.nio.file.Path; -import java.util.Arrays; -import java.util.Collection; - -public class SoftwareKeyStoreFileWrapperTest extends BaseKeyStoreFileWrapperTest { - - private static final String p12KeyStore = "/keystore/partner1client1/keys.p12"; - private static final String jksKeyStore = "/keystore/partner1client1/keystore.jks"; - private static final String trustStore = "/keystore/partner1client1/truststore.jks"; - private static final String crl = "/keystore/partner1client1/crl.pem"; - private static final String validKeystorePassword = "test123"; - - public static Collection data() { - return Arrays.asList( - new KeyStoreWrapperTestParameter( - "SoftwareKeyStoreWrapper[PKCS12 keystore only]", - false, - getPKCS12SoftwareKeyStoreWrapper()), - new KeyStoreWrapperTestParameter( - "SoftwareKeyStoreWrapper[JKS keystore only]", - false, - getJKSSoftwareKeyStoreWrapper(false)), - new KeyStoreWrapperTestParameter( - "SoftwareKeyStoreWrapper[JKS keystore/truststore]", - true, - getJKSSoftwareKeyStoreWrapper(true))); - } - - private static KeyStoreWrapper getPKCS12SoftwareKeyStoreWrapper() { - try { - return new SoftwareKeyStoreWrapper( - KeyStoreWrapper.KEYSTORE_TYPE_PKCS12, - toPath(p12KeyStore), - validKeystorePassword, - toPath(crl)); - } catch (final Exception e) { - throw new PkiException("Failed to initialize software keystore", e); - } - } - - private static KeyStoreWrapper getJKSSoftwareKeyStoreWrapper(final boolean setupTruststore) { - try { - final Path keystoreLocation = toPath(jksKeyStore); - if (setupTruststore) { - final Path truststoreLocation = toPath(trustStore); - // password shouldn't be needed for retrieving certificate from truststore - return new SoftwareKeyStoreWrapper( - KeyStoreWrapper.KEYSTORE_TYPE_JKS, - keystoreLocation, - validKeystorePassword, - KeyStoreWrapper.KEYSTORE_TYPE_JKS, - truststoreLocation, - null, - toPath(crl)); - } - return new SoftwareKeyStoreWrapper( - KeyStoreWrapper.KEYSTORE_TYPE_JKS, keystoreLocation, validKeystorePassword, toPath(crl)); - } catch (final Exception e) { - throw new PkiException("Failed to initialize software keystore", e); - } - } -} diff --git a/pki/src/test/java/org/hyperledger/besu/pki/keystore/SoftwareKeyStoreWrapperTest.java b/pki/src/test/java/org/hyperledger/besu/pki/keystore/SoftwareKeyStoreWrapperTest.java deleted file mode 100644 index 8f7f8164bc8..00000000000 --- a/pki/src/test/java/org/hyperledger/besu/pki/keystore/SoftwareKeyStoreWrapperTest.java +++ /dev/null @@ -1,198 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.hyperledger.besu.pki.keystore; - -import static org.hyperledger.besu.pki.keystore.KeyStoreWrapper.KEYSTORE_TYPE_PKCS12; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import java.nio.file.Path; -import java.security.KeyStore; -import java.security.PrivateKey; -import java.security.PublicKey; -import java.security.cert.Certificate; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -@ExtendWith(MockitoExtension.class) -public class SoftwareKeyStoreWrapperTest { - - private static final String KEY_ALIAS = "keyalias"; - private static final String CERTIFICATE_ALIAS = "certalias"; - private static final char[] PASSWORD = "password".toCharArray(); - - private SoftwareKeyStoreWrapper keyStoreWrapper; - - @Mock private KeyStore keyStore; - @Mock private KeyStore trustStore; - @Mock private PrivateKey privateKey; - @Mock private PublicKey publicKey; - @Mock private Certificate certificate; - - @BeforeEach - public void before() { - keyStoreWrapper = new SoftwareKeyStoreWrapper(keyStore, new String(PASSWORD), null, ""); - } - - @Test - public void getPrivateKey() throws Exception { - when(keyStore.containsAlias(KEY_ALIAS)).thenReturn(true); - when(keyStore.getKey(KEY_ALIAS, PASSWORD)).thenReturn(privateKey); - - assertNotNull(keyStoreWrapper.getPrivateKey(KEY_ALIAS)); - } - - @Test - public void getPrivateKeyCaching() throws Exception { - when(keyStore.containsAlias(KEY_ALIAS)).thenReturn(true); - when(keyStore.getKey(KEY_ALIAS, PASSWORD)).thenReturn(privateKey); - - keyStoreWrapper.getPrivateKey(KEY_ALIAS); - keyStoreWrapper.getPrivateKey(KEY_ALIAS); - - verify(keyStore, times(1)).getKey(eq(KEY_ALIAS), eq(PASSWORD)); - } - - @Test - public void getPrivateKeyFallbackToTrustStore() throws Exception { - keyStoreWrapper = - new SoftwareKeyStoreWrapper( - keyStore, new String(PASSWORD), trustStore, new String(PASSWORD)); - - when(keyStore.containsAlias(KEY_ALIAS)).thenReturn(false); - when(trustStore.containsAlias(KEY_ALIAS)).thenReturn(true); - when(trustStore.getKey(KEY_ALIAS, PASSWORD)).thenReturn(privateKey); - - assertNotNull(keyStoreWrapper.getPrivateKey(KEY_ALIAS)); - - verify(trustStore).getKey(eq(KEY_ALIAS), eq(PASSWORD)); - } - - @Test - public void getPublicKey() throws Exception { - when(keyStore.containsAlias(KEY_ALIAS)).thenReturn(true); - when(keyStore.getKey(KEY_ALIAS, PASSWORD)).thenReturn(publicKey); - - assertNotNull(keyStoreWrapper.getPublicKey(KEY_ALIAS)); - } - - @Test - public void getPublicKeyCaching() throws Exception { - when(keyStore.containsAlias(KEY_ALIAS)).thenReturn(true); - when(keyStore.getKey(KEY_ALIAS, PASSWORD)).thenReturn(publicKey); - - keyStoreWrapper.getPublicKey(KEY_ALIAS); - keyStoreWrapper.getPublicKey(KEY_ALIAS); - - verify(keyStore, times(1)).getKey(eq(KEY_ALIAS), eq(PASSWORD)); - } - - @Test - public void getPublicKeyFallbackToTrustStore() throws Exception { - keyStoreWrapper = - new SoftwareKeyStoreWrapper( - keyStore, new String(PASSWORD), trustStore, new String(PASSWORD)); - - when(keyStore.containsAlias(KEY_ALIAS)).thenReturn(false); - when(trustStore.containsAlias(KEY_ALIAS)).thenReturn(true); - when(trustStore.getKey(KEY_ALIAS, PASSWORD)).thenReturn(publicKey); - - assertNotNull(keyStoreWrapper.getPublicKey(KEY_ALIAS)); - - verify(trustStore).getKey(eq(KEY_ALIAS), eq(PASSWORD)); - } - - @Test - public void getCertificate() throws Exception { - when(keyStore.getCertificate(CERTIFICATE_ALIAS)).thenReturn(certificate); - - assertNotNull(keyStoreWrapper.getCertificate(CERTIFICATE_ALIAS)); - } - - @Test - public void getCertificateCaching() throws Exception { - when(keyStore.getCertificate(CERTIFICATE_ALIAS)).thenReturn(certificate); - - keyStoreWrapper.getCertificate(CERTIFICATE_ALIAS); - keyStoreWrapper.getCertificate(CERTIFICATE_ALIAS); - - verify(keyStore, times(1)).getCertificate(eq(CERTIFICATE_ALIAS)); - } - - @Test - public void getCertificateFallbackToTrustStore() throws Exception { - keyStoreWrapper = - new SoftwareKeyStoreWrapper( - keyStore, new String(PASSWORD), trustStore, new String(PASSWORD)); - - when(keyStore.getCertificate(CERTIFICATE_ALIAS)).thenReturn(null); - when(trustStore.getCertificate(CERTIFICATE_ALIAS)).thenReturn(certificate); - - assertNotNull(keyStoreWrapper.getCertificate(CERTIFICATE_ALIAS)); - - verify(trustStore).getCertificate(eq(CERTIFICATE_ALIAS)); - } - - @Test - public void getCertificateChain() throws Exception { - when(keyStore.getCertificateChain(CERTIFICATE_ALIAS)) - .thenReturn(new Certificate[] {certificate}); - - assertEquals(keyStoreWrapper.getCertificateChain(CERTIFICATE_ALIAS).length, 1); - } - - @Test - public void getCertificateChainFallbackToTrustStore() throws Exception { - keyStoreWrapper = - new SoftwareKeyStoreWrapper( - keyStore, new String(PASSWORD), trustStore, new String(PASSWORD)); - - when(keyStore.getCertificateChain(CERTIFICATE_ALIAS)).thenReturn(null); - when(trustStore.getCertificateChain(CERTIFICATE_ALIAS)) - .thenReturn(new Certificate[] {certificate}); - - assertEquals(keyStoreWrapper.getCertificateChain(CERTIFICATE_ALIAS).length, 1); - - verify(trustStore).getCertificateChain(eq(CERTIFICATE_ALIAS)); - } - - @Test - public void loadKeyStoreFromFile() { - SoftwareKeyStoreWrapper loadedKeyStore = - new SoftwareKeyStoreWrapper( - KEYSTORE_TYPE_PKCS12, - Path.of("src/test/resources/keystore/keystore"), - "validator", - KEYSTORE_TYPE_PKCS12, - Path.of("src/test/resources/keystore/keystore"), - "validator", - null); - - assertNotNull(loadedKeyStore.getPublicKey("validator")); - assertNotNull(loadedKeyStore.getPrivateKey("validator")); - assertNotNull(loadedKeyStore.getCertificate("validator")); - // CA -> INTERCA -> PARTNERACA -> VALIDATOR - assertEquals(loadedKeyStore.getCertificateChain("validator").length, 4); - } -} diff --git a/pki/src/test/resources/keystore/partner1client1/keys.p12 b/pki/src/test/resources/keystore/partner1client1/keys.p12 deleted file mode 100644 index fb3d451add6270cdd21f90f3a8636bf6a53f9249..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6068 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 diff --git a/pki/src/test/resources/keystore/partner1client1/keystore.jks b/pki/src/test/resources/keystore/partner1client1/keystore.jks deleted file mode 100644 index a51a778eff98c923cc099d529d66f134e80a932d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6817 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 diff --git a/pki/src/test/resources/keystore/partner1client1/nss.cfg b/pki/src/test/resources/keystore/partner1client1/nss.cfg deleted file mode 100644 index 6cd0f7eb876..00000000000 --- a/pki/src/test/resources/keystore/partner1client1/nss.cfg +++ /dev/null @@ -1,6 +0,0 @@ - -name = NSScrypto-partner1client1 -nssSecmodDirectory = ./src/test/resources/keystore/partner1client1/nssdb -nssDbMode = readOnly -nssModule = keystore - diff --git a/pki/src/test/resources/keystore/partner1client1/truststore.jks b/pki/src/test/resources/keystore/partner1client1/truststore.jks deleted file mode 100644 index fcfd04602193433388053846383605f0eeb8aa64..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3135 zcmc(hcTf}C9>=puh?LNT2*RZ|scvHEybDSb1f@#7SP-NrAWdorp(%1jDGJO50R<^a zmtqhQq^L+JiZrE)fB^ysNGRTba^?A)@y)z9;~zU`f9H2*cISJ}=d-&py)g}eK%le> zwlzZSPeCAn|9cOpF@(-iP99XIbp}BKtREym8`5D=01D;QCMoty%tTkA3Q!qLVGk;~ zx*R+}W(0#&C@%s?~;hlj2bPyN;V1Dfj5u=xu&~Bj#grRg}!+V6o~S|jrC*fEAYQ1;%DK;pHg&23SycZQPxkDFsc%k ze5gx;*()D=T>G_C+OkqwT8HOP3X{~4pG)DInE^O5tG|Fx@1-HhqpXrIYQ4hF#g#;1 zuCa{=6~Csw7E7wM?Q79}k$IVlu+C3kUEigPFM&m{Ts(F=zdr|XxR1w}2jOP+Mv()l zbEq(9sgIRc%OCRA9UQ52oeFlw7Rf&Dh&r(XZ(XOXa}pnXXsEi&Y5Q!s z2zP;9CxhE=DK`QYATOpKE1>r94R-0H1UsWx}#1Iu$=&`*o@hhrj=COa9T1JYkVKkas9xy|sm zZcQtmnKJ>(^2LqT^f6iP5)@2H2Eo9T%ORk(ocB-_q-mvAd6x$hsc^L8x(oi^V41L- zy|x6R{Yhmm#8pca`S|&x21vt$kbpiTb*V#kxkafj(rV_Z7o_{HX=}|CONU3L?Von+ z1x+mbNM=`t@TL1dq&WuU3hiZBuZqd!Wy$>P5RwMbD80nZvZBx~liq1yq|{q_e~6C@ zl&%`QL$($;yG8ykXE$#L&u#qSqTleJq2WJ8!@u(@{>Na0BGVC#(Pb9-1=lC9gcM9c z`o4?x7vuGF{Qb7I^FQf{4P^PEr|t02f*}7+GqHaSb%&aMhJJCCc3zKN3<~-dWpr@C zQ1Ysl_AM!0f_YKfWgwFtX*5;a-UusR{m(>OD=Q>gfy^~v8E11{ojkA{Um zix;o?IxV+EcG6mbs?{{_&kCUXyzRl%+^RnpQ3EZ$)u-VX) zPHWsvMX98<%LX#t>y&C+je6R;*I99V_MFBaW)~BaB89jznVQ-ot#A$rlbZL#EG{p9 zjH|!Ddo96YL0bu)`9#A&lf-$eREJLh^YT?ikWl7v&5TERu3yl11kdb1e+^+pimx+S z7|~4#-N%?pR&8lu`8oQ#|3RM~M9|QO0>IXO@v&~|08aasMSgc|w`|}LF4$qtqG{BW zVTkEaJP^E`uX191a70ED z=6&dyv*Ya1R%WX+W1SM!Y&!7ycwfkFDXfIGwjPL7`5pGjQHGgNS%xC(KKX))FttTQUZRmyJJfYIZWr?;DfCwf~5 z2##+;_(&51g(ifauR>7pi=33Uy>zkk9OF&usDYUDk+L4t9|lYN>ffI@q!(N}6{khGiNCjq(=@Y*v6QlV zRssR8tWAc-_8;&_xyJ>#gqTY@=7#ZCx6?1VeGXPS;NpN@7un^~6WxsEaga-mPdc76 zLn!@J5o3|<>a!$oaB&ej<;vPd@Z#!Q#A7P!l`4w#^G-`)hMwuk+_4*m*;5G2=hSYm zONV9mrMK})E9KU1?908Ie!vTuUk#q^n;V*o`Y>24CL%ivUDiX49qM9MQt;#^HQS7l z)d0&NFS0SpI1ufu#NVV6{^mzo2&D)cK3SY0u7tCkT%?u`i%|a@`!_B8&>R1$1;~G+ z1<4wdftQ_)!mc9mqHKAba%;ru9GneRxek*}Ay7p9S0^rb=6gAGDez^s7^`?T%|oe6 zrF$IVL!WHK9=uz-)Bl{EE)d%4e|lvp-N-1HtFX>hu>W_pfVU>X1y9g%Ea1A9(wL0gfoFuzI@!K)@LQ6#OR+>5wO0)MB}Xn>N;yiRtr{17B#?@F_4qs8YL@0T(c}4+yd6gi-VGov zJPdtONWKNW9&hK|??tsvI%|=mY&xrqr3>w5{XTUJofmz3dZMO9E$wCG;Ganq?X`Bn XZ<2LKa{5MOW6(E7@2ff42Gsryw|$O7