Replacing the static references of SECP256K1 by an interface (#1933)

* Replacing the static references of SECP256K1 by an interface

Signed-off-by: Daniel Lehrner <daniel@io.builders>
This commit is contained in:
Daniel Lehrner
2021-03-01 01:43:14 +01:00
committed by GitHub
parent e2963d69af
commit 8315ba6dc6
174 changed files with 2327 additions and 1310 deletions

View File

@@ -14,9 +14,11 @@
*/
package org.hyperledger.besu.tests.acceptance.dsl.account;
import org.hyperledger.besu.crypto.SECP256K1.KeyPair;
import org.hyperledger.besu.crypto.SECP256K1.PrivateKey;
import org.hyperledger.besu.crypto.SECP256K1.PublicKey;
import org.hyperledger.besu.crypto.KeyPair;
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.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.Hash;
import org.hyperledger.besu.tests.acceptance.dsl.blockchain.Amount;
@@ -30,6 +32,8 @@ import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Optional;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import org.apache.tuweni.bytes.Bytes32;
import org.web3j.crypto.Credentials;
import org.web3j.utils.Convert.Unit;
@@ -38,11 +42,14 @@ public class Account {
private final EthTransactions eth;
private final String name;
private final Optional<PrivateKey> privateKey;
private final Optional<PublicKey> publicKey;
private final Optional<SECPPrivateKey> privateKey;
private final Optional<SECPPublicKey> publicKey;
private final Address address;
private long nonce = 0;
private static final Supplier<SignatureAlgorithm> SIGNATURE_ALGORITHM =
Suppliers.memoize(SignatureAlgorithmFactory::getInstance);
private Account(
final EthTransactions eth,
final String name,
@@ -68,13 +75,18 @@ public class Account {
}
public static Account create(final EthTransactions eth, final String name) {
return new Account(eth, name, KeyPair.generate());
return new Account(eth, name, SIGNATURE_ALGORITHM.get().generateKeyPair());
}
static Account fromPrivateKey(
final EthTransactions eth, final String name, final String privateKey) {
return new Account(
eth, name, KeyPair.create(PrivateKey.create(Bytes32.fromHexString(privateKey))));
eth,
name,
SIGNATURE_ALGORITHM
.get()
.createKeyPair(
SIGNATURE_ALGORITHM.get().createPrivateKey(Bytes32.fromHexString(privateKey))));
}
public Optional<Credentials> web3jCredentials() {

View File

@@ -18,8 +18,8 @@ import static java.util.Collections.unmodifiableList;
import static org.apache.logging.log4j.LogManager.getLogger;
import static org.apache.tuweni.io.file.Files.copyResource;
import org.hyperledger.besu.crypto.KeyPair;
import org.hyperledger.besu.crypto.KeyPairUtil;
import org.hyperledger.besu.crypto.SECP256K1.KeyPair;
import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcConfiguration;
import org.hyperledger.besu.ethereum.api.jsonrpc.websocket.WebSocketConfiguration;
import org.hyperledger.besu.ethereum.core.Address;

View File

@@ -23,7 +23,9 @@ import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList;
import static org.hyperledger.besu.ethereum.core.Address.DEFAULT_PRIVACY;
import org.hyperledger.besu.crypto.SECP256K1;
import org.hyperledger.besu.crypto.KeyPair;
import org.hyperledger.besu.crypto.SignatureAlgorithm;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.enclave.types.PrivacyGroup;
import org.hyperledger.besu.enclave.types.ReceiveResponse;
import org.hyperledger.besu.enclave.types.SendResponse;
@@ -45,6 +47,8 @@ import java.util.List;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.tomakehurst.wiremock.junit.WireMockRule;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.io.Base64;
import org.junit.After;
@@ -57,11 +61,17 @@ public class MultiTenancyAcceptanceTest extends AcceptanceTestBase {
private final ObjectMapper mapper = new ObjectMapper();
private Cluster multiTenancyCluster;
private static final SECP256K1.KeyPair TEST_KEY =
SECP256K1.KeyPair.create(
SECP256K1.PrivateKey.create(
new BigInteger(
"853d7f0010fd86d0d7811c1f9d968ea89a24484a8127b4a483ddf5d2cfec766d", 16)));
private static final Supplier<SignatureAlgorithm> SIGNATURE_ALGORITHM =
Suppliers.memoize(SignatureAlgorithmFactory::getInstance);
private static final KeyPair TEST_KEY =
SIGNATURE_ALGORITHM
.get()
.createKeyPair(
SIGNATURE_ALGORITHM
.get()
.createPrivateKey(
new BigInteger(
"853d7f0010fd86d0d7811c1f9d968ea89a24484a8127b4a483ddf5d2cfec766d", 16)));
private static final String PRIVACY_GROUP_ID = "B1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo=";
private static final String PARTICIPANT_ENCLAVE_KEY0 =
"A1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo=";

View File

@@ -24,7 +24,8 @@ import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRp
import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError.GET_PRIVATE_TRANSACTION_NONCE_ERROR;
import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError.PRIVATE_FROM_DOES_NOT_MATCH_ENCLAVE_PUBLIC_KEY;
import org.hyperledger.besu.crypto.SECP256K1;
import org.hyperledger.besu.crypto.SignatureAlgorithm;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.enclave.types.PrivacyGroup;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError;
import org.hyperledger.besu.ethereum.core.Address;
@@ -204,6 +205,9 @@ public class MultiTenancyValidationFailAcceptanceTest extends AcceptanceTestBase
private static PrivateTransaction getValidSignedPrivateTransaction(
final Address senderAddress, final String privateFrom) {
final SignatureAlgorithm signatureAlgorithm = SignatureAlgorithmFactory.getInstance();
return PrivateTransaction.builder()
.nonce(0)
.gasPrice(Wei.ZERO)
@@ -217,8 +221,8 @@ public class MultiTenancyValidationFailAcceptanceTest extends AcceptanceTestBase
.restriction(Restriction.RESTRICTED)
.privacyGroupId(Bytes.fromBase64String(PRIVACY_GROUP_ID))
.signAndBuild(
SECP256K1.KeyPair.create(
SECP256K1.PrivateKey.create(
signatureAlgorithm.createKeyPair(
signatureAlgorithm.createPrivateKey(
new BigInteger(
"853d7f0010fd86d0d7811c1f9d968ea89a24484a8127b4a483ddf5d2cfec766d", 16))));
}

View File

@@ -14,8 +14,10 @@
*/
package org.hyperledger.besu.chainimport.internal;
import org.hyperledger.besu.crypto.SECP256K1.KeyPair;
import org.hyperledger.besu.crypto.SECP256K1.PrivateKey;
import org.hyperledger.besu.crypto.KeyPair;
import org.hyperledger.besu.crypto.SECPPrivateKey;
import org.hyperledger.besu.crypto.SignatureAlgorithm;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.core.Wei;
@@ -25,6 +27,8 @@ import java.util.Optional;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
import org.apache.tuweni.units.bigints.UInt256;
@@ -37,7 +41,10 @@ public class TransactionData {
private final Bytes data;
private final Wei value;
private final Optional<Address> to;
private final PrivateKey privateKey;
private final SECPPrivateKey privateKey;
private static final Supplier<SignatureAlgorithm> SIGNATURE_ALGORITHM =
Suppliers.memoize(SignatureAlgorithmFactory::getInstance);
@JsonCreator
public TransactionData(
@@ -52,11 +59,11 @@ public class TransactionData {
this.data = data.map(Bytes::fromHexString).orElse(Bytes.EMPTY);
this.value = value.map(Wei::fromHexString).orElse(Wei.ZERO);
this.to = to.map(Address::fromHexString);
this.privateKey = PrivateKey.create(Bytes32.fromHexString(secretKey));
this.privateKey = SIGNATURE_ALGORITHM.get().createPrivateKey(Bytes32.fromHexString(secretKey));
}
public Transaction getSignedTransaction(final NonceProvider nonceProvider) {
final KeyPair keyPair = KeyPair.create(privateKey);
final KeyPair keyPair = SIGNATURE_ALGORITHM.get().createKeyPair(privateKey);
final Address fromAddress = Address.extract(keyPair.getPublicKey());
final long nonce = nonceProvider.get(fromAddress);

View File

@@ -80,10 +80,11 @@ import org.hyperledger.besu.config.experimental.ExperimentalEIPs;
import org.hyperledger.besu.controller.BesuController;
import org.hyperledger.besu.controller.BesuControllerBuilder;
import org.hyperledger.besu.controller.TargetingGasLimitCalculator;
import org.hyperledger.besu.crypto.KeyPair;
import org.hyperledger.besu.crypto.KeyPairSecurityModule;
import org.hyperledger.besu.crypto.KeyPairUtil;
import org.hyperledger.besu.crypto.NodeKey;
import org.hyperledger.besu.crypto.SECP256K1;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.enclave.EnclaveFactory;
import org.hyperledger.besu.enclave.GoQuorumEnclave;
import org.hyperledger.besu.ethereum.api.ApiConfiguration;
@@ -1274,7 +1275,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
}
@VisibleForTesting
SECP256K1.KeyPair loadKeyPair() {
KeyPair loadKeyPair() {
return KeyPairUtil.loadKeyPair(nodePrivateKeyFile());
}
@@ -1370,7 +1371,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
AbstractAltBnPrecompiledContract.enableNative();
}
if (unstableNativeLibraryOptions.getNativeSecp256k1()) {
SECP256K1.enableNative();
SignatureAlgorithmFactory.getInstance().enableNative();
}
}

View File

@@ -21,7 +21,11 @@ import org.hyperledger.besu.cli.DefaultCommandValues;
import org.hyperledger.besu.config.JsonGenesisConfigOptions;
import org.hyperledger.besu.config.JsonUtil;
import org.hyperledger.besu.consensus.common.bft.BftExtraData;
import org.hyperledger.besu.crypto.SECP256K1;
import org.hyperledger.besu.crypto.KeyPair;
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.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.Util;
@@ -39,6 +43,8 @@ import java.util.stream.IntStream;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.JsonNodeType;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.io.Resources;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -54,6 +60,9 @@ import picocli.CommandLine.ParentCommand;
class GenerateBlockchainConfig implements Runnable {
private static final Logger LOG = LogManager.getLogger();
private static final Supplier<SignatureAlgorithm> SIGNATURE_ALGORITHM =
Suppliers.memoize(SignatureAlgorithmFactory::getInstance);
@Option(
required = true,
names = "--config-file",
@@ -156,8 +165,8 @@ class GenerateBlockchainConfig implements Runnable {
final String publicKeyText = publicKeyJson.asText();
try {
final SECP256K1.PublicKey publicKey =
SECP256K1.PublicKey.create(Bytes.fromHexString(publicKeyText));
final SECPPublicKey publicKey =
SIGNATURE_ALGORITHM.get().createPublicKey(Bytes.fromHexString(publicKeyText));
writeKeypair(publicKey, null);
LOG.info("Public key imported from configuration.({})", publicKey.toString());
} catch (final IOException e) {
@@ -180,7 +189,7 @@ class GenerateBlockchainConfig implements Runnable {
private void generateNodeKeypair(final int node) {
try {
LOG.info("Generating keypair for node {}.", node);
final SECP256K1.KeyPair keyPair = SECP256K1.KeyPair.generate();
final KeyPair keyPair = SIGNATURE_ALGORITHM.get().generateKeyPair();
writeKeypair(keyPair.getPublicKey(), keyPair.getPrivateKey());
} catch (final IOException e) {
@@ -196,8 +205,7 @@ class GenerateBlockchainConfig implements Runnable {
* @param privateKey The private key. No file is created if privateKey is NULL.
* @throws IOException If the file cannot be written or accessed.
*/
private void writeKeypair(
final SECP256K1.PublicKey publicKey, final SECP256K1.PrivateKey privateKey)
private void writeKeypair(final SECPPublicKey publicKey, final SECPPrivateKey privateKey)
throws IOException {
final Address nodeAddress = Util.publicKeyToAddress(publicKey);
addressesForGenesisExtraData.add(nodeAddress);

View File

@@ -22,8 +22,10 @@ import static org.mockito.Mockito.when;
import org.hyperledger.besu.config.GenesisConfigFile;
import org.hyperledger.besu.controller.BesuController;
import org.hyperledger.besu.crypto.KeyPair;
import org.hyperledger.besu.crypto.NodeKeyUtils;
import org.hyperledger.besu.crypto.SECP256K1;
import org.hyperledger.besu.crypto.SignatureAlgorithm;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.enclave.Enclave;
import org.hyperledger.besu.enclave.EnclaveFactory;
import org.hyperledger.besu.enclave.types.PrivacyGroup;
@@ -71,6 +73,8 @@ import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import io.vertx.core.Vertx;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
@@ -83,11 +87,18 @@ import org.junit.rules.TemporaryFolder;
public class PrivacyReorgTest {
@Rule public final TemporaryFolder folder = new TemporaryFolder();
private static final SECP256K1.KeyPair KEY_PAIR =
SECP256K1.KeyPair.create(
SECP256K1.PrivateKey.create(
new BigInteger(
"8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63", 16)));
private static final Supplier<SignatureAlgorithm> SIGNATURE_ALGORITHM =
Suppliers.memoize(SignatureAlgorithmFactory::getInstance);
private static final KeyPair KEY_PAIR =
SIGNATURE_ALGORITHM
.get()
.createKeyPair(
SIGNATURE_ALGORITHM
.get()
.createPrivateKey(
new BigInteger(
"8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63", 16)));
private static final Bytes ENCLAVE_PUBLIC_KEY =
Bytes.fromBase64String("A1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo=");

View File

@@ -25,7 +25,7 @@ import org.hyperledger.besu.consensus.common.bft.protocol.BftProtocolManager;
import org.hyperledger.besu.consensus.ibft.protocol.IbftSubProtocol;
import org.hyperledger.besu.controller.BesuController;
import org.hyperledger.besu.crypto.NodeKey;
import org.hyperledger.besu.crypto.SECP256K1;
import org.hyperledger.besu.crypto.SECPPublicKey;
import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.api.graphql.GraphQLConfiguration;
import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcConfiguration;
@@ -72,7 +72,7 @@ public final class RunnerBuilderTest {
final EthContext ethContext = mock(EthContext.class);
final ProtocolContext protocolContext = mock(ProtocolContext.class);
final NodeKey nodeKey = mock(NodeKey.class);
final SECP256K1.PublicKey publicKey = mock(SECP256K1.PublicKey.class);
final SECPPublicKey publicKey = mock(SECPPublicKey.class);
when(subProtocolConfiguration.getProtocolManagers())
.thenReturn(

View File

@@ -40,8 +40,10 @@ import org.hyperledger.besu.cli.options.unstable.TransactionPoolOptions;
import org.hyperledger.besu.controller.BesuController;
import org.hyperledger.besu.controller.BesuControllerBuilder;
import org.hyperledger.besu.controller.NoopPluginServiceFactory;
import org.hyperledger.besu.crypto.KeyPair;
import org.hyperledger.besu.crypto.NodeKey;
import org.hyperledger.besu.crypto.SECP256K1;
import org.hyperledger.besu.crypto.SignatureAlgorithm;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.api.graphql.GraphQLConfiguration;
import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcConfiguration;
@@ -116,7 +118,7 @@ public abstract class CommandTestAbstract {
private final HashMap<String, String> environment = new HashMap<>();
private final List<TestBesuCommand> besuCommands = new ArrayList<>();
private SECP256K1.KeyPair keyPair;
private KeyPair keyPair;
@Mock protected RunnerBuilder mockRunnerBuilder;
@Mock protected Runner mockRunner;
@@ -241,9 +243,11 @@ public abstract class CommandTestAbstract {
when(mockRunnerBuilder.forkIdSupplier(any())).thenReturn(mockRunnerBuilder);
when(mockRunnerBuilder.build()).thenReturn(mockRunner);
final SignatureAlgorithm signatureAlgorithm = SignatureAlgorithmFactory.getInstance();
final Bytes32 keyPairPrvKey =
Bytes32.fromHexString("0xf7a58d5e755d51fa2f6206e91dd574597c73248aaf946ec1964b8c6268d6207b");
keyPair = SECP256K1.KeyPair.create(SECP256K1.PrivateKey.create(keyPairPrvKey));
keyPair = signatureAlgorithm.createKeyPair(signatureAlgorithm.createPrivateKey(keyPairPrvKey));
lenient().when(nodeKey.getPublicKey()).thenReturn(keyPair.getPublicKey());
@@ -332,12 +336,12 @@ public abstract class CommandTestAbstract {
@CommandLine.Spec CommandLine.Model.CommandSpec spec;
private Vertx vertx;
private final NodeKey mockNodeKey;
private final SECP256K1.KeyPair keyPair;
private final KeyPair keyPair;
TestBesuCommand(
final Logger mockLogger,
final NodeKey mockNodeKey,
final SECP256K1.KeyPair keyPair,
final KeyPair keyPair,
final Supplier<RlpBlockImporter> mockBlockImporter,
final Function<BesuController, JsonBlockImporter> jsonBlockImporterFactory,
final Function<Blockchain, RlpBlockExporter> rlpBlockExporterFactory,
@@ -380,7 +384,7 @@ public abstract class CommandTestAbstract {
}
@Override
SECP256K1.KeyPair loadKeyPair() {
KeyPair loadKeyPair() {
// for testing.
return keyPair;
}

View File

@@ -20,7 +20,9 @@ import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import org.hyperledger.besu.crypto.SECP256K1.KeyPair;
import org.hyperledger.besu.crypto.KeyPair;
import org.hyperledger.besu.crypto.SignatureAlgorithm;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.chain.DefaultBlockchain;
import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
@@ -68,6 +70,8 @@ import java.util.Optional;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Stream;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -78,7 +82,9 @@ import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class BesuEventsImplTest {
private static final KeyPair KEY_PAIR1 = KeyPair.generate();
private static final Supplier<SignatureAlgorithm> SIGNATURE_ALGORITHM =
Suppliers.memoize(SignatureAlgorithmFactory::getInstance);
private static final KeyPair KEY_PAIR1 = SIGNATURE_ALGORITHM.get().generateKeyPair();
private static final org.hyperledger.besu.ethereum.core.Transaction TX1 = createTransaction(1);
private static final org.hyperledger.besu.ethereum.core.Transaction TX2 = createTransaction(2);

View File

@@ -14,7 +14,7 @@
*/
package org.hyperledger.besu.consensus.clique;
import org.hyperledger.besu.crypto.SECP256K1.Signature;
import org.hyperledger.besu.crypto.SECPSignature;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.Hash;
@@ -69,7 +69,7 @@ public class CliqueBlockHashing {
private static Bytes encodeExtraDataWithoutProposerSeal(final CliqueExtraData cliqueExtraData) {
final Bytes extraDataBytes = cliqueExtraData.encode();
// Always trim off final 65 bytes (which maybe zeros)
return extraDataBytes.slice(0, extraDataBytes.size() - Signature.BYTES_REQUIRED);
return extraDataBytes.slice(0, extraDataBytes.size() - SECPSignature.BYTES_REQUIRED);
}
private static Bytes serializeHeader(

View File

@@ -17,7 +17,8 @@ package org.hyperledger.besu.consensus.clique;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import org.hyperledger.besu.crypto.SECP256K1.Signature;
import org.hyperledger.besu.crypto.SECPSignature;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.ParsedExtraData;
@@ -42,12 +43,12 @@ public class CliqueExtraData implements ParsedExtraData {
private final Bytes vanityData;
private final List<Address> validators;
private final Optional<Signature> proposerSeal;
private final Optional<SECPSignature> proposerSeal;
private final Supplier<Address> proposerAddress;
public CliqueExtraData(
final Bytes vanityData,
final Signature proposerSeal,
final SECPSignature proposerSeal,
final List<Address> validators,
final BlockHeader header) {
@@ -81,12 +82,13 @@ public class CliqueExtraData implements ParsedExtraData {
static CliqueExtraData decodeRaw(final BlockHeader header) {
final Bytes input = header.getExtraData();
if (input.size() < EXTRA_VANITY_LENGTH + Signature.BYTES_REQUIRED) {
if (input.size() < EXTRA_VANITY_LENGTH + SECPSignature.BYTES_REQUIRED) {
throw new IllegalArgumentException(
"Invalid Bytes supplied - too short to produce a valid Clique Extra Data object.");
}
final int validatorByteCount = input.size() - EXTRA_VANITY_LENGTH - Signature.BYTES_REQUIRED;
final int validatorByteCount =
input.size() - EXTRA_VANITY_LENGTH - SECPSignature.BYTES_REQUIRED;
if ((validatorByteCount % Address.SIZE) != 0) {
throw new IllegalArgumentException("Bytes is of invalid size - i.e. contains unused bytes.");
}
@@ -95,8 +97,8 @@ public class CliqueExtraData implements ParsedExtraData {
final List<Address> validators =
extractValidators(input.slice(EXTRA_VANITY_LENGTH, validatorByteCount));
final int proposerSealStartIndex = input.size() - Signature.BYTES_REQUIRED;
final Signature proposerSeal = parseProposerSeal(input.slice(proposerSealStartIndex));
final int proposerSealStartIndex = input.size() - SECPSignature.BYTES_REQUIRED;
final SECPSignature proposerSeal = parseProposerSeal(input.slice(proposerSealStartIndex));
return new CliqueExtraData(vanityData, proposerSeal, validators, header);
}
@@ -105,8 +107,10 @@ public class CliqueExtraData implements ParsedExtraData {
return proposerAddress.get();
}
private static Signature parseProposerSeal(final Bytes proposerSealRaw) {
return proposerSealRaw.isZero() ? null : Signature.decode(proposerSealRaw);
private static SECPSignature parseProposerSeal(final Bytes proposerSealRaw) {
return proposerSealRaw.isZero()
? null
: SignatureAlgorithmFactory.getInstance().decodeSignature(proposerSealRaw);
}
private static List<Address> extractValidators(final Bytes validatorsRaw) {
@@ -130,21 +134,21 @@ public class CliqueExtraData implements ParsedExtraData {
private static Bytes encode(
final Bytes vanityData,
final List<Address> validators,
final Optional<Signature> proposerSeal) {
final Optional<SECPSignature> proposerSeal) {
final Bytes validatorData = Bytes.concatenate(validators.toArray(new Bytes[0]));
return Bytes.concatenate(
vanityData,
validatorData,
proposerSeal
.map(Signature::encodedBytes)
.orElse(Bytes.wrap(new byte[Signature.BYTES_REQUIRED])));
.map(SECPSignature::encodedBytes)
.orElse(Bytes.wrap(new byte[SECPSignature.BYTES_REQUIRED])));
}
public Bytes getVanityData() {
return vanityData;
}
public Optional<Signature> getProposerSeal() {
public Optional<SECPSignature> getProposerSeal() {
return proposerSeal;
}

View File

@@ -20,7 +20,8 @@ import static org.hyperledger.besu.consensus.common.VoteType.ADD;
import static org.hyperledger.besu.consensus.common.VoteType.DROP;
import org.hyperledger.besu.consensus.common.ValidatorVote;
import org.hyperledger.besu.crypto.SECP256K1.KeyPair;
import org.hyperledger.besu.crypto.KeyPair;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.AddressHelpers;
import org.hyperledger.besu.ethereum.core.BlockHeader;
@@ -36,7 +37,8 @@ import org.junit.Test;
public class CliqueBlockInterfaceTest {
private static final KeyPair proposerKeys = KeyPair.generate();
private static final KeyPair proposerKeys =
SignatureAlgorithmFactory.getInstance().generateKeyPair();
private static final Address proposerAddress =
Util.publicKeyToAddress(proposerKeys.getPublicKey());
private static final List<Address> validatorList = singletonList(proposerAddress);

View File

@@ -22,7 +22,8 @@ import static org.mockito.Mockito.when;
import org.hyperledger.besu.consensus.common.VoteProposer;
import org.hyperledger.besu.consensus.common.VoteTally;
import org.hyperledger.besu.consensus.common.VoteTallyCache;
import org.hyperledger.besu.crypto.SECP256K1.KeyPair;
import org.hyperledger.besu.crypto.KeyPair;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.AddressHelpers;
@@ -39,7 +40,7 @@ import org.junit.Test;
public class CliqueDifficultyCalculatorTest {
private final KeyPair proposerKeyPair = KeyPair.generate();
private final KeyPair proposerKeyPair = SignatureAlgorithmFactory.getInstance().generateKeyPair();
private Address localAddr;
private final List<Address> validatorList = Lists.newArrayList();

View File

@@ -17,8 +17,10 @@ package org.hyperledger.besu.consensus.clique;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import org.hyperledger.besu.crypto.SECP256K1.KeyPair;
import org.hyperledger.besu.crypto.SECP256K1.Signature;
import org.hyperledger.besu.crypto.KeyPair;
import org.hyperledger.besu.crypto.SECPSignature;
import org.hyperledger.besu.crypto.SignatureAlgorithm;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.AddressHelpers;
import org.hyperledger.besu.ethereum.core.BlockHeader;
@@ -30,6 +32,8 @@ import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.collect.Lists;
import org.apache.tuweni.bytes.Bytes;
import org.bouncycastle.util.encoders.Hex;
@@ -37,9 +41,13 @@ import org.junit.Test;
public class CliqueExtraDataTest {
private static final Supplier<SignatureAlgorithm> SIGNATURE_ALGORITHM =
Suppliers.memoize(SignatureAlgorithmFactory::getInstance);
@Test
public void encodeAndDecodingDoNotAlterData() {
final Signature proposerSeal = Signature.create(BigInteger.ONE, BigInteger.ONE, (byte) 0);
final SECPSignature proposerSeal =
SIGNATURE_ALGORITHM.get().createSignature(BigInteger.ONE, BigInteger.ONE, (byte) 0);
final List<Address> validators =
Arrays.asList(
AddressHelpers.ofValue(1), AddressHelpers.ofValue(2), AddressHelpers.ofValue(3));
@@ -82,7 +90,8 @@ public class CliqueExtraDataTest {
@Test
public void insufficientDataResultsInAnIllegalArgumentException() {
final Bytes illegalData =
Bytes.wrap(new byte[Signature.BYTES_REQUIRED + CliqueExtraData.EXTRA_VANITY_LENGTH - 1]);
Bytes.wrap(
new byte[SECPSignature.BYTES_REQUIRED + CliqueExtraData.EXTRA_VANITY_LENGTH - 1]);
assertThatThrownBy(() -> CliqueExtraData.decodeRaw(createHeaderWithExtraData(illegalData)))
.isInstanceOf(IllegalArgumentException.class)
@@ -95,7 +104,7 @@ public class CliqueExtraDataTest {
final Bytes illegalData =
Bytes.wrap(
new byte
[Signature.BYTES_REQUIRED
[SECPSignature.BYTES_REQUIRED
+ CliqueExtraData.EXTRA_VANITY_LENGTH
+ Address.SIZE
- 1]);
@@ -109,7 +118,7 @@ public class CliqueExtraDataTest {
public void addressToExtraDataString() {
final List<KeyPair> nodeKeys = Lists.newArrayList();
for (int i = 0; i < 4; i++) {
nodeKeys.add(KeyPair.generate());
nodeKeys.add(SIGNATURE_ALGORITHM.get().generateKeyPair());
}
final List<Address> addresses =

View File

@@ -25,7 +25,8 @@ import org.hyperledger.besu.consensus.clique.headervalidationrules.SignerRateLim
import org.hyperledger.besu.consensus.common.VoteProposer;
import org.hyperledger.besu.consensus.common.VoteTally;
import org.hyperledger.besu.consensus.common.VoteTallyCache;
import org.hyperledger.besu.crypto.SECP256K1.KeyPair;
import org.hyperledger.besu.crypto.KeyPair;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
import org.hyperledger.besu.ethereum.core.Address;
@@ -45,9 +46,10 @@ import org.junit.Test;
public class NodeCanProduceNextBlockTest {
private final KeyPair proposerKeyPair = KeyPair.generate();
private final KeyPair proposerKeyPair = SignatureAlgorithmFactory.getInstance().generateKeyPair();
private Address localAddress;
private final KeyPair otherNodeKeyPair = KeyPair.generate();
private final KeyPair otherNodeKeyPair =
SignatureAlgorithmFactory.getInstance().generateKeyPair();
private final List<Address> validatorList = Lists.newArrayList();
private final BlockHeaderTestFixture headerBuilder = new BlockHeaderTestFixture();
private ProtocolContext cliqueProtocolContext;

View File

@@ -14,9 +14,9 @@
*/
package org.hyperledger.besu.consensus.clique;
import org.hyperledger.besu.crypto.SECP256K1;
import org.hyperledger.besu.crypto.SECP256K1.KeyPair;
import org.hyperledger.besu.crypto.SECP256K1.Signature;
import org.hyperledger.besu.crypto.KeyPair;
import org.hyperledger.besu.crypto.SECPSignature;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;
@@ -43,7 +43,8 @@ public class TestHelpers {
final Hash signingHash =
CliqueBlockHashing.calculateDataHashForProposerSeal(unsealedHeader, unsignedExtraData);
final Signature proposerSignature = SECP256K1.sign(signingHash, signer);
final SECPSignature proposerSignature =
SignatureAlgorithmFactory.getInstance().sign(signingHash, signer);
final Bytes signedExtraData =
new CliqueExtraData(

View File

@@ -32,9 +32,10 @@ import org.hyperledger.besu.consensus.common.EpochManager;
import org.hyperledger.besu.consensus.common.VoteProposer;
import org.hyperledger.besu.consensus.common.VoteTally;
import org.hyperledger.besu.consensus.common.VoteTallyCache;
import org.hyperledger.besu.crypto.KeyPair;
import org.hyperledger.besu.crypto.NodeKey;
import org.hyperledger.besu.crypto.NodeKeyUtils;
import org.hyperledger.besu.crypto.SECP256K1.KeyPair;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.chain.GenesisState;
import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
@@ -65,7 +66,7 @@ public class CliqueBlockCreatorTest {
private final NodeKey proposerNodeKey = NodeKeyUtils.generate();
private final Address proposerAddress = Util.publicKeyToAddress(proposerNodeKey.getPublicKey());
private final KeyPair otherKeyPair = KeyPair.generate();
private final KeyPair otherKeyPair = SignatureAlgorithmFactory.getInstance().generateKeyPair();
private final List<Address> validatorList = Lists.newArrayList();
private final MetricsSystem metricsSystem = new NoOpMetricsSystem();
private final CliqueBlockInterface blockInterface = new CliqueBlockInterface();

View File

@@ -21,7 +21,8 @@ import static org.mockito.Mockito.when;
import org.hyperledger.besu.consensus.common.VoteTally;
import org.hyperledger.besu.consensus.common.VoteTallyCache;
import org.hyperledger.besu.crypto.SECP256K1.KeyPair;
import org.hyperledger.besu.crypto.KeyPair;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.ethereum.blockcreation.AbstractBlockScheduler.BlockCreationTimeResult;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.AddressHelpers;
@@ -38,7 +39,7 @@ import org.junit.Test;
public class CliqueBlockSchedulerTest {
private final KeyPair proposerKeyPair = KeyPair.generate();
private final KeyPair proposerKeyPair = SignatureAlgorithmFactory.getInstance().generateKeyPair();
private Address localAddr;
private final List<Address> validatorList = Lists.newArrayList();

View File

@@ -30,7 +30,9 @@ import org.hyperledger.besu.consensus.clique.CliqueMiningTracker;
import org.hyperledger.besu.consensus.clique.TestHelpers;
import org.hyperledger.besu.consensus.common.VoteTally;
import org.hyperledger.besu.consensus.common.VoteTallyCache;
import org.hyperledger.besu.crypto.SECP256K1.KeyPair;
import org.hyperledger.besu.crypto.KeyPair;
import org.hyperledger.besu.crypto.SignatureAlgorithm;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
import org.hyperledger.besu.ethereum.core.Address;
@@ -45,6 +47,8 @@ import org.hyperledger.besu.ethereum.eth.sync.state.SyncState;
import java.util.List;
import java.util.Optional;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import org.assertj.core.util.Lists;
import org.junit.Before;
import org.junit.Test;
@@ -56,8 +60,11 @@ import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class CliqueMiningCoordinatorTest {
private final KeyPair proposerKeys = KeyPair.generate();
private final KeyPair validatorKeys = KeyPair.generate();
private static final Supplier<SignatureAlgorithm> SIGNATURE_ALGORITHM =
Suppliers.memoize(SignatureAlgorithmFactory::getInstance);
private final KeyPair proposerKeys = SIGNATURE_ALGORITHM.get().generateKeyPair();
private final KeyPair validatorKeys = SIGNATURE_ALGORITHM.get().generateKeyPair();
private final Address proposerAddress = Util.publicKeyToAddress(proposerKeys.getPublicKey());
private final Address validatorAddress = Util.publicKeyToAddress(validatorKeys.getPublicKey());

View File

@@ -25,7 +25,8 @@ import org.hyperledger.besu.consensus.clique.TestHelpers;
import org.hyperledger.besu.consensus.common.VoteProposer;
import org.hyperledger.besu.consensus.common.VoteTally;
import org.hyperledger.besu.consensus.common.VoteTallyCache;
import org.hyperledger.besu.crypto.SECP256K1.KeyPair;
import org.hyperledger.besu.crypto.KeyPair;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.AddressHelpers;
@@ -42,7 +43,7 @@ import org.junit.Test;
public class CliqueDifficultyValidationRuleTest {
private final KeyPair proposerKeyPair = KeyPair.generate();
private final KeyPair proposerKeyPair = SignatureAlgorithmFactory.getInstance().generateKeyPair();
private final List<Address> validatorList = Lists.newArrayList();
private ProtocolContext cliqueProtocolContext;
private BlockHeaderTestFixture blockHeaderBuilder;

View File

@@ -26,7 +26,8 @@ import org.hyperledger.besu.consensus.clique.TestHelpers;
import org.hyperledger.besu.consensus.common.EpochManager;
import org.hyperledger.besu.consensus.common.VoteTally;
import org.hyperledger.besu.consensus.common.VoteTallyCache;
import org.hyperledger.besu.crypto.SECP256K1.KeyPair;
import org.hyperledger.besu.crypto.KeyPair;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.AddressHelpers;
@@ -43,7 +44,7 @@ import org.junit.Test;
public class CliqueExtraDataValidationRuleTest {
private final KeyPair proposerKeyPair = KeyPair.generate();
private final KeyPair proposerKeyPair = SignatureAlgorithmFactory.getInstance().generateKeyPair();
private Address localAddr;
private final CliqueBlockInterface blockInterface = new CliqueBlockInterface();
@@ -82,7 +83,7 @@ public class CliqueExtraDataValidationRuleTest {
@Test
public void signerNotInExpectedValidatorsFailsValidation() {
final KeyPair otherSigner = KeyPair.generate();
final KeyPair otherSigner = SignatureAlgorithmFactory.getInstance().generateKeyPair();
final BlockHeaderTestFixture headerBuilder = new BlockHeaderTestFixture();
final BlockHeader parent = headerBuilder.number(1).buildHeader();

View File

@@ -16,7 +16,8 @@ package org.hyperledger.besu.consensus.common.bft;
import static com.google.common.base.Preconditions.checkNotNull;
import org.hyperledger.besu.crypto.SECP256K1.Signature;
import org.hyperledger.besu.crypto.SECPSignature;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.ParsedExtraData;
@@ -44,14 +45,14 @@ public class BftExtraData implements ParsedExtraData {
public static final int EXTRA_VANITY_LENGTH = 32;
private final Bytes vanityData;
private final Collection<Signature> seals;
private final Collection<SECPSignature> seals;
private final Optional<Vote> vote;
private final int round;
private final Collection<Address> validators;
public BftExtraData(
final Bytes vanityData,
final Collection<Signature> seals,
final Collection<SECPSignature> seals,
final Optional<Vote> vote,
final int round,
final Collection<Address> validators) {
@@ -101,7 +102,9 @@ public class BftExtraData implements ParsedExtraData {
vote = Optional.of(Vote.readFrom(rlpInput));
}
final int round = rlpInput.readInt();
final List<Signature> seals = rlpInput.readList(rlp -> Signature.decode(rlp.readBytes()));
final List<SECPSignature> seals =
rlpInput.readList(
rlp -> SignatureAlgorithmFactory.getInstance().decodeSignature(rlp.readBytes()));
rlpInput.leaveList();
return new BftExtraData(vanityData, seals, vote, round, validators);
@@ -160,7 +163,7 @@ public class BftExtraData implements ParsedExtraData {
return vanityData;
}
public Collection<Signature> getSeals() {
public Collection<SECPSignature> getSeals() {
return seals;
}

View File

@@ -14,7 +14,7 @@
*/
package org.hyperledger.besu.consensus.common.bft;
import org.hyperledger.besu.crypto.SECP256K1.Signature;
import org.hyperledger.besu.crypto.SECPSignature;
import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.BlockHeaderBuilder;
@@ -37,7 +37,7 @@ public class BftHelpers {
}
public static Block createSealedBlock(
final Block block, final Collection<Signature> commitSeals) {
final Block block, final Collection<SECPSignature> commitSeals) {
final BlockHeader initialHeader = block.getHeader();
final BftExtraData initialExtraData = BftExtraData.decode(initialHeader);

View File

@@ -19,7 +19,8 @@ import org.hyperledger.besu.consensus.common.bft.payload.Authored;
import org.hyperledger.besu.consensus.common.bft.payload.Payload;
import org.hyperledger.besu.consensus.common.bft.payload.RoundSpecific;
import org.hyperledger.besu.consensus.common.bft.payload.SignedData;
import org.hyperledger.besu.crypto.SECP256K1.Signature;
import org.hyperledger.besu.crypto.SECPSignature;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput;
import org.hyperledger.besu.ethereum.rlp.RLPInput;
@@ -76,7 +77,8 @@ public class BftMessage<P extends Payload> implements Authored, RoundSpecific {
final RLPInput rlpInput, final Function<RLPInput, T> decoder) {
rlpInput.enterList();
final T unsignedMessageData = decoder.apply(rlpInput);
final Signature signature = rlpInput.readBytes((Signature::decode));
final SECPSignature signature =
rlpInput.readBytes((SignatureAlgorithmFactory.getInstance()::decodeSignature));
rlpInput.leaveList();
return SignedData.create(unsignedMessageData, signature);

View File

@@ -16,7 +16,7 @@ package org.hyperledger.besu.consensus.common.bft.payload;
import static org.hyperledger.besu.consensus.common.bft.payload.PayloadHelpers.hashForSignature;
import org.hyperledger.besu.crypto.SECP256K1.Signature;
import org.hyperledger.besu.crypto.SECPSignature;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.Hash;
import org.hyperledger.besu.ethereum.core.Util;
@@ -31,16 +31,16 @@ import org.apache.tuweni.bytes.Bytes;
public class SignedData<M extends Payload> implements Authored {
private final Address sender;
private final Signature signature;
private final SECPSignature signature;
private final M unsignedPayload;
public static <T extends Payload> SignedData<T> create(
final T payload, final Signature signature) {
final T payload, final SECPSignature signature) {
final Hash msgHash = hashForSignature(payload);
return new SignedData<>(payload, Util.signatureToAddress(signature, msgHash), signature);
}
private SignedData(final M unsignedPayload, final Address sender, final Signature signature) {
private SignedData(final M unsignedPayload, final Address sender, final SECPSignature signature) {
this.unsignedPayload = unsignedPayload;
this.sender = sender;
this.signature = signature;

View File

@@ -17,7 +17,7 @@ package org.hyperledger.besu.consensus.common.bft.inttest;
import org.hyperledger.besu.consensus.common.bft.EventMultiplexer;
import org.hyperledger.besu.consensus.common.bft.events.BftEvents;
import org.hyperledger.besu.crypto.NodeKey;
import org.hyperledger.besu.crypto.SECP256K1.Signature;
import org.hyperledger.besu.crypto.SECPSignature;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.Hash;
import org.hyperledger.besu.ethereum.p2p.rlpx.connections.PeerConnection;
@@ -62,7 +62,7 @@ public abstract class DefaultValidatorPeer {
return peerConnection;
}
public Signature getBlockSignature(final Hash digest) {
public SECPSignature getBlockSignature(final Hash digest) {
return nodeKey.sign(digest);
}

View File

@@ -23,7 +23,8 @@ import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
import org.hyperledger.besu.crypto.SECP256K1.KeyPair;
import org.hyperledger.besu.crypto.KeyPair;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.BlockHeader;
@@ -39,7 +40,7 @@ public class VoteTallyUpdaterTest {
private static final long EPOCH_LENGTH = 30_000;
private final VoteTally voteTally = mock(VoteTally.class);
private final MutableBlockchain blockchain = mock(MutableBlockchain.class);
private final KeyPair proposerKeyPair = KeyPair.generate();
private final KeyPair proposerKeyPair = SignatureAlgorithmFactory.getInstance().generateKeyPair();
private final Address proposerAddress =
Address.extract(Hash.hash(proposerKeyPair.getPublicKey().getEncodedBytes()));
private final Address subject = Address.fromHexString("007f4a23ca00cd043d25c2888c1aa5688f81a344");

View File

@@ -17,7 +17,7 @@ package org.hyperledger.besu.consensus.common.bft;
import static java.util.Collections.emptyList;
import org.hyperledger.besu.crypto.NodeKey;
import org.hyperledger.besu.crypto.SECP256K1.Signature;
import org.hyperledger.besu.crypto.SECPSignature;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.Hash;
@@ -67,7 +67,7 @@ public class BftExtraDataFixture {
// if useDifferentRoundNumbersForCommittedSeals is true then each committed seal will be
// calculated for an extraData field with a different round number
List<Signature> commitSeals =
List<SECPSignature> commitSeals =
IntStream.range(0, committerNodeKeys.size())
.mapToObj(
i -> {

View File

@@ -18,7 +18,9 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import org.hyperledger.besu.consensus.common.VoteType;
import org.hyperledger.besu.crypto.SECP256K1.Signature;
import org.hyperledger.besu.crypto.SECPSignature;
import org.hyperledger.besu.crypto.SignatureAlgorithm;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput;
@@ -31,12 +33,17 @@ import java.util.List;
import java.util.Optional;
import java.util.Random;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.collect.Lists;
import org.apache.tuweni.bytes.Bytes;
import org.junit.Test;
public class BftExtraDataTest {
private static final Supplier<SignatureAlgorithm> SIGNATURE_ALGORITHM =
Suppliers.memoize(SignatureAlgorithmFactory::getInstance);
private final String RAW_HEX_ENCODING_STRING =
"f8f1a00102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20ea9400000000000000000000000000000000000"
+ "00001940000000000000000000000000000000000000002d794000000000000000000000000000000000000000181ff8400fedc"
@@ -52,10 +59,10 @@ public class BftExtraDataTest {
Arrays.asList(Address.fromHexString("1"), Address.fromHexString("2"));
final Optional<Vote> vote = Optional.of(Vote.authVote(Address.fromHexString("1")));
final int round = 0x00FEDCBA;
final List<Signature> committerSeals =
final List<SECPSignature> committerSeals =
Arrays.asList(
Signature.create(BigInteger.ONE, BigInteger.TEN, (byte) 0),
Signature.create(BigInteger.TEN, BigInteger.ONE, (byte) 0));
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();
@@ -70,7 +77,7 @@ public class BftExtraDataTest {
final Optional<Vote> vote = Optional.of(Vote.authVote(Address.fromHexString("1")));
final int round = 0x00FEDCBA;
final byte[] roundAsByteArray = new byte[] {(byte) 0x00, (byte) 0xFE, (byte) 0xDC, (byte) 0xBA};
final List<Signature> committerSeals = Lists.newArrayList();
final List<SECPSignature> committerSeals = Lists.newArrayList();
// Create a byte buffer with no data.
final byte[] vanity_bytes = new byte[32];
@@ -108,7 +115,7 @@ public class BftExtraDataTest {
final List<Address> validators = Lists.newArrayList();
final Optional<Vote> vote = Optional.of(Vote.authVote(Address.fromHexString("1")));
final byte[] roundAsByteArray = new byte[] {(byte) 0xFE, (byte) 0xDC, (byte) 0xBA};
final List<Signature> committerSeals = Lists.newArrayList();
final List<SECPSignature> committerSeals = Lists.newArrayList();
// Create a byte buffer with no data.
final byte[] vanity_bytes = new byte[32];
@@ -138,7 +145,7 @@ public class BftExtraDataTest {
public void nullVoteAndListConstituteValidContent() {
final List<Address> validators = Lists.newArrayList();
final int round = 0x00FEDCBA;
final List<Signature> committerSeals = Lists.newArrayList();
final List<SECPSignature> committerSeals = Lists.newArrayList();
// Create a byte buffer with no data.
final byte[] vanity_bytes = new byte[32];
@@ -172,7 +179,7 @@ public class BftExtraDataTest {
final List<Address> validators = Lists.newArrayList();
final Optional<Vote> vote = Optional.empty();
final int round = 0x00FEDCBA;
final List<Signature> committerSeals = Lists.newArrayList();
final List<SECPSignature> committerSeals = Lists.newArrayList();
// Create a byte buffer with no data.
final byte[] vanity_bytes = new byte[32];
@@ -191,7 +198,7 @@ public class BftExtraDataTest {
final List<Address> validators = Lists.newArrayList();
final Optional<Vote> vote = Optional.of(Vote.dropVote(Address.fromHexString("1")));
final int round = 0x00FEDCBA;
final List<Signature> committerSeals = Lists.newArrayList();
final List<SECPSignature> committerSeals = Lists.newArrayList();
// Create a byte buffer with no data.
final byte[] vanity_bytes = new byte[32];
@@ -224,7 +231,7 @@ public class BftExtraDataTest {
final List<Address> validators = Lists.newArrayList();
final Optional<Vote> vote = Optional.of(Vote.authVote(Address.fromHexString("1")));
final int round = 0x00FEDCBA;
final List<Signature> committerSeals = Lists.newArrayList();
final List<SECPSignature> committerSeals = Lists.newArrayList();
// Create a byte buffer with no data.
final byte[] vanity_bytes = new byte[32];
@@ -243,10 +250,10 @@ public class BftExtraDataTest {
final List<Address> validators =
Arrays.asList(Address.fromHexString("1"), Address.fromHexString("2"));
final int round = 0x00FEDCBA;
final List<Signature> committerSeals =
final List<SECPSignature> committerSeals =
Arrays.asList(
Signature.create(BigInteger.ONE, BigInteger.TEN, (byte) 0),
Signature.create(BigInteger.TEN, BigInteger.ONE, (byte) 0));
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();
@@ -286,10 +293,10 @@ public class BftExtraDataTest {
Arrays.asList(Address.fromHexString("1"), Address.fromHexString("2"));
final Optional<Vote> vote = Optional.of(Vote.authVote(Address.fromHexString("1")));
final int round = 0x00FEDCBA;
final List<Signature> committerSeals =
final List<SECPSignature> committerSeals =
Arrays.asList(
Signature.create(BigInteger.ONE, BigInteger.TEN, (byte) 0),
Signature.create(BigInteger.TEN, BigInteger.ONE, (byte) 0));
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();
@@ -327,10 +334,10 @@ public class BftExtraDataTest {
Arrays.asList(Address.fromHexString("1"), Address.fromHexString("2"));
final Optional<Vote> vote = Optional.of(Vote.authVote(Address.fromHexString("1")));
final int round = 0x00FEDCBA;
final List<Signature> committerSeals =
final List<SECPSignature> committerSeals =
Arrays.asList(
Signature.create(BigInteger.ONE, BigInteger.TEN, (byte) 0),
Signature.create(BigInteger.TEN, BigInteger.ONE, (byte) 0));
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();
@@ -362,10 +369,10 @@ public class BftExtraDataTest {
Arrays.asList(Address.fromHexString("1"), Address.fromHexString("2"));
final Optional<Vote> vote = Optional.of(Vote.authVote(Address.fromHexString("1")));
final int round = 0x00FEDCBA;
final List<Signature> committerSeals =
final List<SECPSignature> committerSeals =
Arrays.asList(
Signature.create(BigInteger.ONE, BigInteger.TEN, (byte) 0),
Signature.create(BigInteger.TEN, BigInteger.ONE, (byte) 0));
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();
@@ -395,7 +402,7 @@ public class BftExtraDataTest {
final List<Address> validators = Lists.newArrayList();
final Optional<Vote> vote = Optional.of(Vote.authVote(Address.fromHexString("1")));
final int round = 0x00FEDCBA;
final List<Signature> committerSeals = Lists.newArrayList();
final List<SECPSignature> committerSeals = Lists.newArrayList();
// Create a byte buffer with no data.
final byte[] vanity_bytes = new byte[32];
@@ -427,10 +434,10 @@ public class BftExtraDataTest {
final Address voteRecipient = Address.fromHexString("1");
final byte voteType = (byte) 0xAA;
final int round = 0x00FEDCBA;
final List<Signature> committerSeals =
final List<SECPSignature> committerSeals =
Arrays.asList(
Signature.create(BigInteger.ONE, BigInteger.TEN, (byte) 0),
Signature.create(BigInteger.TEN, BigInteger.ONE, (byte) 0));
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 = new byte[32];

View File

@@ -24,7 +24,8 @@ import static org.mockito.Mockito.when;
import org.hyperledger.besu.consensus.common.VoteTally;
import org.hyperledger.besu.consensus.common.VoteTallyCache;
import org.hyperledger.besu.crypto.SECP256K1.PublicKey;
import org.hyperledger.besu.crypto.SECPPublicKey;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.Util;
import org.hyperledger.besu.ethereum.p2p.rlpx.connections.PeerConnection;
@@ -48,7 +49,7 @@ public class ValidatorPeersTest {
public static final String PROTOCOL_NAME = "BFT";
private final List<Address> validators = newArrayList();
private final List<PublicKey> publicKeys = newArrayList();
private final List<SECPPublicKey> publicKeys = newArrayList();
private final List<PeerConnection> peerConnections = newArrayList();
@Mock private VoteTallyCache voteTallyCache;
@@ -56,7 +57,8 @@ public class ValidatorPeersTest {
@Before
public void setup() {
for (int i = 0; i < 4; i++) {
final PublicKey pubKey = PublicKey.create(BigInteger.valueOf(i));
final SECPPublicKey pubKey =
SignatureAlgorithmFactory.getInstance().createPublicKey(BigInteger.valueOf(i));
publicKeys.add(pubKey);
final Address address = Util.publicKeyToAddress(pubKey);

View File

@@ -24,7 +24,7 @@ import org.hyperledger.besu.consensus.common.bft.BftBlockInterface;
import org.hyperledger.besu.consensus.common.bft.BftExtraData;
import org.hyperledger.besu.crypto.NodeKey;
import org.hyperledger.besu.crypto.NodeKeyUtils;
import org.hyperledger.besu.crypto.SECP256K1.Signature;
import org.hyperledger.besu.crypto.SECPSignature;
import org.hyperledger.besu.ethereum.chain.Blockchain;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.BlockHeader;
@@ -84,7 +84,7 @@ public class BftQueryServiceImplTest {
final BlockHeader unsignedBlockHeader = blockHeaderTestFixture.buildHeader();
final Collection<Signature> validatorSignatures =
final Collection<SECPSignature> validatorSignatures =
signingKeys.stream()
.map(
nodeKey ->

View File

@@ -23,7 +23,7 @@ import org.hyperledger.besu.consensus.ibft.payload.CommitPayload;
import org.hyperledger.besu.consensus.ibft.payload.MessageFactory;
import org.hyperledger.besu.consensus.ibft.statemachine.PreparedRoundArtifacts;
import org.hyperledger.besu.crypto.NodeKey;
import org.hyperledger.besu.crypto.SECP256K1.Signature;
import org.hyperledger.besu.crypto.SECPSignature;
import org.hyperledger.besu.ethereum.core.Block;
import java.util.Optional;
@@ -36,7 +36,7 @@ public class IntegrationTestHelpers {
final BftExtraData extraData = BftExtraData.decode(block.getHeader());
final Signature commitSeal =
final SECPSignature commitSeal =
nodeKey.sign(
BftBlockHashing.calculateDataHashForCommittedSeal(block.getHeader(), extraData));

View File

@@ -31,7 +31,7 @@ import org.hyperledger.besu.consensus.ibft.messagewrappers.RoundChange;
import org.hyperledger.besu.consensus.ibft.payload.PreparePayload;
import org.hyperledger.besu.consensus.ibft.payload.RoundChangePayload;
import org.hyperledger.besu.consensus.ibft.statemachine.PreparedRoundArtifacts;
import org.hyperledger.besu.crypto.SECP256K1.Signature;
import org.hyperledger.besu.crypto.SECPSignature;
import org.hyperledger.besu.ethereum.core.Hash;
import org.hyperledger.besu.ethereum.p2p.rlpx.wire.MessageData;
@@ -72,7 +72,7 @@ public class RoundSpecificPeers {
peers.forEach(ValidatorPeer::clearReceivedMessages);
}
public List<Signature> sign(final Hash digest) {
public List<SECPSignature> sign(final Hash digest) {
return peers.stream().map(peer -> peer.getBlockSignature(digest)).collect(Collectors.toList());
}

View File

@@ -29,7 +29,7 @@ import org.hyperledger.besu.consensus.ibft.messagewrappers.RoundChange;
import org.hyperledger.besu.consensus.ibft.payload.MessageFactory;
import org.hyperledger.besu.consensus.ibft.payload.RoundChangeCertificate;
import org.hyperledger.besu.consensus.ibft.statemachine.PreparedRoundArtifacts;
import org.hyperledger.besu.crypto.SECP256K1.Signature;
import org.hyperledger.besu.crypto.SECPSignature;
import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.core.Hash;
@@ -62,13 +62,13 @@ public class ValidatorPeer extends DefaultValidatorPeer {
}
public Commit injectCommit(final ConsensusRoundIdentifier rId, final Hash digest) {
final Signature commitSeal = nodeKey.sign(digest);
final SECPSignature commitSeal = nodeKey.sign(digest);
return injectCommit(rId, digest, commitSeal);
}
public Commit injectCommit(
final ConsensusRoundIdentifier rId, final Hash digest, final Signature commitSeal) {
final ConsensusRoundIdentifier rId, final Hash digest, final SECPSignature commitSeal) {
final Commit payload = messageFactory.createCommit(rId, digest, commitSeal);
injectMessage(CommitMessageData.create(payload));
return payload;

View File

@@ -29,7 +29,7 @@ import org.hyperledger.besu.consensus.ibft.support.TestContextBuilder;
import org.hyperledger.besu.consensus.ibft.support.ValidatorPeer;
import org.hyperledger.besu.crypto.NodeKey;
import org.hyperledger.besu.crypto.NodeKeyUtils;
import org.hyperledger.besu.crypto.SECP256K1.Signature;
import org.hyperledger.besu.crypto.SECPSignature;
import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.core.Hash;
import org.hyperledger.besu.ethereum.core.Util;
@@ -145,7 +145,7 @@ public class SpuriousBehaviourTest {
// nonProposer-2 will generate an invalid seal
final ValidatorPeer badSealPeer = peers.getNonProposing(2);
final Signature illegalSeal = badSealPeer.getnodeKey().sign(Hash.ZERO);
final SECPSignature illegalSeal = badSealPeer.getnodeKey().sign(Hash.ZERO);
badSealPeer.injectCommit(roundId, proposedBlock.getHash(), illegalSeal);
assertThat(context.getCurrentChainHeight()).isEqualTo(0);

View File

@@ -35,7 +35,8 @@ import org.hyperledger.besu.consensus.ibft.statemachine.RoundState;
import org.hyperledger.besu.consensus.ibft.validation.MessageValidator;
import org.hyperledger.besu.crypto.NodeKey;
import org.hyperledger.besu.crypto.NodeKeyUtils;
import org.hyperledger.besu.crypto.SECP256K1.Signature;
import org.hyperledger.besu.crypto.SECPSignature;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.chain.MinedBlockObserver;
import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
@@ -81,8 +82,9 @@ public class IbftRoundIntegrationTest {
private Block proposedBlock;
private final Signature remoteCommitSeal =
Signature.create(BigInteger.ONE, BigInteger.ONE, (byte) 1);
private final SECPSignature remoteCommitSeal =
SignatureAlgorithmFactory.getInstance()
.createSignature(BigInteger.ONE, BigInteger.ONE, (byte) 1);
@Before
public void setup() {

View File

@@ -18,7 +18,7 @@ import org.hyperledger.besu.consensus.common.bft.messagewrappers.BftMessage;
import org.hyperledger.besu.consensus.common.bft.payload.SignedData;
import org.hyperledger.besu.consensus.ibft.payload.CommitPayload;
import org.hyperledger.besu.consensus.ibft.payload.PayloadDeserializers;
import org.hyperledger.besu.crypto.SECP256K1.Signature;
import org.hyperledger.besu.crypto.SECPSignature;
import org.hyperledger.besu.ethereum.core.Hash;
import org.hyperledger.besu.ethereum.rlp.RLP;
@@ -30,7 +30,7 @@ public class Commit extends BftMessage<CommitPayload> {
super(payload);
}
public Signature getCommitSeal() {
public SECPSignature getCommitSeal() {
return getPayload().getCommitSeal();
}

View File

@@ -27,7 +27,7 @@ import org.hyperledger.besu.consensus.ibft.messagewrappers.RoundChange;
import org.hyperledger.besu.consensus.ibft.payload.MessageFactory;
import org.hyperledger.besu.consensus.ibft.payload.RoundChangeCertificate;
import org.hyperledger.besu.consensus.ibft.statemachine.PreparedRoundArtifacts;
import org.hyperledger.besu.crypto.SECP256K1.Signature;
import org.hyperledger.besu.crypto.SECPSignature;
import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.core.Hash;
import org.hyperledger.besu.plugin.services.securitymodule.SecurityModuleException;
@@ -81,7 +81,7 @@ public class IbftMessageTransmitter {
public void multicastCommit(
final ConsensusRoundIdentifier roundIdentifier,
final Hash digest,
final Signature commitSeal) {
final SECPSignature commitSeal) {
try {
final Commit data = messageFactory.createCommit(roundIdentifier, digest, commitSeal);

View File

@@ -17,7 +17,8 @@ package org.hyperledger.besu.consensus.ibft.payload;
import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier;
import org.hyperledger.besu.consensus.common.bft.payload.Payload;
import org.hyperledger.besu.consensus.ibft.messagedata.IbftV2;
import org.hyperledger.besu.crypto.SECP256K1.Signature;
import org.hyperledger.besu.crypto.SECPSignature;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.ethereum.core.Hash;
import org.hyperledger.besu.ethereum.rlp.RLPInput;
import org.hyperledger.besu.ethereum.rlp.RLPOutput;
@@ -29,12 +30,12 @@ public class CommitPayload implements Payload {
private static final int TYPE = IbftV2.COMMIT;
private final ConsensusRoundIdentifier roundIdentifier;
private final Hash digest;
private final Signature commitSeal;
private final SECPSignature commitSeal;
public CommitPayload(
final ConsensusRoundIdentifier roundIdentifier,
final Hash digest,
final Signature commitSeal) {
final SECPSignature commitSeal) {
this.roundIdentifier = roundIdentifier;
this.digest = digest;
this.commitSeal = commitSeal;
@@ -44,7 +45,8 @@ public class CommitPayload implements Payload {
rlpInput.enterList();
final ConsensusRoundIdentifier roundIdentifier = ConsensusRoundIdentifier.readFrom(rlpInput);
final Hash digest = Payload.readDigest(rlpInput);
final Signature commitSeal = rlpInput.readBytes(Signature::decode);
final SECPSignature commitSeal =
rlpInput.readBytes(SignatureAlgorithmFactory.getInstance()::decodeSignature);
rlpInput.leaveList();
return new CommitPayload(roundIdentifier, digest, commitSeal);
@@ -68,7 +70,7 @@ public class CommitPayload implements Payload {
return digest;
}
public Signature getCommitSeal() {
public SECPSignature getCommitSeal() {
return commitSeal;
}

View File

@@ -25,7 +25,7 @@ import org.hyperledger.besu.consensus.ibft.messagewrappers.Proposal;
import org.hyperledger.besu.consensus.ibft.messagewrappers.RoundChange;
import org.hyperledger.besu.consensus.ibft.statemachine.PreparedRoundArtifacts;
import org.hyperledger.besu.crypto.NodeKey;
import org.hyperledger.besu.crypto.SECP256K1.Signature;
import org.hyperledger.besu.crypto.SECPSignature;
import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.core.Hash;
@@ -59,7 +59,7 @@ public class MessageFactory {
public Commit createCommit(
final ConsensusRoundIdentifier roundIdentifier,
final Hash digest,
final Signature commitSeal) {
final SECPSignature commitSeal) {
final CommitPayload payload = new CommitPayload(roundIdentifier, digest, commitSeal);
@@ -79,7 +79,7 @@ public class MessageFactory {
}
private <M extends Payload> SignedData<M> createSignedMessage(final M payload) {
final Signature signature = nodeKey.sign(hashForSignature(payload));
final SECPSignature signature = nodeKey.sign(hashForSignature(payload));
return SignedData.create(payload, signature);
}
}

View File

@@ -16,7 +16,8 @@ package org.hyperledger.besu.consensus.ibft.payload;
import org.hyperledger.besu.consensus.common.bft.payload.Payload;
import org.hyperledger.besu.consensus.common.bft.payload.SignedData;
import org.hyperledger.besu.crypto.SECP256K1.Signature;
import org.hyperledger.besu.crypto.SECPSignature;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.ethereum.rlp.RLPInput;
public class PayloadDeserializers {
@@ -25,7 +26,7 @@ public class PayloadDeserializers {
rlpInput.enterList();
final ProposalPayload unsignedMessageData = ProposalPayload.readFrom(rlpInput);
final Signature signature = readSignature(rlpInput);
final SECPSignature signature = readSignature(rlpInput);
rlpInput.leaveList();
return from(unsignedMessageData, signature);
@@ -35,7 +36,7 @@ public class PayloadDeserializers {
rlpInput.enterList();
final PreparePayload unsignedMessageData = PreparePayload.readFrom(rlpInput);
final Signature signature = readSignature(rlpInput);
final SECPSignature signature = readSignature(rlpInput);
rlpInput.leaveList();
return from(unsignedMessageData, signature);
@@ -45,7 +46,7 @@ public class PayloadDeserializers {
rlpInput.enterList();
final CommitPayload unsignedMessageData = CommitPayload.readFrom(rlpInput);
final Signature signature = readSignature(rlpInput);
final SECPSignature signature = readSignature(rlpInput);
rlpInput.leaveList();
return from(unsignedMessageData, signature);
@@ -56,18 +57,18 @@ public class PayloadDeserializers {
rlpInput.enterList();
final RoundChangePayload unsignedMessageData = RoundChangePayload.readFrom(rlpInput);
final Signature signature = readSignature(rlpInput);
final SECPSignature signature = readSignature(rlpInput);
rlpInput.leaveList();
return from(unsignedMessageData, signature);
}
protected static <M extends Payload> SignedData<M> from(
final M unsignedMessageData, final Signature signature) {
final M unsignedMessageData, final SECPSignature signature) {
return SignedData.create(unsignedMessageData, signature);
}
protected static Signature readSignature(final RLPInput signedMessage) {
return signedMessage.readBytes(Signature::decode);
protected static SECPSignature readSignature(final RLPInput signedMessage) {
return signedMessage.readBytes(SignatureAlgorithmFactory.getInstance()::decodeSignature);
}
}

View File

@@ -29,7 +29,7 @@ import org.hyperledger.besu.consensus.ibft.network.IbftMessageTransmitter;
import org.hyperledger.besu.consensus.ibft.payload.MessageFactory;
import org.hyperledger.besu.consensus.ibft.payload.RoundChangeCertificate;
import org.hyperledger.besu.crypto.NodeKey;
import org.hyperledger.besu.crypto.SECP256K1.Signature;
import org.hyperledger.besu.crypto.SECPSignature;
import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.chain.MinedBlockObserver;
import org.hyperledger.besu.ethereum.core.Block;
@@ -172,7 +172,7 @@ public class IbftRound {
if (blockAccepted) {
final Block block = roundState.getProposedBlock().get();
final Signature commitSeal;
final SECPSignature commitSeal;
try {
commitSeal = createCommitSeal(block);
} catch (final SecurityModuleException e) {
@@ -258,7 +258,7 @@ public class IbftRound {
}
}
private Signature createCommitSeal(final Block block) {
private SECPSignature createCommitSeal(final Block block) {
final BlockHeader proposedHeader = block.getHeader();
final BftExtraData extraData = BftExtraData.decode(proposedHeader);
final Hash commitHash =

View File

@@ -20,7 +20,7 @@ import org.hyperledger.besu.consensus.ibft.messagewrappers.Commit;
import org.hyperledger.besu.consensus.ibft.messagewrappers.Prepare;
import org.hyperledger.besu.consensus.ibft.messagewrappers.Proposal;
import org.hyperledger.besu.consensus.ibft.validation.MessageValidator;
import org.hyperledger.besu.crypto.SECP256K1.Signature;
import org.hyperledger.besu.crypto.SECPSignature;
import org.hyperledger.besu.ethereum.core.Block;
import java.util.Collection;
@@ -123,7 +123,7 @@ public class RoundState {
return committed;
}
public Collection<Signature> getCommitSeals() {
public Collection<SECPSignature> getCommitSeals() {
return commitMessages.stream()
.map(cp -> cp.getSignedPayload().getPayload().getCommitSeal())
.collect(Collectors.toList());

View File

@@ -23,9 +23,9 @@ import org.hyperledger.besu.consensus.common.bft.BftExtraData;
import org.hyperledger.besu.consensus.common.bft.Vote;
import org.hyperledger.besu.crypto.NodeKey;
import org.hyperledger.besu.crypto.NodeKeyUtils;
import org.hyperledger.besu.crypto.SECP256K1.KeyPair;
import org.hyperledger.besu.crypto.SECP256K1.PrivateKey;
import org.hyperledger.besu.crypto.SECP256K1.Signature;
import org.hyperledger.besu.crypto.SECPSignature;
import org.hyperledger.besu.crypto.SignatureAlgorithm;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.BlockHeaderBuilder;
@@ -85,7 +85,7 @@ public class BftBlockHashingTest {
BlockHeaderBuilder builder = setHeaderFieldsExceptForExtraData();
List<Signature> commitSeals =
List<SECPSignature> commitSeals =
COMMITTERS_NODE_KEYS.stream()
.map(nodeKey -> nodeKey.sign(dataHahsForCommittedSeal))
.collect(Collectors.toList());
@@ -99,11 +99,14 @@ public class BftBlockHashingTest {
}
private static List<NodeKey> committersNodeKeys() {
final SignatureAlgorithm signatureAlgorithm = SignatureAlgorithmFactory.getInstance();
return IntStream.rangeClosed(1, 4)
.mapToObj(
i ->
NodeKeyUtils.createFrom(
(KeyPair.create(PrivateKey.create(UInt256.valueOf(i).toBytes())))))
(signatureAlgorithm.createKeyPair(
signatureAlgorithm.createPrivateKey(UInt256.valueOf(i).toBytes())))))
.collect(Collectors.toList());
}
@@ -159,7 +162,7 @@ public class BftBlockHashingTest {
BytesValueRLPOutput rlpForHeaderFroCommittersSigning = new BytesValueRLPOutput();
builder.buildBlockHeader().writeTo(rlpForHeaderFroCommittersSigning);
List<Signature> commitSeals =
List<SECPSignature> commitSeals =
COMMITTERS_NODE_KEYS.stream()
.map(nodeKey -> nodeKey.sign(Hash.hash(rlpForHeaderFroCommittersSigning.encoded())))
.collect(Collectors.toList());

View File

@@ -18,7 +18,8 @@ import static org.assertj.core.api.Assertions.assertThat;
import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier;
import org.hyperledger.besu.consensus.ibft.messagedata.IbftV2;
import org.hyperledger.besu.crypto.SECP256K1.Signature;
import org.hyperledger.besu.crypto.SECPSignature;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.ethereum.core.Hash;
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput;
import org.hyperledger.besu.ethereum.rlp.RLP;
@@ -34,7 +35,9 @@ public class CommitPayloadTest {
@Test
public void roundTripRlp() {
final Signature signature = Signature.create(BigInteger.ONE, BigInteger.TEN, (byte) 0);
final SECPSignature signature =
SignatureAlgorithmFactory.getInstance()
.createSignature(BigInteger.ONE, BigInteger.TEN, (byte) 0);
final Hash hash = Hash.fromHexStringLenient("0x8523ba6e7c5f59ae87");
final CommitPayload expectedCommitPayload =

View File

@@ -20,7 +20,9 @@ import static org.assertj.core.api.Assertions.assertThat;
import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier;
import org.hyperledger.besu.consensus.common.bft.ProposedBlockHelpers;
import org.hyperledger.besu.consensus.common.bft.payload.SignedData;
import org.hyperledger.besu.crypto.SECP256K1.Signature;
import org.hyperledger.besu.crypto.SECPSignature;
import org.hyperledger.besu.crypto.SignatureAlgorithm;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.ethereum.core.AddressHelpers;
import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.core.Hash;
@@ -32,6 +34,8 @@ import java.math.BigInteger;
import java.util.Collections;
import java.util.List;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import org.assertj.core.util.Lists;
import org.junit.Test;
@@ -40,6 +44,9 @@ public class PreparedCertificateTest {
private static final ConsensusRoundIdentifier ROUND_IDENTIFIER =
new ConsensusRoundIdentifier(0x1234567890ABCDEFL, 0xFEDCBA98);
private static final Supplier<SignatureAlgorithm> SIGNATURE_ALGORITHM =
Suppliers.memoize(SignatureAlgorithmFactory::getInstance);
@Test
public void roundTripRlpWithNoPreparePayloads() {
final SignedData<ProposalPayload> signedProposalPayload = signedProposal();
@@ -63,7 +70,8 @@ public class PreparedCertificateTest {
final SignedData<ProposalPayload> signedProposalPayload = signedProposal();
final PreparePayload preparePayload =
new PreparePayload(ROUND_IDENTIFIER, Hash.fromHexStringLenient("0x8523ba6e7c5f59ae87"));
final Signature signature = Signature.create(BigInteger.ONE, BigInteger.TEN, (byte) 0);
final SECPSignature signature =
SIGNATURE_ALGORITHM.get().createSignature(BigInteger.ONE, BigInteger.TEN, (byte) 0);
final SignedData<PreparePayload> signedPrepare =
PayloadDeserializers.from(preparePayload, signature);
@@ -85,7 +93,8 @@ public class PreparedCertificateTest {
ProposedBlockHelpers.createProposalBlock(
singletonList(AddressHelpers.ofValue(1)), ROUND_IDENTIFIER);
final ProposalPayload proposalPayload = new ProposalPayload(ROUND_IDENTIFIER, block.getHash());
final Signature signature = Signature.create(BigInteger.ONE, BigInteger.TEN, (byte) 0);
final SECPSignature signature =
SIGNATURE_ALGORITHM.get().createSignature(BigInteger.ONE, BigInteger.TEN, (byte) 0);
return PayloadDeserializers.from(proposalPayload, signature);
}
}

View File

@@ -21,7 +21,8 @@ import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier;
import org.hyperledger.besu.consensus.common.bft.ProposedBlockHelpers;
import org.hyperledger.besu.consensus.common.bft.payload.SignedData;
import org.hyperledger.besu.consensus.ibft.messagedata.IbftV2;
import org.hyperledger.besu.crypto.SECP256K1.Signature;
import org.hyperledger.besu.crypto.SECPSignature;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.ethereum.core.AddressHelpers;
import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.core.Hash;
@@ -60,7 +61,9 @@ public class RoundChangeCertificateTest {
ProposedBlockHelpers.createProposalBlock(
singletonList(AddressHelpers.ofValue(1)), ROUND_IDENTIFIER);
final ProposalPayload proposalPayload = new ProposalPayload(ROUND_IDENTIFIER, block.getHash());
final Signature signature = Signature.create(BigInteger.ONE, BigInteger.TEN, (byte) 0);
final SECPSignature signature =
SignatureAlgorithmFactory.getInstance()
.createSignature(BigInteger.ONE, BigInteger.TEN, (byte) 0);
SignedData<ProposalPayload> signedProposal =
PayloadDeserializers.from(proposalPayload, signature);

View File

@@ -22,7 +22,9 @@ import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier;
import org.hyperledger.besu.consensus.common.bft.ProposedBlockHelpers;
import org.hyperledger.besu.consensus.common.bft.payload.SignedData;
import org.hyperledger.besu.consensus.ibft.messagedata.IbftV2;
import org.hyperledger.besu.crypto.SECP256K1.Signature;
import org.hyperledger.besu.crypto.SECPSignature;
import org.hyperledger.besu.crypto.SignatureAlgorithm;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.ethereum.core.AddressHelpers;
import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.core.Hash;
@@ -34,6 +36,8 @@ import java.math.BigInteger;
import java.util.Collections;
import java.util.Optional;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import org.assertj.core.util.Lists;
import org.junit.Test;
@@ -41,8 +45,10 @@ public class RoundChangePayloadTest {
private static final ConsensusRoundIdentifier ROUND_IDENTIFIER =
new ConsensusRoundIdentifier(0x1234567890ABCDEFL, 0xFEDCBA98);
private static final Signature SIGNATURE =
Signature.create(BigInteger.ONE, BigInteger.TEN, (byte) 0);
private static final Supplier<SignatureAlgorithm> SIGNATURE_ALGORITHM =
Suppliers.memoize(SignatureAlgorithmFactory::getInstance);
private static final SECPSignature SIGNATURE =
SIGNATURE_ALGORITHM.get().createSignature(BigInteger.ONE, BigInteger.TEN, (byte) 0);
@Test
public void roundTripRlpWithNoPreparedCertificate() {
@@ -106,7 +112,8 @@ public class RoundChangePayloadTest {
ProposedBlockHelpers.createProposalBlock(
singletonList(AddressHelpers.ofValue(1)), ROUND_IDENTIFIER);
final ProposalPayload proposalPayload = new ProposalPayload(ROUND_IDENTIFIER, block.getHash());
final Signature signature = Signature.create(BigInteger.ONE, BigInteger.TEN, (byte) 0);
final SECPSignature signature =
SIGNATURE_ALGORITHM.get().createSignature(BigInteger.ONE, BigInteger.TEN, (byte) 0);
return PayloadDeserializers.from(proposalPayload, signature);
}
}

View File

@@ -52,7 +52,7 @@ import org.hyperledger.besu.consensus.ibft.validation.MessageValidator;
import org.hyperledger.besu.consensus.ibft.validation.MessageValidatorFactory;
import org.hyperledger.besu.crypto.NodeKey;
import org.hyperledger.besu.crypto.NodeKeyUtils;
import org.hyperledger.besu.crypto.SECP256K1.Signature;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.Block;
@@ -315,7 +315,8 @@ public class IbftBlockHeightManagerTest {
.createCommit(
futureRoundIdentifier,
Hash.fromHexStringLenient("0"),
Signature.create(BigInteger.ONE, BigInteger.ONE, (byte) 1));
SignatureAlgorithmFactory.getInstance()
.createSignature(BigInteger.ONE, BigInteger.ONE, (byte) 1));
manager.handlePreparePayload(prepare);
manager.handleCommitPayload(commit);

View File

@@ -39,7 +39,8 @@ import org.hyperledger.besu.consensus.ibft.payload.RoundChangeCertificate;
import org.hyperledger.besu.consensus.ibft.validation.MessageValidator;
import org.hyperledger.besu.crypto.NodeKey;
import org.hyperledger.besu.crypto.NodeKeyUtils;
import org.hyperledger.besu.crypto.SECP256K1.Signature;
import org.hyperledger.besu.crypto.SECPSignature;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.chain.MinedBlockObserver;
import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
@@ -89,8 +90,9 @@ public class IbftRoundTest {
private Block proposedBlock;
private BftExtraData proposedExtraData;
private final Signature remoteCommitSeal =
Signature.create(BigInteger.ONE, BigInteger.ONE, (byte) 1);
private final SECPSignature remoteCommitSeal =
SignatureAlgorithmFactory.getInstance()
.createSignature(BigInteger.ONE, BigInteger.ONE, (byte) 1);
@Before
public void setup() {
@@ -216,7 +218,7 @@ public class IbftRoundTest {
final Hash commitSealHash =
BftBlockHashing.calculateDataHashForCommittedSeal(
proposedBlock.getHeader(), proposedExtraData);
final Signature localCommitSeal = nodeKey.sign(commitSealHash);
final SECPSignature localCommitSeal = nodeKey.sign(commitSealHash);
// Receive Proposal Message
round.handleProposalMessage(
@@ -259,7 +261,7 @@ public class IbftRoundTest {
final Hash commitSealHash =
BftBlockHashing.calculateDataHashForCommittedSeal(
proposedBlock.getHeader(), proposedExtraData);
final Signature localCommitSeal = nodeKey.sign(commitSealHash);
final SECPSignature localCommitSeal = nodeKey.sign(commitSealHash);
round.createAndSendProposalMessage(15);
verify(transmitter, never()).multicastCommit(any(), any(), any());

View File

@@ -28,7 +28,8 @@ import org.hyperledger.besu.consensus.ibft.payload.MessageFactory;
import org.hyperledger.besu.consensus.ibft.validation.MessageValidator;
import org.hyperledger.besu.crypto.NodeKey;
import org.hyperledger.besu.crypto.NodeKeyUtils;
import org.hyperledger.besu.crypto.SECP256K1.Signature;
import org.hyperledger.besu.crypto.SignatureAlgorithm;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.core.Hash;
@@ -132,7 +133,8 @@ public class RoundStateTest {
.createCommit(
roundIdentifier,
block.getHash(),
Signature.create(BigInteger.ONE, BigInteger.ONE, (byte) 1));
SignatureAlgorithmFactory.getInstance()
.createSignature(BigInteger.ONE, BigInteger.ONE, (byte) 1));
roundState.addCommitMessage(commit);
assertThat(roundState.isPrepared()).isTrue();
@@ -233,6 +235,7 @@ public class RoundStateTest {
when(messageValidator.validateCommit(any())).thenReturn(true);
final RoundState roundState = new RoundState(roundIdentifier, 2, messageValidator);
final SignatureAlgorithm signatureAlgorithm = SignatureAlgorithmFactory.getInstance();
final Commit firstCommit =
validatorMessageFactories
@@ -240,7 +243,7 @@ public class RoundStateTest {
.createCommit(
roundIdentifier,
block.getHash(),
Signature.create(BigInteger.ONE, BigInteger.TEN, (byte) 1));
signatureAlgorithm.createSignature(BigInteger.ONE, BigInteger.TEN, (byte) 1));
final Commit secondCommit =
validatorMessageFactories
@@ -248,7 +251,7 @@ public class RoundStateTest {
.createCommit(
roundIdentifier,
block.getHash(),
Signature.create(BigInteger.TEN, BigInteger.TEN, (byte) 1));
signatureAlgorithm.createSignature(BigInteger.TEN, BigInteger.TEN, (byte) 1));
final Proposal proposal =
validatorMessageFactories.get(0).createProposal(roundIdentifier, block, Optional.empty());

View File

@@ -14,7 +14,7 @@
*/
package org.hyperledger.besu.consensus.ibftlegacy;
import org.hyperledger.besu.crypto.SECP256K1.Signature;
import org.hyperledger.besu.crypto.SECPSignature;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.Hash;
@@ -116,7 +116,7 @@ public class IbftBlockHashing {
}
private static Bytes encodeExtraDataWithoutCommittedSeals(
final IbftExtraData ibftExtraData, final Signature proposerSeal) {
final IbftExtraData ibftExtraData, final SECPSignature proposerSeal) {
final BytesValueRLPOutput extraDataEncoding = new BytesValueRLPOutput();
extraDataEncoding.startList();
extraDataEncoding.writeList(

View File

@@ -17,7 +17,9 @@ package org.hyperledger.besu.consensus.ibftlegacy;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import org.hyperledger.besu.crypto.SECP256K1.Signature;
import org.hyperledger.besu.crypto.SECPSignature;
import org.hyperledger.besu.crypto.SignatureAlgorithm;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.ParsedExtraData;
@@ -27,6 +29,8 @@ import org.hyperledger.besu.ethereum.rlp.RLPInput;
import java.util.Collection;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.tuweni.bytes.Bytes;
@@ -39,16 +43,18 @@ public class IbftExtraData implements ParsedExtraData {
private static final Logger LOG = LogManager.getLogger();
public static final int EXTRA_VANITY_LENGTH = 32;
private static final Supplier<SignatureAlgorithm> SIGNATURE_ALGORITHM =
Suppliers.memoize(SignatureAlgorithmFactory::getInstance);
private final Bytes vanityData;
private final Collection<Signature> seals;
private final Signature proposerSeal;
private final Collection<SECPSignature> seals;
private final SECPSignature proposerSeal;
private final Collection<Address> validators;
public IbftExtraData(
final Bytes vanityData,
final Collection<Signature> seals,
final Signature proposerSeal,
final Collection<SECPSignature> seals,
final SECPSignature proposerSeal,
final Collection<Address> validators) {
checkNotNull(vanityData);
@@ -84,16 +90,17 @@ public class IbftExtraData implements ParsedExtraData {
rlpInput.enterList(); // This accounts for the "root node" which contains IBFT data items.
final Collection<Address> validators = rlpInput.readList(Address::readFrom);
final Signature proposerSeal = parseProposerSeal(rlpInput);
final Collection<Signature> seals = rlpInput.readList(rlp -> Signature.decode(rlp.readBytes()));
final SECPSignature proposerSeal = parseProposerSeal(rlpInput);
final Collection<SECPSignature> seals =
rlpInput.readList(rlp -> SIGNATURE_ALGORITHM.get().decodeSignature(rlp.readBytes()));
rlpInput.leaveList();
return new IbftExtraData(vanityData, seals, proposerSeal, validators);
}
private static Signature parseProposerSeal(final RLPInput rlpInput) {
private static SECPSignature parseProposerSeal(final RLPInput rlpInput) {
final Bytes data = rlpInput.readBytes();
return data.isZero() ? null : Signature.decode(data);
return data.isZero() ? null : SIGNATURE_ALGORITHM.get().decodeSignature(data);
}
public Bytes encode() {
@@ -116,11 +123,11 @@ public class IbftExtraData implements ParsedExtraData {
return vanityData;
}
public Collection<Signature> getSeals() {
public Collection<SECPSignature> getSeals() {
return seals;
}
public Signature getProposerSeal() {
public SECPSignature getProposerSeal() {
return proposerSeal;
}

View File

@@ -17,8 +17,8 @@ package org.hyperledger.besu.consensus.ibftlegacy.blockcreation;
import org.hyperledger.besu.consensus.ibftlegacy.IbftBlockHashing;
import org.hyperledger.besu.consensus.ibftlegacy.IbftExtraData;
import org.hyperledger.besu.consensus.ibftlegacy.IbftHelpers;
import org.hyperledger.besu.crypto.SECP256K1;
import org.hyperledger.besu.crypto.SECP256K1.KeyPair;
import org.hyperledger.besu.crypto.KeyPair;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.blockcreation.AbstractBlockCreator;
import org.hyperledger.besu.ethereum.blockcreation.GasLimitCalculator;
@@ -110,7 +110,7 @@ public class IbftBlockCreator extends AbstractBlockCreator {
return new IbftExtraData(
extraData.getVanityData(),
extraData.getSeals(),
SECP256K1.sign(hashToSign, nodeKeys),
SignatureAlgorithmFactory.getInstance().sign(hashToSign, nodeKeys),
extraData.getValidators());
}
}

View File

@@ -16,7 +16,9 @@ package org.hyperledger.besu.consensus.ibftlegacy;
import static org.assertj.core.api.Assertions.assertThat;
import org.hyperledger.besu.crypto.SECP256K1.Signature;
import org.hyperledger.besu.crypto.SECPSignature;
import org.hyperledger.besu.crypto.SignatureAlgorithm;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput;
import org.hyperledger.besu.ethereum.rlp.RLPException;
@@ -26,6 +28,8 @@ import java.util.Arrays;
import java.util.List;
import java.util.Random;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.collect.Lists;
import org.apache.tuweni.bytes.Bytes;
import org.bouncycastle.util.encoders.Hex;
@@ -33,11 +37,15 @@ import org.junit.Test;
public class BftExtraDataTest {
private static final Supplier<SignatureAlgorithm> SIGNATURE_ALGORITHM =
Suppliers.memoize(SignatureAlgorithmFactory::getInstance);
@Test
public void emptyListsConstituteValidContent() {
final Signature proposerSeal = Signature.create(BigInteger.ONE, BigInteger.ONE, (byte) 0);
final SECPSignature proposerSeal =
SIGNATURE_ALGORITHM.get().createSignature(BigInteger.ONE, BigInteger.ONE, (byte) 0);
final List<Address> validators = Lists.newArrayList();
final List<Signature> committerSeals = Lists.newArrayList();
final List<SECPSignature> committerSeals = Lists.newArrayList();
final BytesValueRLPOutput encoder = new BytesValueRLPOutput();
encoder.startList();
@@ -62,11 +70,12 @@ public class BftExtraDataTest {
@Test
public void fullyPopulatedDataProducesCorrectlyFormedExtraDataObject() {
final List<Address> validators = Arrays.asList(Address.ECREC, Address.SHA256);
final Signature proposerSeal = Signature.create(BigInteger.ONE, BigInteger.ONE, (byte) 0);
final List<Signature> committerSeals =
final SECPSignature proposerSeal =
SIGNATURE_ALGORITHM.get().createSignature(BigInteger.ONE, BigInteger.ONE, (byte) 0);
final List<SECPSignature> committerSeals =
Arrays.asList(
Signature.create(BigInteger.ONE, BigInteger.TEN, (byte) 0),
Signature.create(BigInteger.TEN, BigInteger.ONE, (byte) 0));
SIGNATURE_ALGORITHM.get().createSignature(BigInteger.ONE, BigInteger.TEN, (byte) 0),
SIGNATURE_ALGORITHM.get().createSignature(BigInteger.TEN, BigInteger.ONE, (byte) 0));
final BytesValueRLPOutput encoder = new BytesValueRLPOutput();
encoder.startList(); // This is required to create a "root node" for all RLP'd data
@@ -91,9 +100,10 @@ public class BftExtraDataTest {
@Test(expected = RLPException.class)
public void incorrectlyStructuredRlpThrowsException() {
final Signature proposerSeal = Signature.create(BigInteger.ONE, BigInteger.ONE, (byte) 0);
final SECPSignature proposerSeal =
SIGNATURE_ALGORITHM.get().createSignature(BigInteger.ONE, BigInteger.ONE, (byte) 0);
final List<Address> validators = Lists.newArrayList();
final List<Signature> committerSeals = Lists.newArrayList();
final List<SECPSignature> committerSeals = Lists.newArrayList();
final BytesValueRLPOutput encoder = new BytesValueRLPOutput();
encoder.startList();
@@ -111,11 +121,12 @@ public class BftExtraDataTest {
@Test(expected = RLPException.class)
public void incorrectlySizedVanityDataThrowsException() {
final List<Address> validators = Arrays.asList(Address.ECREC, Address.SHA256);
final Signature proposerSeal = Signature.create(BigInteger.ONE, BigInteger.ONE, (byte) 0);
final List<Signature> committerSeals =
final SECPSignature proposerSeal =
SIGNATURE_ALGORITHM.get().createSignature(BigInteger.ONE, BigInteger.ONE, (byte) 0);
final List<SECPSignature> committerSeals =
Arrays.asList(
Signature.create(BigInteger.ONE, BigInteger.TEN, (byte) 0),
Signature.create(BigInteger.TEN, BigInteger.ONE, (byte) 0));
SIGNATURE_ALGORITHM.get().createSignature(BigInteger.ONE, BigInteger.TEN, (byte) 0),
SIGNATURE_ALGORITHM.get().createSignature(BigInteger.TEN, BigInteger.ONE, (byte) 0));
final BytesValueRLPOutput encoder = new BytesValueRLPOutput();
encoder.startList();

View File

@@ -24,9 +24,10 @@ import static org.mockito.Mockito.when;
import org.hyperledger.besu.consensus.common.VoteTally;
import org.hyperledger.besu.consensus.common.VoteTallyCache;
import org.hyperledger.besu.consensus.common.bft.BftContext;
import org.hyperledger.besu.crypto.SECP256K1;
import org.hyperledger.besu.crypto.SECP256K1.KeyPair;
import org.hyperledger.besu.crypto.SECP256K1.Signature;
import org.hyperledger.besu.crypto.KeyPair;
import org.hyperledger.besu.crypto.SECPSignature;
import org.hyperledger.besu.crypto.SignatureAlgorithm;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.BlockHeader;
@@ -40,11 +41,16 @@ import java.math.BigInteger;
import java.util.Collection;
import java.util.List;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import org.apache.tuweni.bytes.Bytes;
import org.junit.Test;
public class IbftBlockHeaderValidationRulesetFactoryTest {
private static final Supplier<SignatureAlgorithm> SIGNATURE_ALGORITHM =
Suppliers.memoize(SignatureAlgorithmFactory::getInstance);
private ProtocolContext setupContextWithValidators(final Collection<Address> validators) {
final BftContext bftContext = mock(BftContext.class);
final VoteTallyCache mockCache = mock(VoteTallyCache.class);
@@ -58,7 +64,7 @@ public class IbftBlockHeaderValidationRulesetFactoryTest {
@Test
public void ibftValidateHeaderPasses() {
final KeyPair proposerKeyPair = KeyPair.generate();
final KeyPair proposerKeyPair = SIGNATURE_ALGORITHM.get().generateKeyPair();
final Address proposerAddress =
Address.extract(Hash.hash(proposerKeyPair.getPublicKey().getEncodedBytes()));
@@ -81,7 +87,7 @@ public class IbftBlockHeaderValidationRulesetFactoryTest {
@Test
public void ibftValidateHeaderFails() {
final KeyPair proposerKeyPair = KeyPair.generate();
final KeyPair proposerKeyPair = SIGNATURE_ALGORITHM.get().generateKeyPair();
final Address proposerAddress =
Address.extract(Hash.hash(proposerKeyPair.getPublicKey().getEncodedBytes()));
@@ -126,7 +132,7 @@ public class IbftBlockHeaderValidationRulesetFactoryTest {
new IbftExtraData(
Bytes.wrap(new byte[IbftExtraData.EXTRA_VANITY_LENGTH]),
emptyList(),
Signature.create(BigInteger.ONE, BigInteger.ONE, (byte) 0),
SIGNATURE_ALGORITHM.get().createSignature(BigInteger.ONE, BigInteger.ONE, (byte) 0),
validators);
builder.extraData(initialIbftExtraData.encode());
@@ -134,7 +140,8 @@ public class IbftBlockHeaderValidationRulesetFactoryTest {
final Hash proposerSealHash =
IbftBlockHashing.calculateDataHashForProposerSeal(parentHeader, initialIbftExtraData);
final Signature proposerSignature = SECP256K1.sign(proposerSealHash, proposerKeyPair);
final SECPSignature proposerSignature =
SIGNATURE_ALGORITHM.get().sign(proposerSealHash, proposerKeyPair);
final IbftExtraData proposedData =
new IbftExtraData(
@@ -145,8 +152,8 @@ public class IbftBlockHeaderValidationRulesetFactoryTest {
final Hash headerHashForCommitters =
IbftBlockHashing.calculateDataHashForCommittedSeal(parentHeader, proposedData);
final Signature proposerAsCommitterSignature =
SECP256K1.sign(headerHashForCommitters, proposerKeyPair);
final SECPSignature proposerAsCommitterSignature =
SIGNATURE_ALGORITHM.get().sign(headerHashForCommitters, proposerKeyPair);
final IbftExtraData sealedData =
new IbftExtraData(

View File

@@ -20,7 +20,8 @@ import static org.hyperledger.besu.consensus.common.VoteType.ADD;
import static org.hyperledger.besu.consensus.common.VoteType.DROP;
import org.hyperledger.besu.consensus.common.ValidatorVote;
import org.hyperledger.besu.crypto.SECP256K1.KeyPair;
import org.hyperledger.besu.crypto.KeyPair;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.AddressHelpers;
import org.hyperledger.besu.ethereum.core.BlockHeader;
@@ -37,7 +38,8 @@ import org.junit.Test;
public class IbftLegacyBlockInterfaceTest {
private static final KeyPair proposerKeys = KeyPair.generate();
private static final KeyPair proposerKeys =
SignatureAlgorithmFactory.getInstance().generateKeyPair();
private static final Address proposerAddress =
Util.publicKeyToAddress(proposerKeys.getPublicKey());
private static final List<Address> validatorList = singletonList(proposerAddress);

View File

@@ -14,9 +14,9 @@
*/
package org.hyperledger.besu.consensus.ibftlegacy;
import org.hyperledger.besu.crypto.SECP256K1;
import org.hyperledger.besu.crypto.SECP256K1.KeyPair;
import org.hyperledger.besu.crypto.SECP256K1.Signature;
import org.hyperledger.besu.crypto.KeyPair;
import org.hyperledger.besu.crypto.SECPSignature;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;
@@ -42,7 +42,8 @@ public class TestHelpers {
IbftBlockHashing.calculateDataHashForProposerSeal(
blockHeaderBuilder.buildHeader(), unsignedExtraData);
final Signature proposerSignature = SECP256K1.sign(signingHash, signer);
final SECPSignature proposerSignature =
SignatureAlgorithmFactory.getInstance().sign(signingHash, signer);
final IbftExtraData signedExtraData =
new IbftExtraData(

View File

@@ -25,7 +25,8 @@ import org.hyperledger.besu.config.GenesisConfigFile;
import org.hyperledger.besu.consensus.ibftlegacy.IbftBlockHeaderValidationRulesetFactory;
import org.hyperledger.besu.consensus.ibftlegacy.IbftExtraData;
import org.hyperledger.besu.consensus.ibftlegacy.IbftProtocolSchedule;
import org.hyperledger.besu.crypto.SECP256K1.KeyPair;
import org.hyperledger.besu.crypto.KeyPair;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
import org.hyperledger.besu.ethereum.core.Address;
@@ -68,7 +69,7 @@ public class BftBlockCreatorTest {
when(blockchain.getChainHeadHash()).thenReturn(parentHeader.getHash());
when(blockchain.getBlockHeader(any())).thenReturn(optionalHeader);
final KeyPair nodeKeys = KeyPair.generate();
final KeyPair nodeKeys = SignatureAlgorithmFactory.getInstance().generateKeyPair();
// Add the local node as a validator (can't propose a block if node is not a validator).
final Address localAddr = Address.extract(Hash.hash(nodeKeys.getPublicKey().getEncodedBytes()));
final List<Address> initialValidatorList =

View File

@@ -21,9 +21,10 @@ import static org.hyperledger.besu.consensus.common.bft.BftContextBuilder.setupC
import org.hyperledger.besu.consensus.ibftlegacy.IbftBlockHashing;
import org.hyperledger.besu.consensus.ibftlegacy.IbftExtraData;
import org.hyperledger.besu.crypto.SECP256K1;
import org.hyperledger.besu.crypto.SECP256K1.KeyPair;
import org.hyperledger.besu.crypto.SECP256K1.Signature;
import org.hyperledger.besu.crypto.KeyPair;
import org.hyperledger.besu.crypto.SECPSignature;
import org.hyperledger.besu.crypto.SignatureAlgorithm;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.AddressHelpers;
@@ -43,6 +44,8 @@ import org.junit.Test;
public class BftExtraDataValidationRuleTest {
private final SignatureAlgorithm signatureAlgorithm = SignatureAlgorithmFactory.getInstance();
private BlockHeader createProposedBlockHeader(
final KeyPair proposerKeyPair, final List<Address> validators) {
final BlockHeaderTestFixture builder = new BlockHeaderTestFixture();
@@ -58,7 +61,8 @@ public class BftExtraDataValidationRuleTest {
// Hash the header (ignoring committer and proposer seals), and create signature
final Hash proposerSealHash =
IbftBlockHashing.calculateDataHashForProposerSeal(header, initialIbftExtraData);
final Signature proposerSignature = SECP256K1.sign(proposerSealHash, proposerKeyPair);
final SECPSignature proposerSignature =
signatureAlgorithm.sign(proposerSealHash, proposerKeyPair);
// Construct a new extraData block, containing the constructed proposer signature
final IbftExtraData proposedData =
@@ -80,9 +84,9 @@ public class BftExtraDataValidationRuleTest {
final Hash headerHashForCommitters =
IbftBlockHashing.calculateDataHashForCommittedSeal(header, extraDataInHeader);
final List<Signature> commitSeals =
final List<SECPSignature> commitSeals =
committerKeyPairs.stream()
.map(keys -> SECP256K1.sign(headerHashForCommitters, keys))
.map(keys -> signatureAlgorithm.sign(headerHashForCommitters, keys))
.collect(Collectors.toList());
return new IbftExtraData(
@@ -96,7 +100,7 @@ public class BftExtraDataValidationRuleTest {
public void correctlyConstructedHeaderPassesValidation() {
final BlockHeaderTestFixture builder = new BlockHeaderTestFixture();
builder.number(1); // must NOT be block 0, as that should not contain seals at all
final KeyPair proposerKeyPair = KeyPair.generate();
final KeyPair proposerKeyPair = signatureAlgorithm.generateKeyPair();
final Address proposerAddress =
Address.extract(Hash.hash(proposerKeyPair.getPublicKey().getEncodedBytes()));
@@ -122,7 +126,7 @@ public class BftExtraDataValidationRuleTest {
public void insufficientCommitSealsFailsValidation() {
final BlockHeaderTestFixture builder = new BlockHeaderTestFixture();
builder.number(1); // must NOT be block 0, as that should not contain seals at all
final KeyPair proposerKeyPair = KeyPair.generate();
final KeyPair proposerKeyPair = signatureAlgorithm.generateKeyPair();
final Address proposerAddress =
Address.extract(Hash.hash(proposerKeyPair.getPublicKey().getEncodedBytes()));
@@ -146,7 +150,7 @@ public class BftExtraDataValidationRuleTest {
public void outOfOrderValidatorListFailsValidation() {
final BlockHeaderTestFixture builder = new BlockHeaderTestFixture();
builder.number(1); // must NOT be block 0, as that should not contain seals at all
final KeyPair proposerKeyPair = KeyPair.generate();
final KeyPair proposerKeyPair = signatureAlgorithm.generateKeyPair();
final Address proposerAddress =
Address.extract(Hash.hash(proposerKeyPair.getPublicKey().getEncodedBytes()));
@@ -175,7 +179,7 @@ public class BftExtraDataValidationRuleTest {
public void proposerNotInValidatorListFailsValidation() {
final BlockHeaderTestFixture builder = new BlockHeaderTestFixture();
builder.number(1); // must NOT be block 0, as that should not contain seals at all
final KeyPair proposerKeyPair = KeyPair.generate();
final KeyPair proposerKeyPair = signatureAlgorithm.generateKeyPair();
final Address proposerAddress =
Address.extract(Hash.hash(proposerKeyPair.getPublicKey().getEncodedBytes()));
@@ -204,7 +208,7 @@ public class BftExtraDataValidationRuleTest {
public void mismatchingReportedValidatorsVsLocallyStoredListFailsValidation() {
final BlockHeaderTestFixture builder = new BlockHeaderTestFixture();
builder.number(1); // must NOT be block 0, as that should not contain seals at all
final KeyPair proposerKeyPair = KeyPair.generate();
final KeyPair proposerKeyPair = signatureAlgorithm.generateKeyPair();
final Address proposerAddress =
Address.extract(Hash.hash(proposerKeyPair.getPublicKey().getEncodedBytes()));
@@ -235,7 +239,7 @@ public class BftExtraDataValidationRuleTest {
public void committerNotInValidatorListFailsValidation() {
final BlockHeaderTestFixture builder = new BlockHeaderTestFixture();
builder.number(1); // must NOT be block 0, as that should not contain seals at all
final KeyPair proposerKeyPair = KeyPair.generate();
final KeyPair proposerKeyPair = signatureAlgorithm.generateKeyPair();
final Address proposerAddress =
Address.extract(Hash.hash(proposerKeyPair.getPublicKey().getEncodedBytes()));
@@ -244,7 +248,7 @@ public class BftExtraDataValidationRuleTest {
BlockHeader header = createProposedBlockHeader(proposerKeyPair, validators);
// Insert an extraData block with committer seals.
final KeyPair nonValidatorKeyPair = KeyPair.generate();
final KeyPair nonValidatorKeyPair = signatureAlgorithm.generateKeyPair();
final IbftExtraData commitedExtraData =
createExtraDataWithCommitSeals(header, singletonList(nonValidatorKeyPair));
builder.extraData(commitedExtraData.encode());
@@ -293,7 +297,7 @@ public class BftExtraDataValidationRuleTest {
final int validatorCount, final int committerCount, final boolean useTwoThirds) {
final BlockHeaderTestFixture builder = new BlockHeaderTestFixture();
builder.number(1); // must NOT be block 0, as that should not contain seals at all
final KeyPair proposerKeyPair = KeyPair.generate();
final KeyPair proposerKeyPair = signatureAlgorithm.generateKeyPair();
final Address proposerAddress =
Address.extract(Hash.hash(proposerKeyPair.getPublicKey().getEncodedBytes()));
@@ -303,7 +307,7 @@ public class BftExtraDataValidationRuleTest {
validators.add(proposerAddress);
committerKeys.add(proposerKeyPair);
for (int i = 0; i < validatorCount - 1; i++) { // need -1 to account for proposer
final KeyPair committerKeyPair = KeyPair.generate();
final KeyPair committerKeyPair = signatureAlgorithm.generateKeyPair();
committerKeys.add(committerKeyPair);
validators.add(Address.extract(Hash.hash(committerKeyPair.getPublicKey().getEncodedBytes())));
}

View File

@@ -96,6 +96,7 @@ dependencies {
integrationTestImplementation 'org.mockito:mockito-core'
referenceTestImplementation 'junit:junit'
referenceTestImplementation 'com.google.guava:guava'
referenceTestImplementation 'org.assertj:assertj-core'
referenceTestImplementation 'org.mockito:mockito-core'
referenceTestImplementation 'com.fasterxml.jackson.core:jackson-databind'

View File

@@ -22,7 +22,7 @@ import org.hyperledger.besu.consensus.qbft.payload.CommitPayload;
import org.hyperledger.besu.consensus.qbft.payload.MessageFactory;
import org.hyperledger.besu.consensus.qbft.statemachine.PreparedCertificate;
import org.hyperledger.besu.crypto.NodeKey;
import org.hyperledger.besu.crypto.SECP256K1.Signature;
import org.hyperledger.besu.crypto.SECPSignature;
import org.hyperledger.besu.ethereum.core.Block;
public class IntegrationTestHelpers {
@@ -32,7 +32,7 @@ public class IntegrationTestHelpers {
final BftExtraData extraData = BftExtraData.decode(block.getHeader());
final Signature commitSeal =
final SECPSignature commitSeal =
nodeKey.sign(
BftBlockHashing.calculateDataHashForCommittedSeal(block.getHeader(), extraData));

View File

@@ -31,7 +31,7 @@ import org.hyperledger.besu.consensus.qbft.messagewrappers.RoundChange;
import org.hyperledger.besu.consensus.qbft.payload.PreparePayload;
import org.hyperledger.besu.consensus.qbft.payload.RoundChangePayload;
import org.hyperledger.besu.consensus.qbft.statemachine.PreparedCertificate;
import org.hyperledger.besu.crypto.SECP256K1.Signature;
import org.hyperledger.besu.crypto.SECPSignature;
import org.hyperledger.besu.ethereum.core.Hash;
import org.hyperledger.besu.ethereum.p2p.rlpx.wire.MessageData;
@@ -72,7 +72,7 @@ public class RoundSpecificPeers {
peers.forEach(ValidatorPeer::clearReceivedMessages);
}
public List<Signature> sign(final Hash digest) {
public List<SECPSignature> sign(final Hash digest) {
return peers.stream().map(peer -> peer.getBlockSignature(digest)).collect(Collectors.toList());
}

View File

@@ -31,7 +31,7 @@ import org.hyperledger.besu.consensus.qbft.payload.MessageFactory;
import org.hyperledger.besu.consensus.qbft.payload.PreparePayload;
import org.hyperledger.besu.consensus.qbft.payload.RoundChangePayload;
import org.hyperledger.besu.consensus.qbft.statemachine.PreparedCertificate;
import org.hyperledger.besu.crypto.SECP256K1.Signature;
import org.hyperledger.besu.crypto.SECPSignature;
import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.core.Hash;
@@ -64,13 +64,13 @@ public class ValidatorPeer extends DefaultValidatorPeer {
}
public Commit injectCommit(final ConsensusRoundIdentifier rId, final Hash digest) {
final Signature commitSeal = nodeKey.sign(digest);
final SECPSignature commitSeal = nodeKey.sign(digest);
return injectCommit(rId, digest, commitSeal);
}
public Commit injectCommit(
final ConsensusRoundIdentifier rId, final Hash digest, final Signature commitSeal) {
final ConsensusRoundIdentifier rId, final Hash digest, final SECPSignature commitSeal) {
final Commit payload = messageFactory.createCommit(rId, digest, commitSeal);
injectMessage(CommitMessageData.create(payload));
return payload;

View File

@@ -29,7 +29,7 @@ import org.hyperledger.besu.consensus.qbft.support.TestContextBuilder;
import org.hyperledger.besu.consensus.qbft.support.ValidatorPeer;
import org.hyperledger.besu.crypto.NodeKey;
import org.hyperledger.besu.crypto.NodeKeyUtils;
import org.hyperledger.besu.crypto.SECP256K1.Signature;
import org.hyperledger.besu.crypto.SECPSignature;
import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.core.Hash;
import org.hyperledger.besu.ethereum.core.Util;
@@ -146,7 +146,7 @@ public class SpuriousBehaviourTest {
// nonProposer-2 will generate an invalid seal
final ValidatorPeer badSealPeer = peers.getNonProposing(2);
final Signature illegalSeal = badSealPeer.getnodeKey().sign(Hash.ZERO);
final SECPSignature illegalSeal = badSealPeer.getnodeKey().sign(Hash.ZERO);
badSealPeer.injectCommit(roundId, proposedBlock.getHash(), illegalSeal);
assertThat(context.getCurrentChainHeight()).isEqualTo(0);

View File

@@ -35,7 +35,8 @@ import org.hyperledger.besu.consensus.qbft.statemachine.RoundState;
import org.hyperledger.besu.consensus.qbft.validation.MessageValidator;
import org.hyperledger.besu.crypto.NodeKey;
import org.hyperledger.besu.crypto.NodeKeyUtils;
import org.hyperledger.besu.crypto.SECP256K1.Signature;
import org.hyperledger.besu.crypto.SECPSignature;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.chain.MinedBlockObserver;
import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
@@ -80,8 +81,9 @@ public class QbftRoundIntegrationTest {
private Block proposedBlock;
private final Signature remoteCommitSeal =
Signature.create(BigInteger.ONE, BigInteger.ONE, (byte) 1);
private final SECPSignature remoteCommitSeal =
SignatureAlgorithmFactory.getInstance()
.createSignature(BigInteger.ONE, BigInteger.ONE, (byte) 1);
@Before
public void setup() {

View File

@@ -17,7 +17,7 @@ package org.hyperledger.besu.consensus.qbft.messagewrappers;
import org.hyperledger.besu.consensus.common.bft.messagewrappers.BftMessage;
import org.hyperledger.besu.consensus.common.bft.payload.SignedData;
import org.hyperledger.besu.consensus.qbft.payload.CommitPayload;
import org.hyperledger.besu.crypto.SECP256K1.Signature;
import org.hyperledger.besu.crypto.SECPSignature;
import org.hyperledger.besu.ethereum.core.Hash;
import org.hyperledger.besu.ethereum.rlp.RLP;
import org.hyperledger.besu.ethereum.rlp.RLPInput;
@@ -30,7 +30,7 @@ public class Commit extends BftMessage<CommitPayload> {
super(payload);
}
public Signature getCommitSeal() {
public SECPSignature getCommitSeal() {
return getPayload().getCommitSeal();
}

View File

@@ -29,7 +29,7 @@ import org.hyperledger.besu.consensus.qbft.payload.MessageFactory;
import org.hyperledger.besu.consensus.qbft.payload.PreparePayload;
import org.hyperledger.besu.consensus.qbft.payload.RoundChangePayload;
import org.hyperledger.besu.consensus.qbft.statemachine.PreparedCertificate;
import org.hyperledger.besu.crypto.SECP256K1.Signature;
import org.hyperledger.besu.crypto.SECPSignature;
import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.core.Hash;
import org.hyperledger.besu.plugin.services.securitymodule.SecurityModuleException;
@@ -85,7 +85,7 @@ public class QbftMessageTransmitter {
public void multicastCommit(
final ConsensusRoundIdentifier roundIdentifier,
final Hash digest,
final Signature commitSeal) {
final SECPSignature commitSeal) {
try {
final Commit data = messageFactory.createCommit(roundIdentifier, digest, commitSeal);

View File

@@ -17,7 +17,8 @@ package org.hyperledger.besu.consensus.qbft.payload;
import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier;
import org.hyperledger.besu.consensus.common.bft.payload.Payload;
import org.hyperledger.besu.consensus.qbft.messagedata.QbftV1;
import org.hyperledger.besu.crypto.SECP256K1.Signature;
import org.hyperledger.besu.crypto.SECPSignature;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.ethereum.core.Hash;
import org.hyperledger.besu.ethereum.rlp.RLPInput;
import org.hyperledger.besu.ethereum.rlp.RLPOutput;
@@ -29,12 +30,12 @@ public class CommitPayload implements Payload {
private static final int TYPE = QbftV1.COMMIT;
private final ConsensusRoundIdentifier roundIdentifier;
private final Hash digest;
private final Signature commitSeal;
private final SECPSignature commitSeal;
public CommitPayload(
final ConsensusRoundIdentifier roundIdentifier,
final Hash digest,
final Signature commitSeal) {
final SECPSignature commitSeal) {
this.roundIdentifier = roundIdentifier;
this.digest = digest;
this.commitSeal = commitSeal;
@@ -44,7 +45,8 @@ public class CommitPayload implements Payload {
rlpInput.enterList();
final ConsensusRoundIdentifier roundIdentifier = ConsensusRoundIdentifier.readFrom(rlpInput);
final Hash digest = Payload.readDigest(rlpInput);
final Signature commitSeal = rlpInput.readBytes(Signature::decode);
final SECPSignature commitSeal =
rlpInput.readBytes(SignatureAlgorithmFactory.getInstance()::decodeSignature);
rlpInput.leaveList();
return new CommitPayload(roundIdentifier, digest, commitSeal);
@@ -68,7 +70,7 @@ public class CommitPayload implements Payload {
return digest;
}
public Signature getCommitSeal() {
public SECPSignature getCommitSeal() {
return commitSeal;
}

View File

@@ -25,7 +25,7 @@ import org.hyperledger.besu.consensus.qbft.messagewrappers.Proposal;
import org.hyperledger.besu.consensus.qbft.messagewrappers.RoundChange;
import org.hyperledger.besu.consensus.qbft.statemachine.PreparedCertificate;
import org.hyperledger.besu.crypto.NodeKey;
import org.hyperledger.besu.crypto.SECP256K1.Signature;
import org.hyperledger.besu.crypto.SECPSignature;
import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.core.Hash;
@@ -60,7 +60,7 @@ public class MessageFactory {
public Commit createCommit(
final ConsensusRoundIdentifier roundIdentifier,
final Hash digest,
final Signature commitSeal) {
final SECPSignature commitSeal) {
final CommitPayload payload = new CommitPayload(roundIdentifier, digest, commitSeal);
return new Commit(createSignedMessage(payload));
}
@@ -93,7 +93,7 @@ public class MessageFactory {
}
private <M extends Payload> SignedData<M> createSignedMessage(final M payload) {
final Signature signature = nodeKey.sign(hashForSignature(payload));
final SECPSignature signature = nodeKey.sign(hashForSignature(payload));
return SignedData.create(payload, signature);
}
}

View File

@@ -33,7 +33,7 @@ import org.hyperledger.besu.consensus.qbft.payload.MessageFactory;
import org.hyperledger.besu.consensus.qbft.payload.PreparePayload;
import org.hyperledger.besu.consensus.qbft.payload.RoundChangePayload;
import org.hyperledger.besu.crypto.NodeKey;
import org.hyperledger.besu.crypto.SECP256K1.Signature;
import org.hyperledger.besu.crypto.SECPSignature;
import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.chain.MinedBlockObserver;
import org.hyperledger.besu.ethereum.core.Block;
@@ -189,7 +189,7 @@ public class QbftRound {
if (blockAccepted) {
final Block block = roundState.getProposedBlock().get();
final Signature commitSeal;
final SECPSignature commitSeal;
try {
commitSeal = createCommitSeal(block);
} catch (final SecurityModuleException e) {
@@ -275,7 +275,7 @@ public class QbftRound {
}
}
private Signature createCommitSeal(final Block block) {
private SECPSignature createCommitSeal(final Block block) {
final BlockHeader proposedHeader = block.getHeader();
final BftExtraData extraData = BftExtraData.decode(proposedHeader);
final Hash commitHash =

View File

@@ -19,7 +19,7 @@ import org.hyperledger.besu.consensus.qbft.messagewrappers.Commit;
import org.hyperledger.besu.consensus.qbft.messagewrappers.Prepare;
import org.hyperledger.besu.consensus.qbft.messagewrappers.Proposal;
import org.hyperledger.besu.consensus.qbft.validation.MessageValidator;
import org.hyperledger.besu.crypto.SECP256K1.Signature;
import org.hyperledger.besu.crypto.SECPSignature;
import org.hyperledger.besu.ethereum.core.Block;
import java.util.Collection;
@@ -119,7 +119,7 @@ public class RoundState {
return committed;
}
public Collection<Signature> getCommitSeals() {
public Collection<SECPSignature> getCommitSeals() {
return commitMessages.stream()
.map(cp -> cp.getSignedPayload().getPayload().getCommitSeal())
.collect(Collectors.toList());

View File

@@ -19,14 +19,19 @@ import org.hyperledger.besu.consensus.common.bft.messagewrappers.BftMessage;
import org.hyperledger.besu.consensus.common.bft.payload.SignedData;
import org.hyperledger.besu.consensus.qbft.messagewrappers.Commit;
import org.hyperledger.besu.consensus.qbft.payload.CommitPayload;
import org.hyperledger.besu.crypto.SECP256K1.Signature;
import org.hyperledger.besu.crypto.SignatureAlgorithm;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.ethereum.core.Hash;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import org.apache.tuweni.bytes.Bytes;
public class CommitMessage implements RlpTestCaseMessage {
private static final Supplier<SignatureAlgorithm> SIGNATURE_ALGORITHM =
Suppliers.memoize(SignatureAlgorithmFactory::getInstance);
private final UnsignedCommit unsignedCommit;
private final String signature;
@@ -49,9 +54,13 @@ public class CommitMessage implements RlpTestCaseMessage {
new CommitPayload(
new ConsensusRoundIdentifier(unsignedCommit.sequence, unsignedCommit.round),
Hash.fromHexStringLenient(unsignedCommit.digest),
Signature.decode(Bytes.fromHexString(unsignedCommit.commitSeal)));
SIGNATURE_ALGORITHM
.get()
.decodeSignature(Bytes.fromHexString(unsignedCommit.commitSeal)));
final SignedData<CommitPayload> signedCommitPayload =
SignedData.create(commitPayload, Signature.decode(Bytes.fromHexString(signature)));
SignedData.create(
commitPayload,
SIGNATURE_ALGORITHM.get().decodeSignature(Bytes.fromHexString(signature)));
return new Commit(signedCommitPayload);
}

View File

@@ -19,7 +19,7 @@ import org.hyperledger.besu.consensus.common.bft.messagewrappers.BftMessage;
import org.hyperledger.besu.consensus.common.bft.payload.SignedData;
import org.hyperledger.besu.consensus.qbft.messagewrappers.Prepare;
import org.hyperledger.besu.consensus.qbft.payload.PreparePayload;
import org.hyperledger.besu.crypto.SECP256K1.Signature;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.ethereum.core.Hash;
import com.fasterxml.jackson.annotation.JsonCreator;
@@ -55,7 +55,8 @@ public class PrepareMessage implements RlpTestCaseMessage {
new PreparePayload(
new ConsensusRoundIdentifier(unsignedPrepare.sequence, unsignedPrepare.round),
Hash.fromHexString(unsignedPrepare.digest)),
Signature.decode(Bytes.fromHexString(prepareMessage.signature)));
SignatureAlgorithmFactory.getInstance()
.decodeSignature(Bytes.fromHexString(prepareMessage.signature)));
}
public static class UnsignedPrepare {

View File

@@ -23,7 +23,7 @@ import org.hyperledger.besu.consensus.qbft.payload.PreparePayload;
import org.hyperledger.besu.consensus.qbft.payload.ProposalPayload;
import org.hyperledger.besu.consensus.qbft.payload.RoundChangePayload;
import org.hyperledger.besu.consensus.qbt.support.RoundChangeMessage.SignedRoundChange;
import org.hyperledger.besu.crypto.SECP256K1.Signature;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.rlp.RLP;
@@ -75,7 +75,9 @@ public class ProposalMessage implements RlpTestCaseMessage {
block);
final SignedData<ProposalPayload> signedProposalPayload =
SignedData.create(
proposalPayload, Signature.decode(Bytes.fromHexString(signedProposal.signature)));
proposalPayload,
SignatureAlgorithmFactory.getInstance()
.decodeSignature(Bytes.fromHexString(signedProposal.signature)));
return new Proposal(signedProposalPayload, signedRoundChanges, signedPrepares);
}

View File

@@ -23,7 +23,7 @@ import org.hyperledger.besu.consensus.qbft.messagewrappers.RoundChange;
import org.hyperledger.besu.consensus.qbft.payload.PreparePayload;
import org.hyperledger.besu.consensus.qbft.payload.PreparedRoundMetadata;
import org.hyperledger.besu.consensus.qbft.payload.RoundChangePayload;
import org.hyperledger.besu.crypto.SECP256K1.Signature;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.core.Hash;
import org.hyperledger.besu.ethereum.rlp.RLP;
@@ -115,7 +115,9 @@ public class RoundChangeMessage implements RlpTestCaseMessage {
new ConsensusRoundIdentifier(unsignedRoundChange.sequence, unsignedRoundChange.round),
preparedRoundMetadata);
return SignedData.create(
roundChangePayload, Signature.decode(Bytes.fromHexString(signedRoundChange.signature)));
roundChangePayload,
SignatureAlgorithmFactory.getInstance()
.decodeSignature(Bytes.fromHexString(signedRoundChange.signature)));
}
}
}

View File

@@ -23,7 +23,7 @@ import org.hyperledger.besu.consensus.qbft.messagedata.QbftV1;
import org.hyperledger.besu.consensus.qbft.payload.CommitPayload;
import org.hyperledger.besu.crypto.NodeKey;
import org.hyperledger.besu.crypto.NodeKeyUtils;
import org.hyperledger.besu.crypto.SECP256K1.Signature;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.Hash;
import org.hyperledger.besu.ethereum.core.Util;
@@ -43,7 +43,8 @@ public class CommitTest {
new CommitPayload(
new ConsensusRoundIdentifier(1, 1),
Hash.ZERO,
Signature.create(BigInteger.ONE, BigInteger.ONE, (byte) 0));
SignatureAlgorithmFactory.getInstance()
.createSignature(BigInteger.ONE, BigInteger.ONE, (byte) 0));
final SignedData<CommitPayload> signedCommitPayload =
SignedData.create(commitPayload, nodeKey.sign(hashForSignature(commitPayload)));

View File

@@ -51,7 +51,7 @@ import org.hyperledger.besu.consensus.qbft.validation.MessageValidator;
import org.hyperledger.besu.consensus.qbft.validation.MessageValidatorFactory;
import org.hyperledger.besu.crypto.NodeKey;
import org.hyperledger.besu.crypto.NodeKeyUtils;
import org.hyperledger.besu.crypto.SECP256K1.Signature;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.Block;
@@ -317,7 +317,8 @@ public class QbftBlockHeightManagerTest {
.createCommit(
futureRoundIdentifier,
Hash.fromHexStringLenient("0"),
Signature.create(BigInteger.ONE, BigInteger.ONE, (byte) 1));
SignatureAlgorithmFactory.getInstance()
.createSignature(BigInteger.ONE, BigInteger.ONE, (byte) 1));
manager.handlePreparePayload(prepare);
manager.handleCommitPayload(commit);

View File

@@ -42,7 +42,8 @@ import org.hyperledger.besu.consensus.qbft.payload.PreparePayload;
import org.hyperledger.besu.consensus.qbft.validation.MessageValidator;
import org.hyperledger.besu.crypto.NodeKey;
import org.hyperledger.besu.crypto.NodeKeyUtils;
import org.hyperledger.besu.crypto.SECP256K1.Signature;
import org.hyperledger.besu.crypto.SECPSignature;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.chain.MinedBlockObserver;
import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
@@ -93,8 +94,9 @@ public class QbftRoundTest {
private Block proposedBlock;
private BftExtraData proposedExtraData;
private final Signature remoteCommitSeal =
Signature.create(BigInteger.ONE, BigInteger.ONE, (byte) 1);
private final SECPSignature remoteCommitSeal =
SignatureAlgorithmFactory.getInstance()
.createSignature(BigInteger.ONE, BigInteger.ONE, (byte) 1);
@Before
public void setup() {
@@ -223,7 +225,7 @@ public class QbftRoundTest {
final Hash commitSealHash =
BftBlockHashing.calculateDataHashForCommittedSeal(
proposedBlock.getHeader(), proposedExtraData);
final Signature localCommitSeal = nodeKey.sign(commitSealHash);
final SECPSignature localCommitSeal = nodeKey.sign(commitSealHash);
round.createAndSendProposalMessage(15);
verify(transmitter, never()).multicastCommit(any(), any(), any());

View File

@@ -28,7 +28,8 @@ import org.hyperledger.besu.consensus.qbft.payload.MessageFactory;
import org.hyperledger.besu.consensus.qbft.validation.MessageValidator;
import org.hyperledger.besu.crypto.NodeKey;
import org.hyperledger.besu.crypto.NodeKeyUtils;
import org.hyperledger.besu.crypto.SECP256K1.Signature;
import org.hyperledger.besu.crypto.SignatureAlgorithm;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.core.Hash;
@@ -38,6 +39,8 @@ import java.math.BigInteger;
import java.util.Collections;
import java.util.List;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.collect.Lists;
import org.junit.Before;
import org.junit.Test;
@@ -48,6 +51,9 @@ import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class RoundStateTest {
private static final Supplier<SignatureAlgorithm> SIGNATURE_ALGORITHM =
Suppliers.memoize(SignatureAlgorithmFactory::getInstance);
private final List<NodeKey> validatorKeys = Lists.newArrayList();
private final List<MessageFactory> validatorMessageFactories = Lists.newArrayList();
private final ConsensusRoundIdentifier roundIdentifier = new ConsensusRoundIdentifier(1, 1);
@@ -118,7 +124,9 @@ public class RoundStateTest {
.createCommit(
roundIdentifier,
block.getHash(),
Signature.create(BigInteger.ONE, BigInteger.ONE, (byte) 1));
SIGNATURE_ALGORITHM
.get()
.createSignature(BigInteger.ONE, BigInteger.ONE, (byte) 1));
roundState.addCommitMessage(commit);
assertThat(roundState.isPrepared()).isFalse();
@@ -250,7 +258,9 @@ public class RoundStateTest {
.createCommit(
roundIdentifier,
block.getHash(),
Signature.create(BigInteger.ONE, BigInteger.TEN, (byte) 1));
SIGNATURE_ALGORITHM
.get()
.createSignature(BigInteger.ONE, BigInteger.TEN, (byte) 1));
final Commit secondCommit =
validatorMessageFactories
@@ -258,7 +268,9 @@ public class RoundStateTest {
.createCommit(
roundIdentifier,
block.getHash(),
Signature.create(BigInteger.TEN, BigInteger.TEN, (byte) 1));
SIGNATURE_ALGORITHM
.get()
.createSignature(BigInteger.TEN, BigInteger.TEN, (byte) 1));
final Proposal proposal =
validatorMessageFactories

View File

@@ -19,7 +19,7 @@ import static org.assertj.core.api.Assertions.assertThat;
import org.hyperledger.besu.consensus.common.bft.ConsensusRoundHelpers;
import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier;
import org.hyperledger.besu.consensus.qbft.messagewrappers.Commit;
import org.hyperledger.besu.crypto.SECP256K1.Signature;
import org.hyperledger.besu.crypto.SECPSignature;
import org.hyperledger.besu.ethereum.core.Hash;
import org.junit.Test;
@@ -37,7 +37,7 @@ public class CommitValidatorTest {
@Test
public void commitIsValidIfItMatchesExpectedValues() {
for (int i = 0; i < VALIDATOR_COUNT; i++) {
final Signature commitSeal = validators.getNode(i).getNodeKey().sign(expectedHash);
final SECPSignature commitSeal = validators.getNode(i).getNodeKey().sign(expectedHash);
final Commit msg =
validators.getMessageFactory(i).createCommit(round, expectedHash, commitSeal);
assertThat(validator.validate(msg)).isTrue();
@@ -47,7 +47,7 @@ public class CommitValidatorTest {
@Test
public void commitSignedByANonValidatorFails() {
final QbftNode nonValidator = QbftNode.create();
final Signature commitSeal = nonValidator.getNodeKey().sign(expectedHash);
final SECPSignature commitSeal = nonValidator.getNodeKey().sign(expectedHash);
final Commit msg =
nonValidator.getMessageFactory().createCommit(round, expectedHash, commitSeal);
assertThat(validator.validate(msg)).isFalse();
@@ -55,7 +55,7 @@ public class CommitValidatorTest {
@Test
public void commitForWrongRoundFails() {
final Signature commitSeal = validators.getNode(0).getNodeKey().sign(expectedHash);
final SECPSignature commitSeal = validators.getNode(0).getNodeKey().sign(expectedHash);
final Commit msg =
validators
.getMessageFactory(0)
@@ -65,7 +65,7 @@ public class CommitValidatorTest {
@Test
public void commitForWrongSequenceFails() {
final Signature commitSeal = validators.getNode(0).getNodeKey().sign(expectedHash);
final SECPSignature commitSeal = validators.getNode(0).getNodeKey().sign(expectedHash);
final Commit msg =
validators
.getMessageFactory(0)
@@ -75,7 +75,7 @@ public class CommitValidatorTest {
@Test
public void commitWithWrongDigestFails() {
final Signature commitSeal = validators.getNode(0).getNodeKey().sign(expectedHash);
final SECPSignature commitSeal = validators.getNode(0).getNodeKey().sign(expectedHash);
final Commit msg =
validators
.getMessageFactory(0)
@@ -85,7 +85,7 @@ public class CommitValidatorTest {
@Test
public void commitWithMismatchedSealFails() {
final Signature commitSeal =
final SECPSignature commitSeal =
validators.getNode(0).getNodeKey().sign(Hash.fromHexStringLenient("0x2"));
final Commit msg =
validators.getMessageFactory(0).createCommit(round, expectedHash, commitSeal);

View File

@@ -34,7 +34,7 @@ import org.hyperledger.besu.consensus.qbft.messagewrappers.RoundChange;
import org.hyperledger.besu.consensus.qbft.payload.PreparedRoundMetadata;
import org.hyperledger.besu.consensus.qbft.payload.RoundChangePayload;
import org.hyperledger.besu.consensus.qbft.statemachine.PreparedCertificate;
import org.hyperledger.besu.crypto.SECP256K1.Signature;
import org.hyperledger.besu.crypto.SECPSignature;
import org.hyperledger.besu.ethereum.BlockValidator;
import org.hyperledger.besu.ethereum.BlockValidator.BlockProcessingOutputs;
import org.hyperledger.besu.ethereum.ProtocolContext;
@@ -404,7 +404,8 @@ public class RoundChangeMessageValidatorTest {
ProposedBlockHelpers.createProposalBlock(Collections.emptyList(), roundIdentifier);
final RoundChangePayload payload = new RoundChangePayload(targetRound, Optional.empty());
final Signature signature = validators.getNode(0).getNodeKey().sign(hashForSignature(payload));
final SECPSignature signature =
validators.getNode(0).getNodeKey().sign(hashForSignature(payload));
final RoundChange message =
new RoundChange(SignedData.create(payload, signature), Optional.of(block), emptyList());
@@ -436,7 +437,8 @@ public class RoundChangeMessageValidatorTest {
Optional.of(
new PreparedRoundMetadata(
Hash.fromHexStringLenient("0x1"), roundIdentifier.getRoundNumber())));
final Signature signature = validators.getNode(0).getNodeKey().sign(hashForSignature(payload));
final SECPSignature signature =
validators.getNode(0).getNodeKey().sign(hashForSignature(payload));
final RoundChange message =
new RoundChange(

View File

@@ -23,7 +23,7 @@ import org.hyperledger.besu.consensus.qbft.payload.PreparedRoundMetadata;
import org.hyperledger.besu.consensus.qbft.payload.RoundChangePayload;
import org.hyperledger.besu.crypto.NodeKey;
import org.hyperledger.besu.crypto.NodeKeyUtils;
import org.hyperledger.besu.crypto.SECP256K1.Signature;
import org.hyperledger.besu.crypto.SECPSignature;
import org.hyperledger.besu.ethereum.core.Hash;
import java.util.Optional;
@@ -153,7 +153,7 @@ public class RoundChangePayloadValidatorTest {
private SignedData<RoundChangePayload> createSignedPayload(
final RoundChangePayload payload, final NodeKey nodeKey) {
final Signature signature = nodeKey.sign(hashForSignature(payload));
final SECPSignature signature = nodeKey.sign(hashForSignature(payload));
return SignedData.create(payload, signature);
}
}

View File

@@ -0,0 +1,86 @@
/*
* 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.crypto;
import static com.google.common.base.Preconditions.checkNotNull;
import java.math.BigInteger;
import java.security.KeyPairGenerator;
import java.util.Arrays;
import java.util.Objects;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
public class KeyPair {
private final SECPPrivateKey privateKey;
private final SECPPublicKey publicKey;
public KeyPair(final SECPPrivateKey privateKey, final SECPPublicKey publicKey) {
checkNotNull(privateKey);
checkNotNull(publicKey);
this.privateKey = privateKey;
this.publicKey = publicKey;
}
public static KeyPair create(
final SECPPrivateKey privateKey, final ECDomainParameters curve, final String algorithm) {
return new KeyPair(privateKey, SECPPublicKey.create(privateKey, curve, algorithm));
}
public static KeyPair generate(final KeyPairGenerator keyPairGenerator, final String algorithm) {
final java.security.KeyPair rawKeyPair = keyPairGenerator.generateKeyPair();
final BCECPrivateKey privateKey = (BCECPrivateKey) rawKeyPair.getPrivate();
final BCECPublicKey publicKey = (BCECPublicKey) rawKeyPair.getPublic();
final BigInteger privateKeyValue = privateKey.getD();
// Ethereum does not use encoded public keys like bitcoin - see
// https://en.bitcoin.it/wiki/Elliptic_Curve_Digital_Signature_Algorithm for details
// Additionally, as the first bit is a constant prefix (0x04) we ignore this value
final byte[] publicKeyBytes = publicKey.getQ().getEncoded(false);
final BigInteger publicKeyValue =
new BigInteger(1, Arrays.copyOfRange(publicKeyBytes, 1, publicKeyBytes.length));
return new KeyPair(
SECPPrivateKey.create(privateKeyValue, algorithm),
SECPPublicKey.create(publicKeyValue, algorithm));
}
@Override
public int hashCode() {
return Objects.hash(privateKey, publicKey);
}
@Override
public boolean equals(final Object other) {
if (!(other instanceof KeyPair)) {
return false;
}
final KeyPair that = (KeyPair) other;
return this.privateKey.equals(that.privateKey) && this.publicKey.equals(that.publicKey);
}
public SECPPrivateKey getPrivateKey() {
return privateKey;
}
public SECPPublicKey getPublicKey() {
return publicKey;
}
}

View File

@@ -32,17 +32,19 @@ import org.apache.tuweni.bytes.Bytes32;
* operations via SECP256K1 class
*/
public class KeyPairSecurityModule implements SecurityModule {
private final SECP256K1.KeyPair keyPair;
private final KeyPair keyPair;
private final PublicKey publicKey;
private final SignatureAlgorithm signatureAlgorithm = SignatureAlgorithmFactory.getInstance();
public KeyPairSecurityModule(final SECP256K1.KeyPair keyPair) {
public KeyPairSecurityModule(final KeyPair keyPair) {
this.keyPair = keyPair;
this.publicKey = convertPublicKey(keyPair.getPublicKey());
}
private PublicKey convertPublicKey(final SECP256K1.PublicKey publicKey) {
private PublicKey convertPublicKey(final SECPPublicKey publicKey) {
try {
return new PublicKeyImpl(fromBouncyCastleECPoint(publicKey.asEcPoint()));
return new PublicKeyImpl(
fromBouncyCastleECPoint(signatureAlgorithm.publicKeyAsEcPoint(publicKey)));
} catch (final Exception e) {
throw new SecurityModuleException(
"Unexpected error while converting ECPoint: " + e.getMessage(), e);
@@ -52,7 +54,7 @@ public class KeyPairSecurityModule implements SecurityModule {
@Override
public Signature sign(final Bytes32 dataHash) throws SecurityModuleException {
try {
final SECP256K1.Signature signature = SECP256K1.sign(dataHash, keyPair);
final SECPSignature signature = signatureAlgorithm.sign(dataHash, keyPair);
return new SignatureImpl(signature);
} catch (final Exception e) {
throw new SecurityModuleException("Unexpected error while signing: " + e.getMessage(), e);
@@ -69,8 +71,9 @@ public class KeyPairSecurityModule implements SecurityModule {
throws SecurityModuleException {
try {
final Bytes encodedECPoint = ECPointUtil.getEncodedBytes(partyKey.getW());
final SECP256K1.PublicKey secp256KPartyKey = SECP256K1.PublicKey.create(encodedECPoint);
return SECP256K1.calculateECDHKeyAgreement(keyPair.getPrivateKey(), secp256KPartyKey);
final SECPPublicKey secp256KPartyKey = signatureAlgorithm.createPublicKey(encodedECPoint);
return signatureAlgorithm.calculateECDHKeyAgreement(
keyPair.getPrivateKey(), secp256KPartyKey);
} catch (final Exception e) {
throw new SecurityModuleException(
"Unexpected error while calculating ECDH Key Agreement: " + e.getMessage(), e);
@@ -79,9 +82,9 @@ public class KeyPairSecurityModule implements SecurityModule {
private static class SignatureImpl implements Signature {
private final SECP256K1.Signature signature;
private final SECPSignature signature;
SignatureImpl(final SECP256K1.Signature signature) {
SignatureImpl(final SECPSignature signature) {
this.signature = signature;
}

View File

@@ -25,6 +25,8 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.io.Resources;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -32,6 +34,8 @@ import org.apache.tuweni.bytes.Bytes32;
public class KeyPairUtil {
private static final Logger LOG = LogManager.getLogger();
private static final Supplier<SignatureAlgorithm> SIGNATURE_ALGORITHM =
Suppliers.memoize(SignatureAlgorithmFactory::getInstance);
public static String loadResourceFile(final String resourcePath) {
try {
@@ -42,29 +46,30 @@ public class KeyPairUtil {
}
}
public static SECP256K1.KeyPair loadKeyPairFromResource(final String resourcePath) {
final SECP256K1.KeyPair keyPair;
public static KeyPair loadKeyPairFromResource(final String resourcePath) {
final KeyPair keyPair;
String keyData = loadResourceFile(resourcePath);
if (keyData == null || keyData.isEmpty()) {
throw new IllegalArgumentException("Unable to load resource: " + resourcePath);
}
SECP256K1.PrivateKey privateKey = SECP256K1.PrivateKey.create(Bytes32.fromHexString((keyData)));
keyPair = SECP256K1.KeyPair.create(privateKey);
SECPPrivateKey privateKey =
SIGNATURE_ALGORITHM.get().createPrivateKey(Bytes32.fromHexString((keyData)));
keyPair = SIGNATURE_ALGORITHM.get().createKeyPair(privateKey);
LOG.info("Loaded keyPair {} from {}", keyPair.getPublicKey().toString(), resourcePath);
return keyPair;
}
public static SECP256K1.KeyPair loadKeyPair(final File keyFile) {
public static KeyPair loadKeyPair(final File keyFile) {
final SECP256K1.KeyPair key;
final KeyPair key;
if (keyFile.exists()) {
key = load(keyFile);
LOG.info(
"Loaded public key {} from {}", key.getPublicKey().toString(), keyFile.getAbsolutePath());
} else {
key = SECP256K1.KeyPair.generate();
key = SIGNATURE_ALGORITHM.get().generateKeyPair();
try {
storeKeyPair(key, keyFile);
} catch (IOException e) {
@@ -78,7 +83,7 @@ public class KeyPairUtil {
return key;
}
public static SECP256K1.KeyPair loadKeyPair(final Path homeDirectory) {
public static KeyPair loadKeyPair(final Path homeDirectory) {
return loadKeyPair(getDefaultKeyFile(homeDirectory));
}
@@ -86,23 +91,23 @@ public class KeyPairUtil {
return homeDirectory.resolve("key").toFile();
}
public static SECP256K1.KeyPair load(final File file) {
return SECP256K1.KeyPair.create(loadPrivateKey(file));
public static KeyPair load(final File file) {
return SIGNATURE_ALGORITHM.get().createKeyPair(loadPrivateKey(file));
}
static SECP256K1.PrivateKey loadPrivateKey(final File file) {
static SECPPrivateKey loadPrivateKey(final File file) {
try {
final List<String> info = Files.readAllLines(file.toPath());
if (info.size() != 1) {
throw new IllegalArgumentException("Supplied file does not contain valid keyPair pair.");
}
return SECP256K1.PrivateKey.create(Bytes32.fromHexString((info.get(0))));
return SIGNATURE_ALGORITHM.get().createPrivateKey(Bytes32.fromHexString((info.get(0))));
} catch (IOException ex) {
throw new IllegalArgumentException("Supplied file does not contain valid keyPair pair.");
}
}
static void storeKeyPair(final SECP256K1.KeyPair keyKair, final File file) throws IOException {
static void storeKeyPair(final KeyPair keyKair, final File file) throws IOException {
final File privateKeyDir = file.getParentFile();
privateKeyDir.mkdirs();
final Path tempPath = Files.createTempFile(privateKeyDir.toPath(), ".tmp", "");

View File

@@ -22,25 +22,26 @@ import org.apache.tuweni.bytes.Bytes32;
public class NodeKey {
private final SecurityModule securityModule;
private final SignatureAlgorithm signatureAlgorithm = SignatureAlgorithmFactory.getInstance();
public NodeKey(final SecurityModule securityModule) {
this.securityModule = securityModule;
}
public SECP256K1.Signature sign(final Bytes32 dataHash) {
public SECPSignature sign(final Bytes32 dataHash) {
final Signature signature = securityModule.sign(dataHash);
return SECP256K1.normaliseSignature(
return signatureAlgorithm.normaliseSignature(
signature.getR(), signature.getS(), getPublicKey(), dataHash);
}
public SECP256K1.PublicKey getPublicKey() {
return SECP256K1.PublicKey.create(
public SECPPublicKey getPublicKey() {
return signatureAlgorithm.createPublicKey(
ECPointUtil.getEncodedBytes(securityModule.getPublicKey().getW()));
}
public Bytes32 calculateECDHKeyAgreement(final SECP256K1.PublicKey partyKey) {
public Bytes32 calculateECDHKeyAgreement(final SECPPublicKey partyKey) {
return securityModule.calculateECDHKeyAgreement(
() -> ECPointUtil.fromBouncyCastleECPoint(partyKey.asEcPoint()));
() -> ECPointUtil.fromBouncyCastleECPoint(signatureAlgorithm.publicKeyAsEcPoint(partyKey)));
}
}

View File

@@ -15,7 +15,6 @@
package org.hyperledger.besu.crypto;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.hyperledger.besu.nativelib.secp256k1.LibSecp256k1.SECP256K1_EC_UNCOMPRESSED;
import org.hyperledger.besu.nativelib.secp256k1.LibSecp256k1;
@@ -30,19 +29,15 @@ import java.security.KeyPairGenerator;
import java.security.Security;
import java.security.spec.ECGenParameterSpec;
import java.util.Arrays;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Supplier;
import java.util.function.UnaryOperator;
import com.google.common.base.Suppliers;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.ptr.LongByReference;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
import org.apache.tuweni.bytes.MutableBytes;
import org.apache.tuweni.units.bigints.UInt256;
import org.bouncycastle.asn1.sec.SECNamedCurves;
import org.bouncycastle.asn1.x9.X9ECParameters;
@@ -54,12 +49,9 @@ import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.crypto.signers.ECDSASigner;
import org.bouncycastle.crypto.signers.HMacDSAKCalculator;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.math.ec.ECAlgorithms;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.math.ec.FixedPointCombMultiplier;
import org.bouncycastle.math.ec.custom.sec.SecP256K1Curve;
/*
@@ -70,48 +62,49 @@ import org.bouncycastle.math.ec.custom.sec.SecP256K1Curve;
* Adapted from the web3j (Apache 2 License) implementations:
* https://github.com/web3j/web3j/crypto/src/main/java/org/web3j/crypto/*.java
*/
public class SECP256K1 {
public class SECP256K1 implements SignatureAlgorithm {
private static final Logger LOG = LogManager.getLogger();
private static boolean useNative = true;
private boolean useNative = true;
public static final String ALGORITHM = "ECDSA";
public static final String CURVE_NAME = "secp256k1";
public static final String PROVIDER = "BC";
public static final ECDomainParameters CURVE;
public static final BigInteger HALF_CURVE_ORDER;
private final ECDomainParameters curve;
private final BigInteger halfCurveOrder;
private static final KeyPairGenerator KEY_PAIR_GENERATOR;
private static final BigInteger CURVE_ORDER;
private final KeyPairGenerator keyPairGenerator;
private final BigInteger curveOrder;
static {
public SECP256K1() {
Security.addProvider(new BouncyCastleProvider());
final X9ECParameters params = SECNamedCurves.getByName(CURVE_NAME);
CURVE = new ECDomainParameters(params.getCurve(), params.getG(), params.getN(), params.getH());
CURVE_ORDER = CURVE.getN();
HALF_CURVE_ORDER = CURVE_ORDER.shiftRight(1);
curve = new ECDomainParameters(params.getCurve(), params.getG(), params.getN(), params.getH());
curveOrder = curve.getN();
halfCurveOrder = curveOrder.shiftRight(1);
try {
KEY_PAIR_GENERATOR = KeyPairGenerator.getInstance(ALGORITHM, PROVIDER);
keyPairGenerator = KeyPairGenerator.getInstance(ALGORITHM, PROVIDER);
} catch (final Exception e) {
throw new RuntimeException(e);
}
final ECGenParameterSpec ecGenParameterSpec = new ECGenParameterSpec(CURVE_NAME);
try {
KEY_PAIR_GENERATOR.initialize(ecGenParameterSpec, SecureRandomProvider.createSecureRandom());
keyPairGenerator.initialize(ecGenParameterSpec, SecureRandomProvider.createSecureRandom());
} catch (final InvalidAlgorithmParameterException e) {
throw new RuntimeException(e);
}
}
public static void enableNative() {
@Override
public void enableNative() {
useNative = LibSecp256k1.CONTEXT != null;
LOG.info(useNative ? "Using native secp256k1" : "Native secp256k1 requested but not available");
}
public static Signature sign(final Bytes32 dataHash, final KeyPair keyPair) {
@Override
public SECPSignature sign(final Bytes32 dataHash, final KeyPair keyPair) {
if (useNative) {
return signNative(dataHash, keyPair);
} else {
@@ -130,7 +123,8 @@ public class SECP256K1 {
* @param pub The public key bytes to use.
* @return True if the verification is successful.
*/
public static boolean verify(final Bytes data, final Signature signature, final PublicKey pub) {
@Override
public boolean verify(final Bytes data, final SECPSignature signature, final SECPPublicKey pub) {
if (useNative) {
return verifyNative(data, signature, pub);
} else {
@@ -139,13 +133,13 @@ public class SECP256K1 {
}
/** Decompress a compressed public key (x co-ord and low-bit of y-coord). */
private static ECPoint decompressKey(final BigInteger xBN, final boolean yBit) {
private ECPoint decompressKey(final BigInteger xBN, final boolean yBit) {
final X9IntegerConverter x9 = new X9IntegerConverter();
final byte[] compEnc = x9.integerToBytes(xBN, 1 + x9.getByteLength(CURVE.getCurve()));
final byte[] compEnc = x9.integerToBytes(xBN, 1 + x9.getByteLength(curve.getCurve()));
compEnc[0] = (byte) (yBit ? 0x03 : 0x02);
// TODO: Find a better way to handle an invalid point compression here.
// Currently ECCurve#decodePoint throws an IllegalArgumentException.
return CURVE.getCurve().decodePoint(compEnc);
return curve.getCurve().decodePoint(compEnc);
}
/**
@@ -164,7 +158,7 @@ public class SECP256K1 {
* @param dataHash Hash of the data that was signed.
* @return An ECKey containing only the public part, or null if recovery wasn't possible.
*/
private static BigInteger recoverFromSignature(
private BigInteger recoverFromSignature(
final int recId, final BigInteger r, final BigInteger s, final Bytes32 dataHash) {
assert (recId >= 0);
assert (r.signum() >= 0);
@@ -173,7 +167,7 @@ public class SECP256K1 {
// 1.0 For j from 0 to h (h == recId here and the loop is outside this function)
// 1.1 Let x = r + jn
final BigInteger n = CURVE.getN(); // Curve order.
final BigInteger n = curve.getN(); // Curve order.
final BigInteger i = BigInteger.valueOf((long) recId / 2);
final BigInteger x = r.add(i.multiply(n));
// 1.2. Convert the integer x to an octet string X of length mlen using the conversion
@@ -216,7 +210,7 @@ public class SECP256K1 {
final BigInteger rInv = r.modInverse(n);
final BigInteger srInv = rInv.multiply(s).mod(n);
final BigInteger eInvrInv = rInv.multiply(eInv).mod(n);
final ECPoint q = ECAlgorithms.sumOfTwoMultiplies(CURVE.getG(), eInvrInv, R, srInv);
final ECPoint q = ECAlgorithms.sumOfTwoMultiplies(curve.getG(), eInvrInv, R, srInv);
if (q.isInfinity()) {
return null;
@@ -227,12 +221,12 @@ public class SECP256K1 {
return new BigInteger(1, Arrays.copyOfRange(qBytes, 1, qBytes.length));
}
private static Signature signDefault(final Bytes32 dataHash, final KeyPair keyPair) {
private SECPSignature signDefault(final Bytes32 dataHash, final KeyPair keyPair) {
final ECDSASigner signer = new ECDSASigner(new HMacDSAKCalculator(new SHA256Digest()));
final ECPrivateKeyParameters privKey =
new ECPrivateKeyParameters(
keyPair.getPrivateKey().getEncodedBytes().toUnsignedBigInteger(), CURVE);
keyPair.getPrivateKey().getEncodedBytes().toUnsignedBigInteger(), curve);
signer.init(true, privKey);
final BigInteger[] components = signer.generateSignature(dataHash.toArrayUnsafe());
@@ -240,10 +234,11 @@ public class SECP256K1 {
return normaliseSignature(components[0], components[1], keyPair.getPublicKey(), dataHash);
}
public static Signature normaliseSignature(
@Override
public SECPSignature normaliseSignature(
final BigInteger nativeR,
final BigInteger nativeS,
final PublicKey publicKey,
final SECPPublicKey publicKey,
final Bytes32 dataHash) {
BigInteger s = nativeS;
@@ -253,14 +248,14 @@ public class SECP256K1 {
// ability to modify the bits of a Bitcoin transaction after it's been signed, as that
// violates various assumed invariants. Thus in future only one of those forms will be
// considered legal and the other will be banned.
if (s.compareTo(HALF_CURVE_ORDER) > 0) {
if (s.compareTo(halfCurveOrder) > 0) {
// The order of the curve is the number of valid points that exist on that curve.
// If S is in the upper half of the number of valid points, then bring it back to
// the lower half. Otherwise, imagine that
// N = 10
// s = 8, so (-8 % 10 == 2) thus both (r, 8) and (r, 2) are valid solutions.
// 10 - 8 == 2, giving us always the latter solution, which is canonical.
s = CURVE.getN().subtract(s);
s = curve.getN().subtract(s);
}
// Now we have to work backwards to figure out the recId needed to recover the signature.
@@ -278,18 +273,18 @@ public class SECP256K1 {
"Could not construct a recoverable key. This should never happen.");
}
return new Signature(nativeR, s, (byte) recId);
return new SECPSignature(nativeR, s, (byte) recId);
}
private static boolean verifyDefault(
final Bytes data, final Signature signature, final PublicKey pub) {
private boolean verifyDefault(
final Bytes data, final SECPSignature signature, final SECPPublicKey pub) {
final ECDSASigner signer = new ECDSASigner();
final Bytes toDecode = Bytes.wrap(Bytes.of((byte) 4), pub.getEncodedBytes());
final ECPublicKeyParameters params =
new ECPublicKeyParameters(CURVE.getCurve().decodePoint(toDecode.toArrayUnsafe()), CURVE);
new ECPublicKeyParameters(curve.getCurve().decodePoint(toDecode.toArrayUnsafe()), curve);
signer.init(false, params);
try {
return signer.verifySignature(data.toArrayUnsafe(), signature.r, signature.s);
return signer.verifySignature(data.toArrayUnsafe(), signature.getR(), signature.getS());
} catch (final NullPointerException e) {
// Bouncy Castle contains a bug that can cause NPEs given specially crafted signatures. Those
// signatures
@@ -309,10 +304,11 @@ public class SECP256K1 {
* a hashing function.
* @return True if the verification is successful.
*/
public static boolean verify(
@Override
public boolean verify(
final Bytes data,
final Signature signature,
final PublicKey pub,
final SECPSignature signature,
final SECPPublicKey pub,
final UnaryOperator<Bytes> preprocessor) {
checkArgument(preprocessor != null, "preprocessor must not be null");
return verify(preprocessor.apply(data), signature, pub);
@@ -325,13 +321,15 @@ public class SECP256K1 {
* @param theirPubKey The public key.
* @return The agreed secret.
*/
public static Bytes32 calculateECDHKeyAgreement(
final PrivateKey privKey, final PublicKey theirPubKey) {
@Override
public Bytes32 calculateECDHKeyAgreement(
final SECPPrivateKey privKey, final SECPPublicKey theirPubKey) {
checkArgument(privKey != null, "missing private key");
checkArgument(theirPubKey != null, "missing remote public key");
final ECPrivateKeyParameters privKeyP = new ECPrivateKeyParameters(privKey.getD(), CURVE);
final ECPublicKeyParameters pubKeyP = new ECPublicKeyParameters(theirPubKey.asEcPoint(), CURVE);
final ECPrivateKeyParameters privKeyP = new ECPrivateKeyParameters(privKey.getD(), curve);
final ECPublicKeyParameters pubKeyP =
new ECPublicKeyParameters(theirPubKey.asEcPoint(curve), curve);
final ECDHBasicAgreement agreement = new ECDHBasicAgreement();
agreement.init(privKeyP);
@@ -340,7 +338,84 @@ public class SECP256K1 {
return UInt256.valueOf(agreed).toBytes();
}
private static Signature signNative(final Bytes32 dataHash, final KeyPair keyPair) {
@Override
public SECPPrivateKey createPrivateKey(final BigInteger key) {
return SECPPrivateKey.create(key, ALGORITHM);
}
@Override
public SECPPrivateKey createPrivateKey(final Bytes32 key) {
return SECPPrivateKey.create(key, ALGORITHM);
}
@Override
public SECPPublicKey createPublicKey(final SECPPrivateKey privateKey) {
return SECPPublicKey.create(privateKey, curve, ALGORITHM);
}
@Override
public SECPPublicKey createPublicKey(final BigInteger key) {
return SECPPublicKey.create(key, ALGORITHM);
}
@Override
public SECPPublicKey createPublicKey(final Bytes encoded) {
return SECPPublicKey.create(encoded, ALGORITHM);
}
@Override
public Optional<SECPPublicKey> recoverPublicKeyFromSignature(
final Bytes32 dataHash, final SECPSignature signature) {
if (useNative) {
return recoverFromSignatureNative(dataHash, signature);
} else {
final BigInteger publicKeyBI =
recoverFromSignature(signature.getRecId(), signature.getR(), signature.getS(), dataHash);
return Optional.of(SECPPublicKey.create(publicKeyBI, ALGORITHM));
}
}
@Override
public ECPoint publicKeyAsEcPoint(final SECPPublicKey publicKey) {
return publicKey.asEcPoint(curve);
}
@Override
public KeyPair createKeyPair(final SECPPrivateKey privateKey) {
return KeyPair.create(privateKey, curve, ALGORITHM);
}
@Override
public KeyPair generateKeyPair() {
return KeyPair.generate(keyPairGenerator, ALGORITHM);
}
@Override
public SECPSignature createSignature(final BigInteger r, final BigInteger s, final byte recId) {
return SECPSignature.create(r, s, recId, curveOrder);
}
@Override
public SECPSignature decodeSignature(final Bytes bytes) {
return SECPSignature.decode(bytes, curveOrder);
}
@Override
public BigInteger getHalfCurveOrder() {
return halfCurveOrder;
}
@Override
public String getProvider() {
return PROVIDER;
}
@Override
public String getCurveName() {
return CURVE_NAME;
}
private SECPSignature signNative(final Bytes32 dataHash, final KeyPair keyPair) {
final LibSecp256k1.secp256k1_ecdsa_recoverable_signature signature =
new secp256k1_ecdsa_recoverable_signature();
// sign in internal form
@@ -348,7 +423,7 @@ public class SECP256K1 {
LibSecp256k1.CONTEXT,
signature,
dataHash.toArrayUnsafe(),
keyPair.privateKey.getEncoded(),
keyPair.getPrivateKey().getEncoded(),
null,
null)
== 0) {
@@ -367,12 +442,12 @@ public class SECP256K1 {
// wrap in signature object
final Bytes32 r = Bytes32.wrap(sig, 0);
final Bytes32 s = Bytes32.wrap(sig, 32);
return Signature.create(
r.toUnsignedBigInteger(), s.toUnsignedBigInteger(), (byte) recId.getValue());
return SECPSignature.create(
r.toUnsignedBigInteger(), s.toUnsignedBigInteger(), (byte) recId.getValue(), curveOrder);
}
private static boolean verifyNative(
final Bytes data, final Signature signature, final PublicKey pub) {
private boolean verifyNative(
final Bytes data, final SECPSignature signature, final SECPPublicKey pub) {
// translate signature
final LibSecp256k1.secp256k1_ecdsa_signature _signature = new secp256k1_ecdsa_signature();
@@ -396,8 +471,8 @@ public class SECP256K1 {
!= 0;
}
private static Optional<PublicKey> recoverFromSignatureNative(
final Bytes32 dataHash, final Signature signature) {
private Optional<SECPPublicKey> recoverFromSignatureNative(
final Bytes32 dataHash, final SECPSignature signature) {
// parse the sig
final LibSecp256k1.secp256k1_ecdsa_recoverable_signature parsedSignature =
@@ -426,360 +501,7 @@ public class SECP256K1 {
LibSecp256k1.secp256k1_ec_pubkey_serialize(
LibSecp256k1.CONTEXT, recoveredKey, keySize, newPubKey, SECP256K1_EC_UNCOMPRESSED);
return Optional.of(PublicKey.create(Bytes.wrapByteBuffer(recoveredKey).slice(1)));
}
public static class PrivateKey implements java.security.PrivateKey {
private final Bytes32 encoded;
private PrivateKey(final Bytes32 encoded) {
checkNotNull(encoded);
this.encoded = encoded;
}
public static PrivateKey create(final BigInteger key) {
checkNotNull(key);
return create(UInt256.valueOf(key).toBytes());
}
public static PrivateKey create(final Bytes32 key) {
return new PrivateKey(key);
}
@Override
public boolean equals(final Object other) {
if (!(other instanceof PrivateKey)) {
return false;
}
final PrivateKey that = (PrivateKey) other;
return this.encoded.equals(that.encoded);
}
@Override
public byte[] getEncoded() {
return encoded.toArrayUnsafe();
}
public Bytes32 getEncodedBytes() {
return encoded;
}
public BigInteger getD() {
return encoded.toUnsignedBigInteger();
}
@Override
public String getAlgorithm() {
return ALGORITHM;
}
@Override
public String getFormat() {
return null;
}
@Override
public int hashCode() {
return encoded.hashCode();
}
@Override
public String toString() {
return encoded.toString();
}
}
public static class PublicKey implements java.security.PublicKey {
public static final int BYTE_LENGTH = 64;
private final Bytes encoded;
public static PublicKey create(final PrivateKey privateKey) {
BigInteger privKey = privateKey.getEncodedBytes().toUnsignedBigInteger();
/*
* TODO: FixedPointCombMultiplier currently doesn't support scalars longer than the group
* order, but that could change in future versions.
*/
if (privKey.bitLength() > CURVE.getN().bitLength()) {
privKey = privKey.mod(CURVE.getN());
}
final ECPoint point = new FixedPointCombMultiplier().multiply(CURVE.getG(), privKey);
return PublicKey.create(Bytes.wrap(Arrays.copyOfRange(point.getEncoded(false), 1, 65)));
}
private static Bytes toBytes64(final byte[] backing) {
if (backing.length == BYTE_LENGTH) {
return Bytes.wrap(backing);
} else if (backing.length > BYTE_LENGTH) {
return Bytes.wrap(backing, backing.length - BYTE_LENGTH, BYTE_LENGTH);
} else {
final MutableBytes res = MutableBytes.create(BYTE_LENGTH);
Bytes.wrap(backing).copyTo(res, BYTE_LENGTH - backing.length);
return res;
}
}
public static PublicKey create(final BigInteger key) {
checkNotNull(key);
return create(toBytes64(key.toByteArray()));
}
public static PublicKey create(final Bytes encoded) {
return new PublicKey(encoded);
}
public static Optional<PublicKey> recoverFromSignature(
final Bytes32 dataHash, final Signature signature) {
if (useNative) {
return recoverFromSignatureNative(dataHash, signature);
} else {
final BigInteger publicKeyBI =
SECP256K1.recoverFromSignature(
signature.getRecId(), signature.getR(), signature.getS(), dataHash);
return Optional.ofNullable(publicKeyBI).map(PublicKey::create);
}
}
private PublicKey(final Bytes encoded) {
checkNotNull(encoded);
checkArgument(
encoded.size() == BYTE_LENGTH,
"Encoding must be %s bytes long, got %s",
BYTE_LENGTH,
encoded.size());
this.encoded = encoded;
}
/**
* Returns this public key as an {@link ECPoint} of Bouncy Castle, to facilitate cryptographic
* operations.
*
* @return This public key represented as an Elliptic Curve point.
*/
public ECPoint asEcPoint() {
// 0x04 is the prefix for uncompressed keys.
final Bytes val = Bytes.concatenate(Bytes.of(0x04), encoded);
return CURVE.getCurve().decodePoint(val.toArrayUnsafe());
}
@Override
public boolean equals(final Object other) {
if (!(other instanceof PublicKey)) {
return false;
}
final PublicKey that = (PublicKey) other;
return this.encoded.equals(that.encoded);
}
@Override
public byte[] getEncoded() {
return encoded.toArrayUnsafe();
}
public Bytes getEncodedBytes() {
return encoded;
}
@Override
public String getAlgorithm() {
return ALGORITHM;
}
@Override
public String getFormat() {
return null;
}
@Override
public int hashCode() {
return encoded.hashCode();
}
@Override
public String toString() {
return encoded.toString();
}
}
public static class KeyPair {
private final PrivateKey privateKey;
private final PublicKey publicKey;
public KeyPair(final PrivateKey privateKey, final PublicKey publicKey) {
checkNotNull(privateKey);
checkNotNull(publicKey);
this.privateKey = privateKey;
this.publicKey = publicKey;
}
public static KeyPair create(final PrivateKey privateKey) {
return new KeyPair(privateKey, PublicKey.create(privateKey));
}
public static KeyPair generate() {
final java.security.KeyPair rawKeyPair = KEY_PAIR_GENERATOR.generateKeyPair();
final BCECPrivateKey privateKey = (BCECPrivateKey) rawKeyPair.getPrivate();
final BCECPublicKey publicKey = (BCECPublicKey) rawKeyPair.getPublic();
final BigInteger privateKeyValue = privateKey.getD();
// Ethereum does not use encoded public keys like bitcoin - see
// https://en.bitcoin.it/wiki/Elliptic_Curve_Digital_Signature_Algorithm for details
// Additionally, as the first bit is a constant prefix (0x04) we ignore this value
final byte[] publicKeyBytes = publicKey.getQ().getEncoded(false);
final BigInteger publicKeyValue =
new BigInteger(1, Arrays.copyOfRange(publicKeyBytes, 1, publicKeyBytes.length));
return new KeyPair(PrivateKey.create(privateKeyValue), PublicKey.create(publicKeyValue));
}
@Override
public int hashCode() {
return Objects.hash(privateKey, publicKey);
}
@Override
public boolean equals(final Object other) {
if (!(other instanceof KeyPair)) {
return false;
}
final KeyPair that = (KeyPair) other;
return this.privateKey.equals(that.privateKey) && this.publicKey.equals(that.publicKey);
}
public PrivateKey getPrivateKey() {
return privateKey;
}
public PublicKey getPublicKey() {
return publicKey;
}
}
public static class Signature {
public static final int BYTES_REQUIRED = 65;
/**
* The recovery id to reconstruct the public key used to create the signature.
*
* <p>The recId is an index from 0 to 3 which indicates which of the 4 possible keys is the
* correct one. Because the key recovery operation yields multiple potential keys, the correct
* key must either be stored alongside the signature, or you must be willing to try each recId
* in turn until you find one that outputs the key you are expecting.
*/
private final byte recId;
private final BigInteger r;
private final BigInteger s;
private final Supplier<Bytes> encoded = Suppliers.memoize(this::_encodedBytes);
Signature(final BigInteger r, final BigInteger s, final byte recId) {
this.r = r;
this.s = s;
this.recId = recId;
}
/**
* Creates a new signature object given its parameters.
*
* @param r the 'r' part of the signature.
* @param s the 's' part of the signature.
* @param recId the recovery id part of the signature.
* @return the created {@link Signature} object.
* @throws NullPointerException if {@code r} or {@code s} are {@code null}.
* @throws IllegalArgumentException if any argument is invalid (for instance, {@code v} is
* neither 27 or 28).
*/
public static Signature create(final BigInteger r, final BigInteger s, final byte recId) {
checkNotNull(r);
checkNotNull(s);
checkInBounds("r", r);
checkInBounds("s", s);
if (recId != 0 && recId != 1) {
throw new IllegalArgumentException(
"Invalid 'recId' value, should be 0 or 1 but got " + recId);
}
return new Signature(r, s, recId);
}
private static void checkInBounds(final String name, final BigInteger i) {
if (i.compareTo(BigInteger.ONE) < 0) {
throw new IllegalArgumentException(
String.format("Invalid '%s' value, should be >= 1 but got %s", name, i));
}
if (i.compareTo(CURVE_ORDER) >= 0) {
throw new IllegalArgumentException(
String.format("Invalid '%s' value, should be < %s but got %s", CURVE_ORDER, name, i));
}
}
public static Signature decode(final Bytes bytes) {
checkArgument(
bytes.size() == BYTES_REQUIRED, "encoded SECP256K1 signature must be 65 bytes long");
final BigInteger r = bytes.slice(0, 32).toUnsignedBigInteger();
final BigInteger s = bytes.slice(32, 32).toUnsignedBigInteger();
final byte recId = bytes.get(64);
return SECP256K1.Signature.create(r, s, recId);
}
public Bytes encodedBytes() {
return encoded.get();
}
private Bytes _encodedBytes() {
final MutableBytes bytes = MutableBytes.create(BYTES_REQUIRED);
UInt256.valueOf(r).toBytes().copyTo(bytes, 0);
UInt256.valueOf(s).toBytes().copyTo(bytes, 32);
bytes.set(64, recId);
return bytes;
}
@Override
public boolean equals(final Object other) {
if (!(other instanceof Signature)) {
return false;
}
final Signature that = (Signature) other;
return this.r.equals(that.r) && this.s.equals(that.s) && this.recId == that.recId;
}
@Override
public int hashCode() {
return Objects.hash(r, s, recId);
}
public byte getRecId() {
return recId;
}
public BigInteger getR() {
return r;
}
public BigInteger getS() {
return s;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append("SECP256K1.Signature").append("{");
sb.append("r=").append(r).append(", ");
sb.append("s=").append(s).append(", ");
sb.append("recId=").append(recId);
return sb.append("}").toString();
}
return Optional.of(
SECPPublicKey.create(Bytes.wrapByteBuffer(recoveredKey).slice(1), ALGORITHM));
}
}

View File

@@ -0,0 +1,87 @@
/*
* 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.crypto;
import static com.google.common.base.Preconditions.checkNotNull;
import java.math.BigInteger;
import org.apache.tuweni.bytes.Bytes32;
import org.apache.tuweni.units.bigints.UInt256;
public class SECPPrivateKey implements java.security.PrivateKey {
private final Bytes32 encoded;
private final String algorithm;
private SECPPrivateKey(final Bytes32 encoded, final String algorithm) {
checkNotNull(encoded);
checkNotNull(algorithm);
this.encoded = encoded;
this.algorithm = algorithm;
}
public static SECPPrivateKey create(final BigInteger key, final String algorithm) {
checkNotNull(key);
return create(UInt256.valueOf(key).toBytes(), algorithm);
}
public static SECPPrivateKey create(final Bytes32 key, final String algorithm) {
return new SECPPrivateKey(key, algorithm);
}
@Override
public boolean equals(final Object other) {
if (!(other instanceof SECPPrivateKey)) {
return false;
}
final SECPPrivateKey that = (SECPPrivateKey) other;
return this.encoded.equals(that.encoded) && this.algorithm.equals(that.algorithm);
}
@Override
public byte[] getEncoded() {
return encoded.toArrayUnsafe();
}
public Bytes32 getEncodedBytes() {
return encoded;
}
public BigInteger getD() {
return encoded.toUnsignedBigInteger();
}
@Override
public String getAlgorithm() {
return algorithm;
}
@Override
public String getFormat() {
return null;
}
@Override
public int hashCode() {
return encoded.hashCode();
}
@Override
public String toString() {
return encoded.toString();
}
}

View File

@@ -0,0 +1,137 @@
/*
* 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.crypto;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import java.math.BigInteger;
import java.util.Arrays;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.MutableBytes;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.math.ec.FixedPointCombMultiplier;
public class SECPPublicKey implements java.security.PublicKey {
public static final int BYTE_LENGTH = 64;
private final Bytes encoded;
private final String algorithm;
public static SECPPublicKey create(final BigInteger key, final String algorithm) {
checkNotNull(key);
return create(toBytes64(key.toByteArray()), algorithm);
}
public static SECPPublicKey create(final Bytes encoded, final String algorithm) {
return new SECPPublicKey(encoded, algorithm);
}
public static SECPPublicKey create(
final SECPPrivateKey privateKey, final ECDomainParameters curve, final String algorithm) {
BigInteger privKey = privateKey.getEncodedBytes().toUnsignedBigInteger();
/*
* TODO: FixedPointCombMultiplier currently doesn't support scalars longer than the group
* order, but that could change in future versions.
*/
if (privKey.bitLength() > curve.getN().bitLength()) {
privKey = privKey.mod(curve.getN());
}
final ECPoint point = new FixedPointCombMultiplier().multiply(curve.getG(), privKey);
return SECPPublicKey.create(
Bytes.wrap(Arrays.copyOfRange(point.getEncoded(false), 1, 65)), algorithm);
}
private static Bytes toBytes64(final byte[] backing) {
if (backing.length == BYTE_LENGTH) {
return Bytes.wrap(backing);
} else if (backing.length > BYTE_LENGTH) {
return Bytes.wrap(backing, backing.length - BYTE_LENGTH, BYTE_LENGTH);
} else {
final MutableBytes res = MutableBytes.create(BYTE_LENGTH);
Bytes.wrap(backing).copyTo(res, BYTE_LENGTH - backing.length);
return res;
}
}
private SECPPublicKey(final Bytes encoded, final String algorithm) {
checkNotNull(encoded);
checkNotNull(algorithm);
checkArgument(
encoded.size() == BYTE_LENGTH,
"Encoding must be %s bytes long, got %s",
BYTE_LENGTH,
encoded.size());
this.encoded = encoded;
this.algorithm = algorithm;
}
/**
* Returns this public key as an {@link ECPoint} of Bouncy Castle, to facilitate cryptographic
* operations.
*
* @param curve The elliptic curve (e.g. SECP256K1) represented as its domain parameters
* @return This public key represented as an Elliptic Curve point.
*/
public ECPoint asEcPoint(final ECDomainParameters curve) {
// 0x04 is the prefix for uncompressed keys.
final Bytes val = Bytes.concatenate(Bytes.of(0x04), encoded);
return curve.getCurve().decodePoint(val.toArrayUnsafe());
}
@Override
public boolean equals(final Object other) {
if (!(other instanceof SECPPublicKey)) {
return false;
}
final SECPPublicKey that = (SECPPublicKey) other;
return this.encoded.equals(that.encoded) && this.algorithm.equals(that.algorithm);
}
@Override
public byte[] getEncoded() {
return encoded.toArrayUnsafe();
}
public Bytes getEncodedBytes() {
return encoded;
}
@Override
public String getAlgorithm() {
return algorithm;
}
@Override
public String getFormat() {
return null;
}
@Override
public int hashCode() {
return encoded.hashCode();
}
@Override
public String toString() {
return encoded.toString();
}
}

View File

@@ -0,0 +1,149 @@
/*
* 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.crypto;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import java.math.BigInteger;
import java.util.Objects;
import java.util.function.Supplier;
import com.google.common.base.Suppliers;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.MutableBytes;
import org.apache.tuweni.units.bigints.UInt256;
public class SECPSignature {
public static final int BYTES_REQUIRED = 65;
/**
* The recovery id to reconstruct the public key used to create the signature.
*
* <p>The recId is an index from 0 to 3 which indicates which of the 4 possible keys is the
* correct one. Because the key recovery operation yields multiple potential keys, the correct key
* must either be stored alongside the signature, or you must be willing to try each recId in turn
* until you find one that outputs the key you are expecting.
*/
private final byte recId;
private final BigInteger r;
private final BigInteger s;
private final Supplier<Bytes> encoded = Suppliers.memoize(this::_encodedBytes);
SECPSignature(final BigInteger r, final BigInteger s, final byte recId) {
this.r = r;
this.s = s;
this.recId = recId;
}
/**
* Creates a new signature object given its parameters.
*
* @param r the 'r' part of the signature.
* @param s the 's' part of the signature.
* @param recId the recovery id part of the signature.
* @param curveOrder The order (n) of the used curve
* @return the created {@link SECPSignature} object.
* @throws NullPointerException if {@code r} or {@code s} are {@code null}.
* @throws IllegalArgumentException if any argument is invalid (for instance, {@code v} is neither
* 27 or 28).
*/
public static SECPSignature create(
final BigInteger r, final BigInteger s, final byte recId, final BigInteger curveOrder) {
checkNotNull(r);
checkNotNull(s);
checkInBounds("r", r, curveOrder);
checkInBounds("s", s, curveOrder);
if (recId != 0 && recId != 1) {
throw new IllegalArgumentException(
"Invalid 'recId' value, should be 0 or 1 but got " + recId);
}
return new SECPSignature(r, s, recId);
}
private static void checkInBounds(
final String name, final BigInteger i, final BigInteger curveOrder) {
if (i.compareTo(BigInteger.ONE) < 0) {
throw new IllegalArgumentException(
String.format("Invalid '%s' value, should be >= 1 but got %s", name, i));
}
if (i.compareTo(curveOrder) >= 0) {
throw new IllegalArgumentException(
String.format("Invalid '%s' value, should be < %s but got %s", curveOrder, name, i));
}
}
public static SECPSignature decode(final Bytes bytes, final BigInteger curveOrder) {
checkArgument(
bytes.size() == BYTES_REQUIRED, "encoded SECP256K1 signature must be 65 bytes long");
final BigInteger r = bytes.slice(0, 32).toUnsignedBigInteger();
final BigInteger s = bytes.slice(32, 32).toUnsignedBigInteger();
final byte recId = bytes.get(64);
return SECPSignature.create(r, s, recId, curveOrder);
}
public Bytes encodedBytes() {
return encoded.get();
}
private Bytes _encodedBytes() {
final MutableBytes bytes = MutableBytes.create(BYTES_REQUIRED);
UInt256.valueOf(r).toBytes().copyTo(bytes, 0);
UInt256.valueOf(s).toBytes().copyTo(bytes, 32);
bytes.set(64, recId);
return bytes;
}
@Override
public boolean equals(final Object other) {
if (!(other instanceof SECPSignature)) {
return false;
}
final SECPSignature that = (SECPSignature) other;
return this.r.equals(that.r) && this.s.equals(that.s) && this.recId == that.recId;
}
@Override
public int hashCode() {
return Objects.hash(r, s, recId);
}
public byte getRecId() {
return recId;
}
public BigInteger getR() {
return r;
}
public BigInteger getS() {
return s;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append("Signature").append("{");
sb.append("r=").append(r).append(", ");
sb.append("s=").append(s).append(", ");
sb.append("recId=").append(recId);
return sb.append("}").toString();
}
}

View File

@@ -0,0 +1,77 @@
/*
* 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.crypto;
import java.math.BigInteger;
import java.util.Optional;
import java.util.function.UnaryOperator;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
import org.bouncycastle.math.ec.ECPoint;
public interface SignatureAlgorithm {
// needs to be known at compile time otherwise triggers InsecureCryptoUsage error
String ALGORITHM = "ECDSA";
void enableNative();
SECPSignature sign(final Bytes32 dataHash, final KeyPair keyPair);
boolean verify(final Bytes data, final SECPSignature signature, final SECPPublicKey pub);
boolean verify(
final Bytes data,
final SECPSignature signature,
final SECPPublicKey pub,
final UnaryOperator<Bytes> preprocessor);
SECPSignature normaliseSignature(
final BigInteger nativeR,
final BigInteger nativeS,
final SECPPublicKey publicKey,
final Bytes32 dataHash);
Bytes32 calculateECDHKeyAgreement(final SECPPrivateKey privKey, final SECPPublicKey theirPubKey);
BigInteger getHalfCurveOrder();
String getProvider();
String getCurveName();
SECPPrivateKey createPrivateKey(final BigInteger key);
SECPPrivateKey createPrivateKey(final Bytes32 key);
SECPPublicKey createPublicKey(final SECPPrivateKey privateKey);
SECPPublicKey createPublicKey(final BigInteger key);
SECPPublicKey createPublicKey(final Bytes encoded);
Optional<SECPPublicKey> recoverPublicKeyFromSignature(
final Bytes32 dataHash, final SECPSignature signature);
ECPoint publicKeyAsEcPoint(final SECPPublicKey publicKey);
KeyPair createKeyPair(final SECPPrivateKey privateKey);
KeyPair generateKeyPair();
SECPSignature createSignature(final BigInteger r, final BigInteger s, final byte recId);
SECPSignature decodeSignature(final Bytes bytes);
}

View File

@@ -0,0 +1,24 @@
/*
* 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.crypto;
public class SignatureAlgorithmFactory {
private static final SignatureAlgorithm instance = new SECP256K1();
public static SignatureAlgorithm getInstance() {
return instance;
}
}

View File

@@ -16,11 +16,12 @@ package org.hyperledger.besu.crypto;
public class NodeKeyUtils {
public static NodeKey createFrom(final SECP256K1.KeyPair keyPair) {
public static NodeKey createFrom(final KeyPair keyPair) {
return new NodeKey(new KeyPairSecurityModule(keyPair));
}
public static NodeKey generate() {
return new NodeKey(new KeyPairSecurityModule(SECP256K1.KeyPair.generate()));
return new NodeKey(
new KeyPairSecurityModule(SignatureAlgorithmFactory.getInstance().generateKeyPair()));
}
}

View File

@@ -33,12 +33,13 @@ public class KeyPairSecurityModuleTest {
final File keyDirectory = temp.newFolder();
final File keyFile = new File(keyDirectory, "key");
final SECP256K1.KeyPair keyPair = KeyPairUtil.loadKeyPair(keyFile);
final KeyPair keyPair = KeyPairUtil.loadKeyPair(keyFile);
final KeyPairSecurityModule keyPairSecurityModule = new KeyPairSecurityModule(keyPair);
final ECPoint ecPoint = keyPairSecurityModule.getPublicKey().getW();
final Bytes encodedBytes = ECPointUtil.getEncodedBytes(ecPoint);
final SECP256K1.PublicKey publicKey = SECP256K1.PublicKey.create(encodedBytes);
final SECPPublicKey publicKey =
SignatureAlgorithmFactory.getInstance().createPublicKey(encodedBytes);
Assertions.assertThat(keyPair.getPublicKey().getEncodedBytes())
.isEqualByComparingTo(publicKey.getEncodedBytes());

View File

@@ -0,0 +1,99 @@
/*
* 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.crypto;
import static org.apache.tuweni.bytes.Bytes.fromHexString;
import static org.assertj.core.api.Assertions.assertThat;
import java.math.BigInteger;
import java.security.KeyPairGenerator;
import java.security.Security;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
import org.bouncycastle.asn1.sec.SECNamedCurves;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.junit.BeforeClass;
import org.junit.Test;
public class KeyPairTest {
public static final String ALGORITHM = SignatureAlgorithm.ALGORITHM;
public static final String PROVIDER = "BC";
public static final String CURVE_NAME = "secp256k1";
public static KeyPairGenerator keyPairGenerator;
public static ECDomainParameters curve;
@BeforeClass
public static void setUp() {
Security.addProvider(new BouncyCastleProvider());
try {
keyPairGenerator = KeyPairGenerator.getInstance(ALGORITHM, PROVIDER);
} catch (final Exception e) {
throw new RuntimeException(e);
}
final X9ECParameters params = SECNamedCurves.getByName(CURVE_NAME);
curve = new ECDomainParameters(params.getCurve(), params.getG(), params.getN(), params.getH());
}
@Test(expected = NullPointerException.class)
public void createKeyPair_PublicKeyNull() {
new KeyPair(null, SECPPublicKey.create(Bytes.wrap(new byte[64]), ALGORITHM));
}
@Test(expected = NullPointerException.class)
public void createKeyPair_PrivateKeyNull() {
new KeyPair(SECPPrivateKey.create(Bytes32.wrap(new byte[32]), ALGORITHM), null);
}
@Test
public void keyPairGeneration() {
final KeyPair keyPair = KeyPair.generate(keyPairGenerator, ALGORITHM);
assertThat(keyPair).isNotNull();
assertThat(keyPair.getPrivateKey()).isNotNull();
assertThat(keyPair.getPublicKey()).isNotNull();
}
@Test
public void keyPairEquals() {
final SECPPrivateKey privateKey1 = SECPPrivateKey.create(BigInteger.TEN, ALGORITHM);
final SECPPrivateKey privateKey2 = SECPPrivateKey.create(BigInteger.TEN, ALGORITHM);
final SECPPublicKey publicKey1 =
SECPPublicKey.create(
fromHexString(
"a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7893aba425419bc27a3b6c7e693a24c696f794c2ed877a1593cbee53b037368d7"),
ALGORITHM);
final SECPPublicKey publicKey2 =
SECPPublicKey.create(
fromHexString(
"a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7893aba425419bc27a3b6c7e693a24c696f794c2ed877a1593cbee53b037368d7"),
ALGORITHM);
final KeyPair keyPair1 = new KeyPair(privateKey1, publicKey1);
final KeyPair keyPair2 = new KeyPair(privateKey2, publicKey2);
assertThat(keyPair2).isEqualTo(keyPair1);
}
@Test
public void keyPairHashCode() {
final KeyPair keyPair = KeyPair.generate(keyPairGenerator, ALGORITHM);
assertThat(keyPair.hashCode()).isNotZero();
}
}

View File

@@ -29,8 +29,9 @@ public class NodeKeyTest {
final Bytes32 keyPairPrvKey =
Bytes32.fromHexString("0xf7a58d5e755d51fa2f6206e91dd574597c73248aaf946ec1964b8c6268d6207b");
final SECP256K1.KeyPair keyPair =
SECP256K1.KeyPair.create(SECP256K1.PrivateKey.create(keyPairPrvKey));
final SignatureAlgorithm signatureAlgorithm = SignatureAlgorithmFactory.getInstance();
final KeyPair keyPair =
signatureAlgorithm.createKeyPair(signatureAlgorithm.createPrivateKey(keyPairPrvKey));
final KeyPairSecurityModule keyPairSecurityModule = new KeyPairSecurityModule(keyPair);
final NodeKey nodeKey = new NodeKey(keyPairSecurityModule);

View File

@@ -15,7 +15,6 @@
package org.hyperledger.besu.crypto;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.apache.tuweni.bytes.Bytes.fromHexString;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hyperledger.besu.crypto.Hash.keccak256;
@@ -28,11 +27,14 @@ import java.time.format.DateTimeFormatter;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
public class SECP256K1Test {
protected SECP256K1 secp256K1;
protected static String suiteStartTime = null;
protected static String suiteName = null;
@@ -42,6 +44,12 @@ public class SECP256K1Test {
LocalDateTime.now(ZoneId.systemDefault())
.format(DateTimeFormatter.ofPattern("yyyyMMdd-HHmmss"));
suiteName(SECP256K1Test.class);
;
}
@Before
public void setUp() {
secp256K1 = new SECP256K1();
}
public static void suiteName(final Class<?> clazz) {
@@ -52,218 +60,60 @@ public class SECP256K1Test {
return suiteName;
}
@Test(expected = NullPointerException.class)
public void createPrivateKey_NullEncoding() {
SECP256K1.PrivateKey.create((Bytes32) null);
}
@Test
public void privateKeyEquals() {
final SECP256K1.PrivateKey privateKey1 = SECP256K1.PrivateKey.create(BigInteger.TEN);
final SECP256K1.PrivateKey privateKey2 = SECP256K1.PrivateKey.create(BigInteger.TEN);
assertThat(privateKey2).isEqualTo(privateKey1);
}
@Test
public void privateHashCode() {
final SECP256K1.PrivateKey privateKey = SECP256K1.PrivateKey.create(BigInteger.TEN);
assertThat(privateKey.hashCode()).isNotZero();
}
@Test(expected = NullPointerException.class)
public void createPublicKey_NullEncoding() {
SECP256K1.PublicKey.create((Bytes) null);
}
@Test(expected = IllegalArgumentException.class)
public void createPublicKey_EncodingTooShort() {
SECP256K1.PublicKey.create(Bytes.wrap(new byte[63]));
}
@Test(expected = IllegalArgumentException.class)
public void createPublicKey_EncodingTooLong() {
SECP256K1.PublicKey.create(Bytes.wrap(new byte[65]));
}
@Test
public void publicKeyEquals() {
final SECP256K1.PublicKey publicKey1 =
SECP256K1.PublicKey.create(
fromHexString(
"a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7893aba425419bc27a3b6c7e693a24c696f794c2ed877a1593cbee53b037368d7"));
final SECP256K1.PublicKey publicKey2 =
SECP256K1.PublicKey.create(
fromHexString(
"a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7893aba425419bc27a3b6c7e693a24c696f794c2ed877a1593cbee53b037368d7"));
assertThat(publicKey2).isEqualTo(publicKey1);
}
@Test
public void publicHashCode() {
final SECP256K1.PublicKey publicKey =
SECP256K1.PublicKey.create(
fromHexString(
"a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7893aba425419bc27a3b6c7e693a24c696f794c2ed877a1593cbee53b037368d7"));
assertThat(publicKey.hashCode()).isNotZero();
}
@Test(expected = NullPointerException.class)
public void createKeyPair_PublicKeyNull() {
new SECP256K1.KeyPair(null, SECP256K1.PublicKey.create(Bytes.wrap(new byte[64])));
}
@Test(expected = NullPointerException.class)
public void createKeyPair_PrivateKeyNull() {
new SECP256K1.KeyPair(SECP256K1.PrivateKey.create(Bytes32.wrap(new byte[32])), null);
}
@Test
public void keyPairGeneration() {
final SECP256K1.KeyPair keyPair = SECP256K1.KeyPair.generate();
assertThat(keyPair).isNotNull();
assertThat(keyPair.getPrivateKey()).isNotNull();
assertThat(keyPair.getPublicKey()).isNotNull();
}
@Test
public void keyPairEquals() {
final SECP256K1.PrivateKey privateKey1 = SECP256K1.PrivateKey.create(BigInteger.TEN);
final SECP256K1.PrivateKey privateKey2 = SECP256K1.PrivateKey.create(BigInteger.TEN);
final SECP256K1.PublicKey publicKey1 =
SECP256K1.PublicKey.create(
fromHexString(
"a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7893aba425419bc27a3b6c7e693a24c696f794c2ed877a1593cbee53b037368d7"));
final SECP256K1.PublicKey publicKey2 =
SECP256K1.PublicKey.create(
fromHexString(
"a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7893aba425419bc27a3b6c7e693a24c696f794c2ed877a1593cbee53b037368d7"));
final SECP256K1.KeyPair keyPair1 = new SECP256K1.KeyPair(privateKey1, publicKey1);
final SECP256K1.KeyPair keyPair2 = new SECP256K1.KeyPair(privateKey2, publicKey2);
assertThat(keyPair2).isEqualTo(keyPair1);
}
@Test
public void keyPairHashCode() {
final SECP256K1.KeyPair keyPair = SECP256K1.KeyPair.generate();
assertThat(keyPair.hashCode()).isNotZero();
}
@Test
public void keyPairGeneration_PublicKeyRecovery() {
final SECP256K1.KeyPair keyPair = SECP256K1.KeyPair.generate();
assertThat(SECP256K1.PublicKey.create(keyPair.getPrivateKey()))
final KeyPair keyPair = secp256K1.generateKeyPair();
assertThat(secp256K1.createPublicKey(keyPair.getPrivateKey()))
.isEqualTo(keyPair.getPublicKey());
}
@Test
public void publicKeyRecovery() {
final SECP256K1.PrivateKey privateKey = SECP256K1.PrivateKey.create(BigInteger.TEN);
final SECP256K1.PublicKey expectedPublicKey =
SECP256K1.PublicKey.create(
fromHexString(
"a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7893aba425419bc27a3b6c7e693a24c696f794c2ed877a1593cbee53b037368d7"));
final SECP256K1.PublicKey publicKey = SECP256K1.PublicKey.create(privateKey);
assertThat(publicKey).isEqualTo(expectedPublicKey);
}
@Test
public void createSignature() {
final SECP256K1.Signature signature =
SECP256K1.Signature.create(BigInteger.ONE, BigInteger.TEN, (byte) 0);
assertThat(signature.getR()).isEqualTo(BigInteger.ONE);
assertThat(signature.getS()).isEqualTo(BigInteger.TEN);
assertThat(signature.getRecId()).isEqualTo((byte) 0);
}
@Test(expected = NullPointerException.class)
public void createSignature_NoR() {
SECP256K1.Signature.create(null, BigInteger.ZERO, (byte) 27);
}
@Test(expected = NullPointerException.class)
public void createSignature_NoS() {
SECP256K1.Signature.create(BigInteger.ZERO, null, (byte) 27);
}
@Test
public void recoverPublicKeyFromSignature() {
final SECP256K1.PrivateKey privateKey =
SECP256K1.PrivateKey.create(
final SECPPrivateKey privateKey =
secp256K1.createPrivateKey(
new BigInteger("c85ef7d79691fe79573b1a7064c19c1a9819ebdbd1faaab1a8ec92344438aaf4", 16));
final SECP256K1.KeyPair keyPair = SECP256K1.KeyPair.create(privateKey);
final KeyPair keyPair = secp256K1.createKeyPair(privateKey);
final Bytes data = Bytes.wrap("This is an example of a signed message.".getBytes(UTF_8));
final Bytes32 dataHash = keccak256(data);
final SECP256K1.Signature signature = SECP256K1.sign(dataHash, keyPair);
final SECPSignature signature = secp256K1.sign(dataHash, keyPair);
final SECP256K1.PublicKey recoveredPublicKey =
SECP256K1.PublicKey.recoverFromSignature(dataHash, signature).get();
final SECPPublicKey recoveredPublicKey =
secp256K1.recoverPublicKeyFromSignature(dataHash, signature).get();
assertThat(recoveredPublicKey.toString()).isEqualTo(keyPair.getPublicKey().toString());
}
@Test
public void signatureGeneration() {
final SECP256K1.PrivateKey privateKey =
SECP256K1.PrivateKey.create(
final SECPPrivateKey privateKey =
secp256K1.createPrivateKey(
new BigInteger("c85ef7d79691fe79573b1a7064c19c1a9819ebdbd1faaab1a8ec92344438aaf4", 16));
final SECP256K1.KeyPair keyPair = SECP256K1.KeyPair.create(privateKey);
final KeyPair keyPair = secp256K1.createKeyPair(privateKey);
final Bytes data = Bytes.wrap("This is an example of a signed message.".getBytes(UTF_8));
final Bytes32 dataHash = keccak256(data);
final SECP256K1.Signature expectedSignature =
SECP256K1.Signature.create(
final SECPSignature expectedSignature =
secp256K1.createSignature(
new BigInteger("d2ce488f4da29e68f22cb05cac1b19b75df170a12b4ad1bdd4531b8e9115c6fb", 16),
new BigInteger("75c1fe50a95e8ccffcbb5482a1e42fbbdd6324131dfe75c3b3b7f9a7c721eccb", 16),
(byte) 1);
final SECP256K1.Signature actualSignature = SECP256K1.sign(dataHash, keyPair);
final SECPSignature actualSignature = secp256K1.sign(dataHash, keyPair);
assertThat(actualSignature).isEqualTo(expectedSignature);
}
@Test
public void signatureVerification() {
final SECP256K1.PrivateKey privateKey =
SECP256K1.PrivateKey.create(
final SECPPrivateKey privateKey =
secp256K1.createPrivateKey(
new BigInteger("c85ef7d79691fe79573b1a7064c19c1a9819ebdbd1faaab1a8ec92344438aaf4", 16));
final SECP256K1.KeyPair keyPair = SECP256K1.KeyPair.create(privateKey);
final KeyPair keyPair = secp256K1.createKeyPair(privateKey);
final Bytes data = Bytes.wrap("This is an example of a signed message.".getBytes(UTF_8));
final Bytes32 dataHash = keccak256(data);
final SECP256K1.Signature signature = SECP256K1.sign(dataHash, keyPair);
assertThat(SECP256K1.verify(data, signature, keyPair.getPublicKey(), Hash::keccak256)).isTrue();
}
@Test
public void fileContainsValidPrivateKey() throws Exception {
final File file =
new File(
this.getClass()
.getResource("/org/hyperledger/besu/crypto/validPrivateKey.txt")
.toURI());
final SECP256K1.PrivateKey privateKey = KeyPairUtil.loadPrivateKey(file);
assertThat(privateKey.getEncodedBytes())
.isEqualTo(
Bytes.fromHexString(
"000000000000000000000000000000000000000000000000000000000000000A"));
}
@Test
public void readWritePrivateKeyString() throws Exception {
final SECP256K1.PrivateKey privateKey = SECP256K1.PrivateKey.create(BigInteger.TEN);
final SECP256K1.KeyPair keyPair1 = SECP256K1.KeyPair.create(privateKey);
final File tempFile = Files.createTempFile(suiteName(), ".keypair").toFile();
tempFile.deleteOnExit();
KeyPairUtil.storeKeyPair(keyPair1, tempFile);
final SECP256K1.KeyPair keyPair2 = KeyPairUtil.load(tempFile);
assertThat(keyPair2).isEqualTo(keyPair1);
final SECPSignature signature = secp256K1.sign(dataHash, keyPair);
assertThat(secp256K1.verify(data, signature, keyPair.getPublicKey(), Hash::keccak256)).isTrue();
}
@Test(expected = IllegalArgumentException.class)

Some files were not shown because too many files have changed in this diff Show More