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 fb3d451add6..00000000000 Binary files a/pki/src/test/resources/keystore/partner1client1/keys.p12 and /dev/null differ 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 a51a778eff9..00000000000 Binary files a/pki/src/test/resources/keystore/partner1client1/keystore.jks and /dev/null differ 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 fcfd0460219..00000000000 Binary files a/pki/src/test/resources/keystore/partner1client1/truststore.jks and /dev/null differ