From 456981ccd5a8c5c3ef8e8705ff81d201829bbf7d Mon Sep 17 00:00:00 2001 From: Daniel Lehrner Date: Tue, 27 Apr 2021 22:42:38 +0200 Subject: [PATCH] Added SECP256R1 support to CLI sub command generate-blockchain-config (#2183) Signed-off-by: Daniel Lehrner --- .../org/hyperledger/besu/cli/BesuCommand.java | 6 +- .../operator/GenerateBlockchainConfig.java | 38 ++++- .../hyperledger/besu/cli/BesuCommandTest.java | 4 +- .../cli/operator/OperatorSubCommandTest.java | 140 ++++++++++++++++-- .../config_generate_keys_ec_invalid.json | 40 +++++ .../config_generate_keys_secp256r1.json | 40 +++++ .../operator/config_import_keys.json | 4 +- .../config_import_keys_secp256r1.json | 42 ++++++ ...ig_import_keys_secp256r1_invalid_keys.json | 42 ++++++ .../besu/crypto/AbstractSECP256.java | 11 ++ .../besu/crypto/SignatureAlgorithm.java | 2 + .../besu/crypto/SignatureAlgorithmType.java | 16 +- .../crypto/SignatureAlgorithmTypeTest.java | 4 +- 13 files changed, 364 insertions(+), 25 deletions(-) create mode 100644 besu/src/test/resources/operator/config_generate_keys_ec_invalid.json create mode 100644 besu/src/test/resources/operator/config_generate_keys_secp256r1.json create mode 100644 besu/src/test/resources/operator/config_import_keys_secp256r1.json create mode 100644 besu/src/test/resources/operator/config_import_keys_secp256r1_invalid_keys.json diff --git a/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java b/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java index ec24a60dc6..088416aff0 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java @@ -2673,7 +2673,11 @@ public class BesuCommand implements DefaultCommandValues, Runnable { try { SignatureAlgorithmFactory.setInstance(SignatureAlgorithmType.create(ecCurve.get())); } catch (IllegalArgumentException e) { - throw new CommandLine.InitializationException(e.getMessage()); + throw new CommandLine.InitializationException( + new StringBuilder() + .append("Invalid genesis file configuration for ecCurve. ") + .append(e.getMessage()) + .toString()); } } diff --git a/besu/src/main/java/org/hyperledger/besu/cli/subcommands/operator/GenerateBlockchainConfig.java b/besu/src/main/java/org/hyperledger/besu/cli/subcommands/operator/GenerateBlockchainConfig.java index 10d3c0d97d..8319310113 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/subcommands/operator/GenerateBlockchainConfig.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/subcommands/operator/GenerateBlockchainConfig.java @@ -18,6 +18,8 @@ import static com.google.common.base.Preconditions.checkNotNull; import static java.nio.charset.StandardCharsets.UTF_8; import org.hyperledger.besu.cli.DefaultCommandValues; +import org.hyperledger.besu.config.GenesisConfigFile; +import org.hyperledger.besu.config.GenesisConfigOptions; import org.hyperledger.besu.config.JsonGenesisConfigOptions; import org.hyperledger.besu.config.JsonUtil; import org.hyperledger.besu.consensus.ibft.IbftExtraDataCodec; @@ -26,6 +28,7 @@ import org.hyperledger.besu.crypto.SECPPrivateKey; import org.hyperledger.besu.crypto.SECPPublicKey; import org.hyperledger.besu.crypto.SignatureAlgorithm; import org.hyperledger.besu.crypto.SignatureAlgorithmFactory; +import org.hyperledger.besu.crypto.SignatureAlgorithmType; import org.hyperledger.besu.ethereum.core.Address; import org.hyperledger.besu.ethereum.core.Util; @@ -37,6 +40,7 @@ import java.nio.file.StandardOpenOption; import java.util.ArrayList; import java.util.HashSet; import java.util.List; +import java.util.Optional; import java.util.Set; import java.util.stream.IntStream; @@ -60,7 +64,7 @@ import picocli.CommandLine.ParentCommand; class GenerateBlockchainConfig implements Runnable { private static final Logger LOG = LogManager.getLogger(); - private static final Supplier SIGNATURE_ALGORITHM = + private final Supplier SIGNATURE_ALGORITHM = Suppliers.memoize(SignatureAlgorithmFactory::getInstance); @Option( @@ -133,6 +137,7 @@ class GenerateBlockchainConfig implements Runnable { try { handleOutputDirectory(); parseConfig(); + processEcCurve(); if (generateNodesKeys) { generateNodesKeys(); } else { @@ -167,6 +172,16 @@ class GenerateBlockchainConfig implements Runnable { try { final SECPPublicKey publicKey = SIGNATURE_ALGORITHM.get().createPublicKey(Bytes.fromHexString(publicKeyText)); + + if (!SIGNATURE_ALGORITHM.get().isValidPublicKey(publicKey)) { + throw new IllegalArgumentException( + new StringBuilder() + .append(publicKeyText) + .append(" is not a valid public key for elliptic curve ") + .append(SIGNATURE_ALGORITHM.get().getCurveName()) + .toString()); + } + writeKeypair(publicKey, null); LOG.info("Public key imported from configuration.({})", publicKey.toString()); } catch (final IOException e) { @@ -256,6 +271,27 @@ class GenerateBlockchainConfig implements Runnable { generateNodesKeys = JsonUtil.getBoolean(nodesConfig, "generate", false); } + /** Sets the selected signature algorithm instance in SignatureAlgorithmFactory. */ + private void processEcCurve() { + GenesisConfigOptions options = GenesisConfigFile.fromConfig(genesisConfig).getConfigOptions(); + Optional ecCurve = options.getEcCurve(); + + if (ecCurve.isEmpty()) { + SignatureAlgorithmFactory.setInstance(SignatureAlgorithmType.createDefault()); + return; + } + + try { + SignatureAlgorithmFactory.setInstance(SignatureAlgorithmType.create(ecCurve.get())); + } catch (IllegalArgumentException e) { + throw new IllegalArgumentException( + new StringBuilder() + .append("Invalid parameter for ecCurve in genesis config: ") + .append(e.getMessage()) + .toString()); + } + } + /** * Checks if the output directory exists. * diff --git a/besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java b/besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java index 5eed57783e..44ca636408 100644 --- a/besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java +++ b/besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java @@ -4328,8 +4328,8 @@ public class BesuCommandTest extends CommandTestAbstract { assertThat(commandOutput.toString()).isEmpty(); assertThat(commandErrorOutput.toString()) .contains( - "Invalid genesis file configuration. " - + "Elliptic curve (ecCurve) abcd is not in the list of valid elliptic curves [secp256k1, secp256r1]"); + "Invalid genesis file configuration for ecCurve. " + + "abcd is not in the list of valid elliptic curves [secp256k1, secp256r1]"); } @Test diff --git a/besu/src/test/java/org/hyperledger/besu/cli/operator/OperatorSubCommandTest.java b/besu/src/test/java/org/hyperledger/besu/cli/operator/OperatorSubCommandTest.java index 24b86d74c4..717015ac99 100644 --- a/besu/src/test/java/org/hyperledger/besu/cli/operator/OperatorSubCommandTest.java +++ b/besu/src/test/java/org/hyperledger/besu/cli/operator/OperatorSubCommandTest.java @@ -19,7 +19,6 @@ import static java.lang.System.currentTimeMillis; import static java.nio.charset.StandardCharsets.UTF_8; import static java.nio.file.Files.createTempDirectory; import static java.util.Arrays.asList; -import static java.util.Arrays.stream; import static java.util.Collections.singletonList; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; @@ -28,22 +27,31 @@ import static org.hyperledger.besu.cli.operator.OperatorSubCommandTest.Cmd.cmd; import org.hyperledger.besu.cli.CommandTestAbstract; import org.hyperledger.besu.cli.subcommands.operator.OperatorSubCommand; +import org.hyperledger.besu.crypto.SECP256K1; +import org.hyperledger.besu.crypto.SECP256R1; +import org.hyperledger.besu.crypto.SECPPrivateKey; +import org.hyperledger.besu.crypto.SECPPublicKey; +import org.hyperledger.besu.crypto.SignatureAlgorithm; +import org.hyperledger.besu.crypto.SignatureAlgorithmFactory; import java.io.File; +import java.io.FilenameFilter; import java.io.IOException; import java.net.URL; import java.nio.file.FileSystems; +import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; import java.util.Collection; import java.util.List; -import java.util.stream.Stream; +import java.util.Optional; import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import io.vertx.core.json.JsonObject; +import org.apache.tuweni.bytes.Bytes32; import org.junit.Before; import org.junit.Test; import picocli.CommandLine; @@ -72,6 +80,7 @@ public class OperatorSubCommandTest extends CommandTestAbstract { @Before public void init() throws IOException { + SignatureAlgorithmFactory.resetInstance(); tmpOutputDirectoryPath = createTempDirectory(format("output-%d", currentTimeMillis())); } @@ -107,7 +116,8 @@ public class OperatorSubCommandTest extends CommandTestAbstract { tmpOutputDirectoryPath, "genesis.json", true, - asList("key.pub", "key.priv")); + asList("key.pub", "key.priv"), + Optional.of(new SECP256K1())); } @Test @@ -129,7 +139,8 @@ public class OperatorSubCommandTest extends CommandTestAbstract { tmpOutputDirectoryPath, "option.json", true, - asList("key.pub", "key.priv")); + asList("key.pub", "key.priv"), + Optional.of(new SECP256K1())); } @Test @@ -140,7 +151,8 @@ public class OperatorSubCommandTest extends CommandTestAbstract { tmpOutputDirectoryPath, "genesis.json", true, - asList("pub.test", "key.priv")); + asList("pub.test", "key.priv"), + Optional.of(new SECP256K1())); } @Test @@ -151,7 +163,8 @@ public class OperatorSubCommandTest extends CommandTestAbstract { tmpOutputDirectoryPath, "genesis.json", true, - asList("key.pub", "priv.test")); + asList("key.pub", "priv.test"), + Optional.of(new SECP256K1())); } @Test @@ -197,6 +210,59 @@ public class OperatorSubCommandTest extends CommandTestAbstract { asList("key.pub", "key.priv")); } + @Test + public void shouldFailIfInvalidEcCurveIsSet() { + assertThatThrownBy( + () -> + runCmdAndCheckOutput( + cmd(), + "/operator/config_generate_keys_ec_invalid.json", + tmpOutputDirectoryPath, + "genesis.json", + true, + asList("key.pub", "priv.test"))) + .isInstanceOf(CommandLine.ExecutionException.class); + } + + @Test + public void shouldGenerateSECP256R1KeysWhenSetAsEcCurve() throws IOException { + runCmdAndCheckOutput( + cmd(), + "/operator/config_generate_keys_secp256r1.json", + tmpOutputDirectoryPath, + "genesis.json", + true, + asList("key.pub", "key.priv"), + Optional.of(new SECP256R1())); + } + + @Test + public void shouldFailIfImportedKeysAreFromDifferentEllipticCurve() { + assertThatThrownBy( + () -> + runCmdAndCheckOutput( + cmd(), + "/operator/config_import_keys_secp256r1_invalid_keys.json", + tmpOutputDirectoryPath, + "genesis.json", + true, + asList("key.pub", "key.priv"))) + .isInstanceOf(CommandLine.ExecutionException.class) + .hasMessageEndingWith( + "0xb295c4242fb40c6e8ac7b831c916846050f191adc560b8098ba6ad513079571ec1be6e5e1a715857a13a91963097962e048c36c5863014b59e8f67ed3f667680 is not a valid public key for elliptic curve secp256r1"); + } + + @Test + public void shouldImportSecp256R1Keys() throws IOException { + runCmdAndCheckOutput( + cmd(), + "/operator/config_import_keys_secp256r1.json", + tmpOutputDirectoryPath, + "genesis.json", + false, + singletonList("key.pub")); + } + private void runCmdAndCheckOutput( final Cmd cmd, final String configFile, @@ -205,6 +271,25 @@ public class OperatorSubCommandTest extends CommandTestAbstract { final boolean generate, final Collection expectedKeyFiles) throws IOException { + runCmdAndCheckOutput( + cmd, + configFile, + outputDirectoryPath, + genesisFileName, + generate, + expectedKeyFiles, + Optional.empty()); + } + + private void runCmdAndCheckOutput( + final Cmd cmd, + final String configFile, + final Path outputDirectoryPath, + final String genesisFileName, + final boolean generate, + final Collection expectedKeyFiles, + final Optional signatureAlgorithm) + throws IOException { final URL configFilePath = this.getClass().getResource(configFile); parseCommand( cmd( @@ -238,10 +323,47 @@ public class OperatorSubCommandTest extends CommandTestAbstract { final int nodeCount = jsonNode.get("blockchain").get("nodes").get("count").asInt(); assertThat(nodeCount).isEqualTo(nodesKeysFolders.length); } - final Stream nodesKeysFoldersStream = stream(nodesKeysFolders); - nodesKeysFoldersStream.forEach( - nodeFolder -> assertThat(nodeFolder.list()).containsAll(expectedKeyFiles)); + for (File nodeFolder : nodesKeysFolders) { + assertThat(nodeFolder.list()).containsAll(expectedKeyFiles); + + if (signatureAlgorithm.isPresent()) { + checkPublicKey(nodeFolder, signatureAlgorithm.get()); + } + } + } + + private void checkPublicKey(final File dir, final SignatureAlgorithm signatureAlgorithm) + throws IOException { + String publicKeyHex = readPubFile(dir); + String privateKeyHex = readPrivFile(dir); + + SECPPrivateKey privateKey = + signatureAlgorithm.createPrivateKey(Bytes32.fromHexString(privateKeyHex)); + SECPPublicKey expectedPublicKey = signatureAlgorithm.createPublicKey(privateKey); + + assertThat(publicKeyHex).isEqualTo(expectedPublicKey.getEncodedBytes().toHexString()); + } + + private String readPubFile(final File dir) throws IOException { + FilenameFilter pubFilter = (folder, name) -> name.contains("pub"); + + return readFile(dir, pubFilter); + } + + private String readPrivFile(final File dir) throws IOException { + FilenameFilter privFilter = (folder, name) -> name.contains("priv"); + + return readFile(dir, privFilter); + } + + private String readFile(final File dir, final FilenameFilter fileFilter) throws IOException { + File[] files = dir.listFiles(fileFilter); + + assertThat(files).isNotNull(); + assertThat(files.length).isEqualTo(1); + + return Files.readString(Path.of(files[0].getAbsolutePath())); } static class Cmd { diff --git a/besu/src/test/resources/operator/config_generate_keys_ec_invalid.json b/besu/src/test/resources/operator/config_generate_keys_ec_invalid.json new file mode 100644 index 0000000000..1483c45f38 --- /dev/null +++ b/besu/src/test/resources/operator/config_generate_keys_ec_invalid.json @@ -0,0 +1,40 @@ +{ + "genesis": { + "config": { + "chainId": 2017, + "eip150Block": 0, + "ecCurve": "abcd", + "ibft2": { + + } + }, + "nonce": "0x0", + "timestamp": "0x5b3c3d18", + "number": "0x0", + "gasUsed": "0x0", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "gasLimit": "0x47b760", + "difficulty": "0x1", + "mixHash": "0x63746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365", + "coinbase": "0x0000000000000000000000000000000000000000", + "ibft2": { + "blockperiodseconds": 2, + "epochlength": 30000, + "requesttimeoutseconds": 10 + }, + "alloc": { + "24defc2d149861d3d245749b81fe0e6b28e04f31": { + "balance": "0x446c3b15f9926687d2c40534fdb564000000000000" + }, + "2a813d7db3de19b07f92268b6d4125ed295cbe00": { + "balance": "0x446c3b15f9926687d2c40534fdb542000000000000" + } + } + }, + "blockchain": { + "nodes": { + "generate": true, + "count": 4 + } + } +} \ No newline at end of file diff --git a/besu/src/test/resources/operator/config_generate_keys_secp256r1.json b/besu/src/test/resources/operator/config_generate_keys_secp256r1.json new file mode 100644 index 0000000000..f66f588ffe --- /dev/null +++ b/besu/src/test/resources/operator/config_generate_keys_secp256r1.json @@ -0,0 +1,40 @@ +{ + "genesis": { + "config": { + "chainId": 2017, + "eip150Block": 0, + "ecCurve": "secp256r1", + "ibft2": { + + } + }, + "nonce": "0x0", + "timestamp": "0x5b3c3d18", + "number": "0x0", + "gasUsed": "0x0", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "gasLimit": "0x47b760", + "difficulty": "0x1", + "mixHash": "0x63746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365", + "coinbase": "0x0000000000000000000000000000000000000000", + "ibft2": { + "blockperiodseconds": 2, + "epochlength": 30000, + "requesttimeoutseconds": 10 + }, + "alloc": { + "24defc2d149861d3d245749b81fe0e6b28e04f31": { + "balance": "0x446c3b15f9926687d2c40534fdb564000000000000" + }, + "2a813d7db3de19b07f92268b6d4125ed295cbe00": { + "balance": "0x446c3b15f9926687d2c40534fdb542000000000000" + } + } + }, + "blockchain": { + "nodes": { + "generate": true, + "count": 4 + } + } +} \ No newline at end of file diff --git a/besu/src/test/resources/operator/config_import_keys.json b/besu/src/test/resources/operator/config_import_keys.json index b3a0d8edd8..db4e57b545 100644 --- a/besu/src/test/resources/operator/config_import_keys.json +++ b/besu/src/test/resources/operator/config_import_keys.json @@ -33,8 +33,8 @@ "blockchain": { "nodes": { "keys": [ - "0xb295c4242fb40c6e8ac7b831c916846050f191adc560b8098ba6ad513079571ec1be6e5e1a715857a13a91963097962e048c36c5863014b59e8f67ed3f667680", - "0x6295c4242fb40c6e8ac7b831c916846050f191adc560b8098ba6ad513079571ec1be6e5e1a715857a13a91963097962e048c36c5863014b59e8f67ed3f667680" + "0x9481ee2b34196827e8c4807ae29c2675c15d3641e482ab81cc0bc3ef535755b426b9f5c474213df28a563fab0bf0830b455ee8955b3faac93075422a6abf160d", + "0xf9dff57fc0bae7cba6577d82caf40cf6d266afc2a212775eb45c2188ab30aeed01e724daf4203649d4aa7e30717bfeeaf0b4c30b5d651bad39bcae8429759889" ] } } diff --git a/besu/src/test/resources/operator/config_import_keys_secp256r1.json b/besu/src/test/resources/operator/config_import_keys_secp256r1.json new file mode 100644 index 0000000000..bd189d0235 --- /dev/null +++ b/besu/src/test/resources/operator/config_import_keys_secp256r1.json @@ -0,0 +1,42 @@ +{ + "genesis": { + "config": { + "chainId": 2017, + "petersburgBlock": 0, + "ecCurve": "secp256r1", + "ibft2": { + + } + }, + "nonce": "0x0", + "timestamp": "0x5b3c3d18", + "number": "0x0", + "gasUsed": "0x0", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "gasLimit": "0x47b760", + "difficulty": "0x1", + "mixHash": "0x63746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365", + "coinbase": "0x0000000000000000000000000000000000000000", + "ibft2": { + "blockperiodseconds": 2, + "epochlength": 30000, + "requesttimeoutseconds": 10 + }, + "alloc": { + "24defc2d149861d3d245749b81fe0e6b28e04f31": { + "balance": "0x446c3b15f9926687d2c40534fdb564000000000000" + }, + "2a813d7db3de19b07f92268b6d4125ed295cbe00": { + "balance": "0x446c3b15f9926687d2c40534fdb542000000000000" + } + } + }, + "blockchain": { + "nodes": { + "keys": [ + "0x69b48fbfeaf1275afb2773b8b2ce485660e8d6b92f74b55814a567189339dab9ec75726c13206fdf716bb107eb52666a95b7d8188af60cd1bdb66493959ec3b6", + "0x6256fbfe4731d350d35261d2fa720cc2883d4f6d7f43797e5fee0c6b4c29ea6fc16abb3a8b30384d443f45eb7099b71bf4a61128a03b80c376e3883c8d0ffd0d" + ] + } + } +} diff --git a/besu/src/test/resources/operator/config_import_keys_secp256r1_invalid_keys.json b/besu/src/test/resources/operator/config_import_keys_secp256r1_invalid_keys.json new file mode 100644 index 0000000000..4f59b9ebd7 --- /dev/null +++ b/besu/src/test/resources/operator/config_import_keys_secp256r1_invalid_keys.json @@ -0,0 +1,42 @@ +{ + "genesis": { + "config": { + "chainId": 2017, + "petersburgBlock": 0, + "ecCurve": "secp256r1", + "ibft2": { + + } + }, + "nonce": "0x0", + "timestamp": "0x5b3c3d18", + "number": "0x0", + "gasUsed": "0x0", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "gasLimit": "0x47b760", + "difficulty": "0x1", + "mixHash": "0x63746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365", + "coinbase": "0x0000000000000000000000000000000000000000", + "ibft2": { + "blockperiodseconds": 2, + "epochlength": 30000, + "requesttimeoutseconds": 10 + }, + "alloc": { + "24defc2d149861d3d245749b81fe0e6b28e04f31": { + "balance": "0x446c3b15f9926687d2c40534fdb564000000000000" + }, + "2a813d7db3de19b07f92268b6d4125ed295cbe00": { + "balance": "0x446c3b15f9926687d2c40534fdb542000000000000" + } + } + }, + "blockchain": { + "nodes": { + "keys": [ + "0xb295c4242fb40c6e8ac7b831c916846050f191adc560b8098ba6ad513079571ec1be6e5e1a715857a13a91963097962e048c36c5863014b59e8f67ed3f667680", + "0x6295c4242fb40c6e8ac7b831c916846050f191adc560b8098ba6ad513079571ec1be6e5e1a715857a13a91963097962e048c36c5863014b59e8f67ed3f667680" + ] + } + } +} diff --git a/crypto/src/main/java/org/hyperledger/besu/crypto/AbstractSECP256.java b/crypto/src/main/java/org/hyperledger/besu/crypto/AbstractSECP256.java index 76ecdddffe..8054627671 100644 --- a/crypto/src/main/java/org/hyperledger/besu/crypto/AbstractSECP256.java +++ b/crypto/src/main/java/org/hyperledger/besu/crypto/AbstractSECP256.java @@ -174,6 +174,17 @@ public abstract class AbstractSECP256 implements SignatureAlgorithm { return publicKey.asEcPoint(curve); } + @Override + public boolean isValidPublicKey(final SECPPublicKey publicKey) { + try { + publicKeyAsEcPoint(publicKey); + } catch (IllegalArgumentException e) { + return false; + } + + return true; + } + @Override public KeyPair createKeyPair(final SECPPrivateKey privateKey) { return KeyPair.create(privateKey, curve, ALGORITHM); diff --git a/crypto/src/main/java/org/hyperledger/besu/crypto/SignatureAlgorithm.java b/crypto/src/main/java/org/hyperledger/besu/crypto/SignatureAlgorithm.java index c4a8d18eff..fbde25195d 100644 --- a/crypto/src/main/java/org/hyperledger/besu/crypto/SignatureAlgorithm.java +++ b/crypto/src/main/java/org/hyperledger/besu/crypto/SignatureAlgorithm.java @@ -67,6 +67,8 @@ public interface SignatureAlgorithm { ECPoint publicKeyAsEcPoint(final SECPPublicKey publicKey); + boolean isValidPublicKey(SECPPublicKey publicKey); + KeyPair createKeyPair(final SECPPrivateKey privateKey); KeyPair generateKeyPair(); diff --git a/crypto/src/main/java/org/hyperledger/besu/crypto/SignatureAlgorithmType.java b/crypto/src/main/java/org/hyperledger/besu/crypto/SignatureAlgorithmType.java index 9dc43abad7..c5ed1a7753 100644 --- a/crypto/src/main/java/org/hyperledger/besu/crypto/SignatureAlgorithmType.java +++ b/crypto/src/main/java/org/hyperledger/besu/crypto/SignatureAlgorithmType.java @@ -38,13 +38,7 @@ public class SignatureAlgorithmType { public static SignatureAlgorithmType create(final String ecCurve) throws IllegalArgumentException { if (!isValidType(ecCurve)) { - throw new IllegalArgumentException( - new StringBuilder() - .append("Invalid genesis file configuration. Elliptic curve (ecCurve) ") - .append(ecCurve) - .append(" is not in the list of valid elliptic curves ") - .append(getEcCurvesListAsString()) - .toString()); + throw new IllegalArgumentException(invalidTypeErrorMessage(ecCurve)); } return new SignatureAlgorithmType(SUPPORTED_ALGORITHMS.get(ecCurve)); @@ -66,6 +60,14 @@ public class SignatureAlgorithmType { return signatureAlgorithm.getCurveName().equals(DEFAULT_EC_CURVE_NAME); } + private static String invalidTypeErrorMessage(final String invalidEcCurve) { + return new StringBuilder() + .append(invalidEcCurve) + .append(" is not in the list of valid elliptic curves ") + .append(getEcCurvesListAsString()) + .toString(); + } + private static String getEcCurvesListAsString() { Iterator>> it = SUPPORTED_ALGORITHMS.entrySet().iterator(); diff --git a/crypto/src/test/java/org/hyperledger/besu/crypto/SignatureAlgorithmTypeTest.java b/crypto/src/test/java/org/hyperledger/besu/crypto/SignatureAlgorithmTypeTest.java index 75ca3369bf..faa0b5eeda 100644 --- a/crypto/src/test/java/org/hyperledger/besu/crypto/SignatureAlgorithmTypeTest.java +++ b/crypto/src/test/java/org/hyperledger/besu/crypto/SignatureAlgorithmTypeTest.java @@ -31,8 +31,6 @@ public class SignatureAlgorithmTypeTest { @Test public void shouldThrowExceptionWhenInvalidParameterIsGiven() { assertThatThrownBy(() -> SignatureAlgorithmType.create("abcd")) - .hasMessage( - "Invalid genesis file configuration. Elliptic curve (ecCurve) abcd is not in the list" - + " of valid elliptic curves [secp256k1, secp256r1]"); + .hasMessage("abcd is not in the list of valid elliptic curves [secp256k1, secp256r1]"); } }