From a7c6679eee53032354763ee91a537f4e3df2d3d0 Mon Sep 17 00:00:00 2001 From: eum602 Date: Mon, 3 Jul 2023 15:05:22 -0500 Subject: [PATCH] falcon signature verification with public key digest result --- .../besu/config/GenesisConfigOptions.java | 2 + .../besu/config/JsonGenesisConfigOptions.java | 5 + .../besu/config/StubGenesisConfigOptions.java | 6 ++ config/src/main/resources/dev.json | 1 + crypto/algorithms/build.gradle | 2 +- .../org/hyperledger/besu/crypto/Hash.java | 16 ++++ .../hyperledger/besu/datatypes/Address.java | 2 + enclave/build.gradle | 4 +- ethereum/api/build.gradle | 6 +- .../mainnet/LacchainProtocolSpecs.java | 49 ++++++++++ .../mainnet/MainnetProtocolSpecFactory.java | 5 + .../mainnet/ProtocolScheduleBuilder.java | 2 + ethereum/trie/build.gradle | 2 +- ethereum/verkletrie/build.gradle | 2 +- .../gascalculator/FrontierGasCalculator.java | 7 ++ .../besu/evm/gascalculator/GasCalculator.java | 8 ++ .../precompile/FalconPrecompiledContract.java | 94 +++++++++++++++++++ .../besu/evm/precompile/Benchmarks.java | 45 +++++++++ gradle/verification-metadata.xml | 24 +++++ gradle/versions.gradle | 8 +- pki/build.gradle | 2 +- 21 files changed, 280 insertions(+), 12 deletions(-) create mode 100644 ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/LacchainProtocolSpecs.java create mode 100644 evm/src/main/java/org/hyperledger/besu/evm/precompile/FalconPrecompiledContract.java diff --git a/config/src/main/java/org/hyperledger/besu/config/GenesisConfigOptions.java b/config/src/main/java/org/hyperledger/besu/config/GenesisConfigOptions.java index 41f385fc4f5..caf339f42cd 100644 --- a/config/src/main/java/org/hyperledger/besu/config/GenesisConfigOptions.java +++ b/config/src/main/java/org/hyperledger/besu/config/GenesisConfigOptions.java @@ -394,6 +394,8 @@ default boolean isConsensusMigration() { */ OptionalLong getThanosBlockNumber(); + OptionalLong getLacchainPostQuantumBlockNumber(); + /** * Block number to activate Magneto on Classic networks. * diff --git a/config/src/main/java/org/hyperledger/besu/config/JsonGenesisConfigOptions.java b/config/src/main/java/org/hyperledger/besu/config/JsonGenesisConfigOptions.java index f9cf0696290..6a8a3568a4a 100644 --- a/config/src/main/java/org/hyperledger/besu/config/JsonGenesisConfigOptions.java +++ b/config/src/main/java/org/hyperledger/besu/config/JsonGenesisConfigOptions.java @@ -365,6 +365,11 @@ public OptionalLong getThanosBlockNumber() { return getOptionalLong("thanosblock"); } + @Override + public OptionalLong getLacchainPostQuantumBlockNumber() { + return getOptionalLong("lacchainpqblock"); + } + @Override public OptionalLong getMagnetoBlockNumber() { return getOptionalLong("magnetoblock"); diff --git a/config/src/main/java/org/hyperledger/besu/config/StubGenesisConfigOptions.java b/config/src/main/java/org/hyperledger/besu/config/StubGenesisConfigOptions.java index 949205e9b04..a13e7eca386 100644 --- a/config/src/main/java/org/hyperledger/besu/config/StubGenesisConfigOptions.java +++ b/config/src/main/java/org/hyperledger/besu/config/StubGenesisConfigOptions.java @@ -64,6 +64,7 @@ public class StubGenesisConfigOptions implements GenesisConfigOptions, Cloneable private OptionalLong aghartaBlockNumber = OptionalLong.empty(); private OptionalLong phoenixBlockNumber = OptionalLong.empty(); private OptionalLong thanosBlockNumber = OptionalLong.empty(); + private final OptionalLong lacchainPostQuantumBlockNumber = OptionalLong.empty(); private OptionalLong magnetoBlockNumber = OptionalLong.empty(); private OptionalLong mystiqueBlockNumber = OptionalLong.empty(); private Optional chainId = Optional.empty(); @@ -301,6 +302,11 @@ public OptionalLong getThanosBlockNumber() { return thanosBlockNumber; } + @Override + public OptionalLong getLacchainPostQuantumBlockNumber() { + return lacchainPostQuantumBlockNumber; + } + @Override public OptionalLong getMagnetoBlockNumber() { return magnetoBlockNumber; diff --git a/config/src/main/resources/dev.json b/config/src/main/resources/dev.json index a033d6768c3..5fe4b15015f 100644 --- a/config/src/main/resources/dev.json +++ b/config/src/main/resources/dev.json @@ -2,6 +2,7 @@ "config": { "chainId": 1337, "londonBlock": 0, + "lacchainpqblock": 0, "contractSizeLimit": 2147483647, "ethash": { "fixeddifficulty": 100 diff --git a/crypto/algorithms/build.gradle b/crypto/algorithms/build.gradle index 3421c990bf3..ad5346e2273 100644 --- a/crypto/algorithms/build.gradle +++ b/crypto/algorithms/build.gradle @@ -29,7 +29,7 @@ jar { } dependencies { - api 'org.bouncycastle:bcprov-jdk15on' + api 'org.bouncycastle:bcprov-jdk18on' api 'org.slf4j:slf4j-api' implementation 'net.java.dev.jna:jna' diff --git a/crypto/algorithms/src/main/java/org/hyperledger/besu/crypto/Hash.java b/crypto/algorithms/src/main/java/org/hyperledger/besu/crypto/Hash.java index b1b66f0f961..5b555d0eb73 100644 --- a/crypto/algorithms/src/main/java/org/hyperledger/besu/crypto/Hash.java +++ b/crypto/algorithms/src/main/java/org/hyperledger/besu/crypto/Hash.java @@ -26,6 +26,7 @@ import com.google.common.base.Suppliers; import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.bytes.Bytes32; +import org.bouncycastle.crypto.digests.SHAKEDigest; /** Various utilities for providing hashes (digests) of arbitrary data. */ public abstract class Hash { @@ -105,4 +106,19 @@ public static Bytes ripemd160(final Bytes input) { public static Bytes blake2bf(final Bytes input) { return Bytes.wrap(digestUsingAlgorithm(input, BLAKE2BF_SUPPLIER)); } + + /** + * Digest using Shake256 + * + * @param input The input bytes to produce the digest for + * @param outputLength the number of bytes to produce for the output length + * @return A digest + */ + public static Bytes shake256(final Bytes input, final int outputLength) { + SHAKEDigest digest = new SHAKEDigest(256); + digest.update(input.toArray(), 0, input.size()); + byte[] output = new byte[32]; + digest.doFinal(output, 0, outputLength); + return Bytes.wrap(output); + } } diff --git a/datatypes/src/main/java/org/hyperledger/besu/datatypes/Address.java b/datatypes/src/main/java/org/hyperledger/besu/datatypes/Address.java index 8862d9461e2..c68058e9796 100644 --- a/datatypes/src/main/java/org/hyperledger/besu/datatypes/Address.java +++ b/datatypes/src/main/java/org/hyperledger/besu/datatypes/Address.java @@ -70,6 +70,8 @@ public class Address extends DelegatingBytes { public static final Address BLS12_MAP_FP_TO_G1 = Address.precompiled(0x11); /** The constant BLS12_MAP_FP2_TO_G2. */ public static final Address BLS12_MAP_FP2_TO_G2 = Address.precompiled(0x12); + /** Constant for Precompiled Falcon verification signature. */ + public static final Address LACCHAIN_FALCON = Address.precompiled(0x13); /** The constant KZG_POINT_EVAL. */ public static final Address KZG_POINT_EVAL = Address.precompiled(0x14); /** The constant ZERO. */ diff --git a/enclave/build.gradle b/enclave/build.gradle index 302b2f246a4..103d7f1ab1f 100644 --- a/enclave/build.gradle +++ b/enclave/build.gradle @@ -9,7 +9,7 @@ dependencies { implementation 'io.vertx:vertx-web' implementation 'org.apache.tuweni:tuweni-net' - runtimeOnly('org.bouncycastle:bcpkix-jdk15on') + runtimeOnly('org.bouncycastle:bcpkix-jdk18on') // test dependencies. testImplementation project(':testutil') @@ -20,7 +20,7 @@ dependencies { // integration test dependencies. integrationTestImplementation project(':testutil') integrationTestImplementation 'org.assertj:assertj-core' - integrationTestImplementation 'org.bouncycastle:bcpkix-jdk15on' + integrationTestImplementation 'org.bouncycastle:bcpkix-jdk18on' integrationTestImplementation 'org.awaitility:awaitility' integrationTestImplementation 'org.junit.jupiter:junit-jupiter-api' integrationTestImplementation 'org.mockito:mockito-core' diff --git a/ethereum/api/build.gradle b/ethereum/api/build.gradle index 68b53a3b76a..060bf59fe7b 100644 --- a/ethereum/api/build.gradle +++ b/ethereum/api/build.gradle @@ -69,14 +69,14 @@ dependencies { implementation 'org.apache.tuweni:tuweni-toml' implementation 'org.apache.tuweni:tuweni-units' implementation 'org.antlr:antlr4-runtime' - implementation 'org.bouncycastle:bcprov-jdk15on' + implementation 'org.bouncycastle:bcprov-jdk18on' implementation 'org.springframework.security:spring-security-crypto' implementation 'org.xerial.snappy:snappy-java' annotationProcessor "org.immutables:value" implementation "org.immutables:value-annotations" - runtimeOnly 'org.bouncycastle:bcpkix-jdk15on' + runtimeOnly 'org.bouncycastle:bcpkix-jdk18on' runtimeOnly 'io.netty:netty-transport-native-epoll' runtimeOnly 'io.netty:netty-transport-native-kqueue' @@ -106,7 +106,7 @@ dependencies { testRuntimeOnly 'org.junit.vintage:junit-vintage-engine' - testSupportImplementation 'org.bouncycastle:bcpkix-jdk15on' + testSupportImplementation 'org.bouncycastle:bcpkix-jdk18on' integrationTestImplementation project(':config') integrationTestImplementation project(path: ':config', configuration: 'testSupportArtifacts') diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/LacchainProtocolSpecs.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/LacchainProtocolSpecs.java new file mode 100644 index 00000000000..0dcfe11129d --- /dev/null +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/LacchainProtocolSpecs.java @@ -0,0 +1,49 @@ +/* + * Copyright IADB. + * + * 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.ethereum.mainnet; + +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.evm.internal.EvmConfiguration; +import org.hyperledger.besu.evm.precompile.FalconPrecompiledContract; +import org.hyperledger.besu.evm.precompile.PrecompileContractRegistry; + +import java.math.BigInteger; +import java.util.Optional; +import java.util.OptionalInt; + +public class LacchainProtocolSpecs { + public static ProtocolSpecBuilder postQuantumDefinition( + final Optional chainId, + final OptionalInt contractSizeLimit, + final OptionalInt configStackSizeLimit, + final boolean enableRevertReason) { + return MainnetProtocolSpecs.istanbulDefinition( + chainId, + contractSizeLimit, + configStackSizeLimit, + enableRevertReason, + EvmConfiguration.DEFAULT) + .precompileContractRegistryBuilder( + precompiledContractConfiguration -> { + PrecompileContractRegistry lacchainContractsRegistry = + MainnetPrecompiledContractRegistries.istanbul(precompiledContractConfiguration); + lacchainContractsRegistry.put( + Address.LACCHAIN_FALCON, + new FalconPrecompiledContract( + precompiledContractConfiguration.getGasCalculator())); + return lacchainContractsRegistry; + }); + } +} diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecFactory.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecFactory.java index 3a06d803980..e7aa5953f14 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecFactory.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecFactory.java @@ -210,6 +210,11 @@ public ProtocolSpecBuilder experimentalEipsDefinition( evmConfiguration); } + public ProtocolSpecBuilder lacchainDefinition() { + return LacchainProtocolSpecs.postQuantumDefinition( + chainId, contractSizeLimit, evmStackSize, isRevertReasonEnabled); + } + //////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////// // Classic Protocol Specs diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ProtocolScheduleBuilder.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ProtocolScheduleBuilder.java index 786fdd35976..92f8e8026f8 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ProtocolScheduleBuilder.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ProtocolScheduleBuilder.java @@ -309,6 +309,8 @@ private Stream> createMilestones( config.getGrayGlacierBlockNumber(), specFactory.grayGlacierDefinition(config)), blockNumberMilestone( config.getMergeNetSplitBlockNumber(), specFactory.parisDefinition(config)), + blockNumberMilestone( + config.getLacchainPostQuantumBlockNumber(), specFactory.lacchainDefinition()), // Timestamp Forks timestampMilestone(config.getShanghaiTime(), specFactory.shanghaiDefinition(config)), timestampMilestone(config.getCancunTime(), specFactory.cancunDefinition(config)), diff --git a/ethereum/trie/build.gradle b/ethereum/trie/build.gradle index c671a75bf0f..0477841563d 100644 --- a/ethereum/trie/build.gradle +++ b/ethereum/trie/build.gradle @@ -37,7 +37,7 @@ dependencies { implementation 'com.google.guava:guava' implementation 'io.opentelemetry:opentelemetry-api' implementation 'org.apache.tuweni:tuweni-bytes' - implementation 'org.bouncycastle:bcprov-jdk15on' + implementation 'org.bouncycastle:bcprov-jdk18on' annotationProcessor 'org.immutables:value' diff --git a/ethereum/verkletrie/build.gradle b/ethereum/verkletrie/build.gradle index 0ca780ba88d..1d23538ed0c 100644 --- a/ethereum/verkletrie/build.gradle +++ b/ethereum/verkletrie/build.gradle @@ -37,7 +37,7 @@ dependencies { implementation 'io.opentelemetry:opentelemetry-api' implementation 'org.apache.tuweni:tuweni-bytes' implementation 'org.apache.tuweni:tuweni-units' - implementation 'org.bouncycastle:bcprov-jdk15on' + implementation 'org.bouncycastle:bcprov-jdk18on' implementation 'org.hyperledger.besu:ipa-multipoint' annotationProcessor "org.immutables:value" diff --git a/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/FrontierGasCalculator.java b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/FrontierGasCalculator.java index ed0c3c90d93..7abd20e151c 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/FrontierGasCalculator.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/FrontierGasCalculator.java @@ -119,6 +119,8 @@ public class FrontierGasCalculator implements GasCalculator { private static final long SELF_DESTRUCT_REFUND_AMOUNT = 24_000L; + private static final long FREC_PRECOMPILED_GAS_COST = 2100L; + @Override public long transactionIntrinsicGasCost(final Bytes payload, final boolean isContractCreate) { int zeros = 0; @@ -158,6 +160,11 @@ public long getEcrecPrecompiledContractGasCost() { return ECREC_PRECOMPILED_GAS_COST; } + @Override + public long getFrecPrecompiledContractGasCost() { + return FREC_PRECOMPILED_GAS_COST; + } + @Override public long sha256PrecompiledContractGasCost(final Bytes input) { return SHA256_PRECOMPILED_WORD_GAS_COST * Words.numWords(input) diff --git a/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/GasCalculator.java b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/GasCalculator.java index cd8b659051d..a4ed9cad3dd 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/GasCalculator.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/GasCalculator.java @@ -34,6 +34,7 @@ import org.hyperledger.besu.evm.operation.SLoadOperation; import org.hyperledger.besu.evm.operation.SelfDestructOperation; import org.hyperledger.besu.evm.precompile.ECRECPrecompiledContract; +import org.hyperledger.besu.evm.precompile.FalconPrecompiledContract; import org.hyperledger.besu.evm.precompile.IDPrecompiledContract; import org.hyperledger.besu.evm.precompile.RIPEMD160PrecompiledContract; import org.hyperledger.besu.evm.precompile.SHA256PrecompiledContract; @@ -75,6 +76,13 @@ public interface GasCalculator { */ long getEcrecPrecompiledContractGasCost(); + /** + * Returns the gas cost to execute the {@link FalconPrecompiledContract}. + * + * @return the gas cost to execute the Falcon Signature verification precompiled contract + */ + long getFrecPrecompiledContractGasCost(); + /** * Returns the gas cost to execute the {@link SHA256PrecompiledContract}. * diff --git a/evm/src/main/java/org/hyperledger/besu/evm/precompile/FalconPrecompiledContract.java b/evm/src/main/java/org/hyperledger/besu/evm/precompile/FalconPrecompiledContract.java new file mode 100644 index 00000000000..1bbd07d5914 --- /dev/null +++ b/evm/src/main/java/org/hyperledger/besu/evm/precompile/FalconPrecompiledContract.java @@ -0,0 +1,94 @@ +/* + * Copyright IADB. + * + * 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.evm.precompile; + +import static java.nio.charset.StandardCharsets.UTF_8; + +import org.hyperledger.besu.crypto.Hash; +import org.hyperledger.besu.evm.frame.MessageFrame; +import org.hyperledger.besu.evm.gascalculator.GasCalculator; + +import javax.annotation.Nonnull; + +import org.apache.tuweni.bytes.Bytes; +import org.apache.tuweni.bytes.Bytes32; +import org.bouncycastle.pqc.crypto.falcon.FalconParameters; +import org.bouncycastle.pqc.crypto.falcon.FalconPublicKeyParameters; +import org.bouncycastle.pqc.crypto.falcon.FalconSigner; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class FalconPrecompiledContract extends AbstractPrecompiledContract { + + private static final Logger LOG = LoggerFactory.getLogger(AbstractBLS12PrecompiledContract.class); + + private static final Bytes METHOD_ABI = + Hash.keccak256(Bytes.of("verify(bytes,bytes,bytes32)".getBytes(UTF_8))).slice(0, 4); + private static final String SIGNATURE_ALGORITHM = "Falcon-512"; + + private final FalconSigner falconSigner = new FalconSigner(); + + public FalconPrecompiledContract(final GasCalculator gasCalculator) { + super("Falcon", gasCalculator); + } + + @Override + public long gasRequirement(final Bytes input) { + long value = gasCalculator().getFrecPrecompiledContractGasCost(); + LOG.debug("Gas requirement calculation for Falcon has been called {}", value); + return value; + } + + @Nonnull + @Override + public PrecompileContractResult computePrecompile( + final Bytes methodInput, @Nonnull final MessageFrame messageFrame) { + Bytes methodAbi = methodInput.slice(0, METHOD_ABI.size()); + if (!methodAbi.xor(METHOD_ABI).isZero()) { + throw new IllegalArgumentException("Unexpected method ABI: " + methodAbi.toHexString()); + } + Bytes input = methodInput.slice(METHOD_ABI.size()); + int signatureOffset = input.slice(0, 32).trimLeadingZeros().toInt(); + int pubKeyOffset = input.slice(32, 32).trimLeadingZeros().toInt(); + + int signatureLength = input.slice(signatureOffset, 32).trimLeadingZeros().toInt(); + int pubKeyLength = input.slice(pubKeyOffset, 32).trimLeadingZeros().toInt(); + int dataLength = 32; + + Bytes signatureSlice = input.slice(signatureOffset + 32, signatureLength); + Bytes pubKeySlice = input.slice(pubKeyOffset + 32 + 1, pubKeyLength - 1); + Bytes dataSlice = input.slice(64, dataLength); + + if (LOG.isTraceEnabled()) { + LOG.trace( + "{} verify: signature={}, pubKey={}, data={}", + SIGNATURE_ALGORITHM, + signatureSlice.toHexString(), + pubKeySlice.toHexString(), + dataSlice.toHexString()); + } + FalconPublicKeyParameters falconPublicKeyParameters = + new FalconPublicKeyParameters(FalconParameters.falcon_512, pubKeySlice.toArray()); + falconSigner.init(false, falconPublicKeyParameters); + final boolean verifies = + falconSigner.verifySignature(dataSlice.toArray(), signatureSlice.toArray()); + if (verifies) { + Bytes digest = Hash.shake256(input.slice(pubKeyOffset + 32, pubKeyLength), 32); + return PrecompileContractResult.success(Bytes32.leftPad(digest)); + } else { + return PrecompileContractResult.success(Bytes32.leftPad(Bytes.of(0))); + } + } +} diff --git a/evm/src/test/java/org/hyperledger/besu/evm/precompile/Benchmarks.java b/evm/src/test/java/org/hyperledger/besu/evm/precompile/Benchmarks.java index 94230483ca5..3bdbb4ee9b8 100644 --- a/evm/src/test/java/org/hyperledger/besu/evm/precompile/Benchmarks.java +++ b/evm/src/test/java/org/hyperledger/besu/evm/precompile/Benchmarks.java @@ -45,6 +45,7 @@ import com.google.common.collect.ImmutableMap; import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.bytes.Bytes32; +import org.bouncycastle.util.encoders.Hex; public class Benchmarks { @@ -613,6 +614,49 @@ private static void benchBLS12MapFP2TOG2() { (int) gasSpent, contract.gasRequirement(arg)); } + private static void benchFalcon512() { + final FalconPrecompiledContract contract = + new FalconPrecompiledContract(new IstanbulGasCalculator()); + byte[] bytesSig = + Hex.decode( + "3933b3c07507e4201748494d832b6ee2a6c93bff9b0ee343b550d1f85a3d0de0d704c6d1784295130960fbe956c6851e141ab3c09a5475bdda2d81ee113f1e16e2ddd8e408bbb3f5b06a555d8f1ac072e5be2f9a365b33ace3d8254709c185b6f3d3db4b50baf14536779f24b5e843fb36b5a00ca475d1801a964d09961c1959dad0f80f0615476c75f58e4ae9a9f8eb93e65f1a4753ca75a62269d74a49ddc75f539bfecd60fe3c8966e77b01d9c69a965a39907862b2de754ad319644d21134fccee194278b326aa4e94359f1d4a08814cad9b27d62687cc31cfcf057490cea0512e02b3b3834e6803c30679f2f2ae2bf4d4e670b283f5105dad272da0f8b95168ea1080b184d98787ba335c22a0a40fd5ba4a70d905c373304c2759e695214f741b98629184789ffdaf63731b43188bda77ed49924da34968ee347b973b525ce0b40af92889b479e5e8717c05c923d76f0bf4689747de1821c1c42968eb164a5fe7c25ef75629511ce220c9d71c4fdb4d60b927b1e473dcda691062b6977338e8666b8c82b8f0f118eefeb5e66e408e63aa9cf876a0a4249688aae132955f5ea98fff2bb4f565b4ec4db39d414dd9c9d3edd089ac74af2f9f3feffa72332982d5e470a74bb2b3b7462639ed89319a327e8a11aef2e3cc391789b4c616b1aef335e9b47a294a47d2c42e7daca30c119e8098b6895aa32bb989a675aa72e84dc1ccc8b9f1a6cd274adbb86fc5ca9c2744cd73f064eba715e06dce542ef0646c94f41d3f47bb7c1a6c4e91ee55996dec4cbbc931f0047e3ba251f71b0bbc7e8633cc7479b1361697a131436d5958ee6fd1ccc1a5d31a9a8391bde2d075cce140de8f1dc58a093310821ae1d26917bc2a17dec09225374ee078d977f901825955ec8623304459a51e5cf7fe60c68b1680"); // signer.generateSignature(shake256Length32Message); + byte[] bytesPublicKey = + Hex.decode( + "096BA86CB658A8F445C9A5E4C28374BEC879C8655F68526923240918074D0147C03162E4A49200648C652803C6FD7509AE9AA799D6310D0BD42724E0635920186207000767CA5A8546B1755308C304B84FC93B069E265985B398D6B834698287FF829AA820F17A7F4226AB21F601EBD7175226BAB256D8888F009032566D6383D68457EA155A94301870D589C678ED304259E9D37B193BC2A7CCBCBEC51D69158C44073AEC9792630253318BC954DBF50D15028290DC2D309C7B7B02A6823744D463DA17749595CB77E6D16D20D1B4C3AAD89D320EBE5A672BB96D6CD5C1EFEC8B811200CBB062E473352540EDDEF8AF9499F8CDD1DC7C6873F0C7A6BCB7097560271F946849B7F373640BB69CA9B518AA380A6EB0A7275EE84E9C221AED88F5BFBAF43A3EDE8E6AA42558104FAF800E018441930376C6F6E751569971F47ADBCA5CA00C801988F317A18722A29298925EA154DBC9024E120524A2D41DC0F18FD8D909F6C50977404E201767078BA9A1F9E40A8B2BA9C01B7DA3A0B73A4C2A6B4F518BBEE3455D0AF2204DDC031C805C72CCB647940B1E6794D859AAEBCEA0DEB581D61B9248BD9697B5CB974A8176E8F910469CAE0AB4ED92D2AEE9F7EB50296DAF8057476305C1189D1D9840A0944F0447FB81E511420E67891B98FA6C257034D5A063437D379177CE8D3FA6EAF12E2DBB7EB8E498481612B1929617DA5FB45E4CDF893927D8BA842AA861D9C50471C6D0C6DF7E2BB26465A0EB6A3A709DE792AAFAAF922AA95DD5920B72B4B8856C6E632860B10F5CC08450003671AF388961872B466400ADB815BA81EA794945D19A100622A6CA0D41C4EA620C21DC125119E372418F04402D9FA7180F7BC89AFA54F8082244A42F46E5B5ABCE87B50A7D6FEBE8D7BBBAC92657CBDA1DB7C25572A4C1D0BAEA30447A865A2B1036B880037E2F4D26D453E9E913259779E9169B28A62EB809A5C744E04E260E1F2BBDA874F1AC674839DDB47B3148C5946DE0180148B7973D63C58193B17CD05D16E80CD7928C2A338363A23A81C0608C87505589B9DA1C617E7B70786B6754FBB30A5816810B9E126CFCC5AA49326E9D842973874B6359B5DB75610BA68A98C7B5E83F125A82522E13B83FB8F864E2A97B73B5D544A7415B6504A13939EAB1595D64FAF41FAB25A864A574DE524405E878339877886D2FC07FA0311508252413EDFA1158466667AFF78386DAF7CB4C9B850992F96E20525330599AB601D454688E294C8C3E"); + byte[] messageToSign = + Hex.decode("3d474d06cef2d8da1c97afd7d4993ba792297ca4e161967578494141cab04202"); + + final int sigLen = bytesSig.length; // ~658; + final int pubKeyLen = bytesPublicKey.length; // 897; + + final Bytes signatureLength = Bytes32.leftPad(Bytes.ofUnsignedInt(sigLen)); + final Bytes pubKeyLength = Bytes32.leftPad(Bytes.ofUnsignedInt(pubKeyLen)); + // 4 bytes method signature | 32 bytes signature offset | 32 bytes public key offset | 32 bytes + // dataOffset | + // signature (len+slice) | public key (len+slice) | data (len+slice) + final int sigOff = 96; + final int pubKeyOff = sigOff + 32 + sigLen; + final Bytes signatureOffset = Bytes32.leftPad(Bytes.ofUnsignedInt(sigOff)); + final Bytes publicKeyOffset = Bytes32.leftPad(Bytes.ofUnsignedInt(pubKeyOff)); + final Bytes signature = Bytes.concatenate(signatureLength, Bytes.wrap(bytesSig)); + final Bytes publicKey = Bytes.concatenate(pubKeyLength, Bytes.wrap(bytesPublicKey)); + + final Bytes input = + Bytes.concatenate( + Hash.keccak256(Bytes.of("verify(bytes,bytes,bytes32)".getBytes(UTF_8))).slice(0, 4), + signatureOffset, + publicKeyOffset, + Bytes.wrap(messageToSign), + signature, + publicKey); + System.out.println("Gas requirement " + contract.gasRequirement(input)); + final double gasSpent = runBenchmark(input, contract); + + System.out.printf( + "Falcon-512 for %,d gas. Charging %,d gas.%n", + (int) gasSpent, contract.gasRequirement(input)); + } + private static double runBenchmark(final Bytes arg, final PrecompiledContract contract) { if (contract.computePrecompile(arg, fakeFrame).getOutput() == null) { throw new RuntimeException("Input is Invalid"); @@ -650,5 +694,6 @@ public static void main(final String[] args) { benchBLS12Pair(); benchBLS12MapFPTOG1(); benchBLS12MapFP2TOG2(); + benchFalcon512(); } } diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 5d84c51d99d..5a42be2c72e 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -3545,6 +3545,14 @@ + + + + + + + + @@ -3569,6 +3577,14 @@ + + + + + + + + @@ -3585,6 +3601,14 @@ + + + + + + + + diff --git a/gradle/versions.gradle b/gradle/versions.gradle index 88e87bdf01f..0c8736a0b8a 100644 --- a/gradle/versions.gradle +++ b/gradle/versions.gradle @@ -156,9 +156,9 @@ dependencyManagement { dependency 'org.awaitility:awaitility:4.2.0' - dependencySet(group: 'org.bouncycastle', version: '1.70') { - entry'bcpkix-jdk15on' - entry'bcprov-jdk15on' + dependencySet(group: 'org.bouncycastle', version: '1.73') { + entry'bcpkix-jdk18on' + entry'bcprov-jdk18on' } dependency 'org.fusesource.jansi:jansi:2.4.0' @@ -221,6 +221,8 @@ dependencyManagement { dependency 'org.springframework.security:spring-security-crypto:6.0.2' dependency 'org.testcontainers:testcontainers:1.17.6' + dependency 'org.openquantumsafe:liboqs-java:1.1-SNAPSHOT' + dependency 'org.web3j:quorum:4.9.5' dependencySet(group: 'org.web3j', version: '4.9.7') { diff --git a/pki/build.gradle b/pki/build.gradle index a3edd47ce74..8742ce4bc68 100644 --- a/pki/build.gradle +++ b/pki/build.gradle @@ -32,7 +32,7 @@ dependencies { implementation 'com.google.guava:guava' implementation 'org.apache.tuweni:tuweni-bytes' - implementation 'org.bouncycastle:bcpkix-jdk15on' + implementation 'org.bouncycastle:bcpkix-jdk18on' testImplementation 'junit:junit' testImplementation 'org.assertj:assertj-core'