diff --git a/bcos-executor/src/vm/Precompiled.cpp b/bcos-executor/src/vm/Precompiled.cpp index baa2735286..ad50d97b7a 100644 --- a/bcos-executor/src/vm/Precompiled.cpp +++ b/bcos-executor/src/vm/Precompiled.cpp @@ -27,6 +27,8 @@ #include "wedpr-crypto/WedprBn128.h" #include "wedpr-crypto/WedprCrypto.h" #include +#include + using namespace std; using namespace bcos; @@ -470,23 +472,17 @@ bytes blake2FCompression(uint32_t _rounds, bytesConstRef _stateVector, bytesCons const int RSV_LENGTH = 65; const int PUBLIC_KEY_LENGTH = 64; pair ecRecover(bytesConstRef _in) -{ // _in is hash(32),v(32),r(32),s(32), return address - - if (_in == bytesConstRef()) - { - BCOS_LOG(TRACE) << LOG_BADGE("Precompiled") << LOG_DESC("ecRecover: nullptr input"); - return {false, {}}; - } - - if (_in.size() != 64 + RSV_LENGTH - 1) +{ // _in is hash(32),v(32),r(32),s(32), return address + if (_in.size() <= 128 - 32) // must has hash(32),v(32),r(32),s(32) { - BCOS_LOG(TRACE) << LOG_BADGE("Precompiled") << LOG_DESC("ecRecover: invalid input size"); + BCOS_LOG(TRACE) << LOG_BADGE("Precompiled") + << LOG_DESC("ecRecover: must has hash(32),v(32),r(32),s(32)"); return {true, {}}; } BCOS_LOG(TRACE) << LOG_BADGE("Precompiled") << LOG_DESC("ecRecover: ") << _in.size(); - byte rawRSV[RSV_LENGTH]; - memcpy(rawRSV, _in.data() + 64, RSV_LENGTH - 1); + byte rawRSV[RSV_LENGTH] = {0}; + memcpy(rawRSV, _in.data() + 64, std::min(_in.size() - 64, (size_t)(RSV_LENGTH - 1))); rawRSV[RSV_LENGTH - 1] = (byte)((int)_in[63] - 27); crypto::HashType mHash; memcpy(mHash.data(), _in.data(), crypto::HashType::SIZE); diff --git a/bcos-executor/test/unittest/libvm/PrecompiledTest.cpp b/bcos-executor/test/unittest/libvm/PrecompiledTest.cpp index d8e7bdaec8..bad69ad7d4 100644 --- a/bcos-executor/test/unittest/libvm/PrecompiledTest.cpp +++ b/bcos-executor/test/unittest/libvm/PrecompiledTest.cpp @@ -47,6 +47,39 @@ BOOST_AUTO_TEST_CASE(ecrecoverSuccessTest) BOOST_CHECK_EQUAL(address, "0x6da0599583855f1618b380f6782c0c5c25cb96ec"); } +BOOST_AUTO_TEST_CASE(ecrecoverSuccessTest2) +{ + bytes params = *bcos::fromHexString( + "aa0f7414b7f8648410f9818df3a1f43419d5c30313f430712033937ae57854c8" // hash + "000000000000000000000000000000000000000000000000000000000000001b" // v + "acd0d6c91242e514655815073f5f0e9aed671f68a4ed3e3e9d693095779f704b" // r + "01932751f4431c3b4c9d6fb1c826d138ee155ea72ac9013d66929f6a265386b4"); // s + + auto [success, addressBytes] = crypto::ecRecover(ref(params)); + BOOST_CHECK(success); + auto address = + *bcos::toHexString(addressBytes.data() + 12, addressBytes.data() + 12 + 20, "0x"); + // 0xA5b4792dcAD4fE78D13f6Abd7BA1F302945DE4f7 lower cases + BOOST_CHECK_EQUAL(address, "0xa5b4792dcad4fe78d13f6abd7ba1f302945de4f7"); +} + +BOOST_AUTO_TEST_CASE(ecrecoverSuccessLargerTest) +{ + bytes params = *bcos::fromHexString( + "aa0f7414b7f8648410f9818df3a1f43419d5c30313f430712033937ae57854c8" // hash + "000000000000000000000000000000000000000000000000000000000000001b" // v + "acd0d6c91242e514655815073f5f0e9aed671f68a4ed3e3e9d693095779f704b" // r + "01932751f4431c3b4c9d6fb1c826d138ee155ea72ac9013d66929f6a265386b4" // s + "aabbccddeeff"); // no used extra data + + auto [success, addressBytes] = crypto::ecRecover(ref(params)); + BOOST_CHECK(success); + auto address = + *bcos::toHexString(addressBytes.data() + 12, addressBytes.data() + 12 + 20, "0x"); + // 0xA5b4792dcAD4fE78D13f6Abd7BA1F302945DE4f7 lower cases + BOOST_CHECK_EQUAL(address, "0xa5b4792dcad4fe78d13f6abd7ba1f302945de4f7"); +} + BOOST_AUTO_TEST_CASE(ecrecoverFailedTest) { bytes params = *bcos::fromHexString( @@ -61,6 +94,62 @@ BOOST_AUTO_TEST_CASE(ecrecoverFailedTest) BOOST_CHECK(addressBytes.empty()); // but return empty } + +BOOST_AUTO_TEST_CASE(ecrecoverInvalidVTest) +{ + bytes params = *bcos::fromHexString( + "aa0f7414b7f8648410f9818df3a1f43419d5c30313f430712033937ae57854c8" // hash + "000000000000000000000000000000000000000000000000000000000000001a" // v + "acd0d6c91242e514655815073f5f0e9aed671f68a4ed3e3e9d693095779f704b" // r + "01932751f4431c3b4c9d6fb1c826d138ee155ea72ac9013d66929f6a265386b4"); // s + + auto [success, addressBytes] = crypto::ecRecover(ref(params)); + BOOST_CHECK(success); // also success + BOOST_CHECK(addressBytes.empty()); // but return empty +} + +BOOST_AUTO_TEST_CASE(ecrecoverInvalidVTest2) +{ + bytes params = *bcos::fromHexString( + "aa0f7414b7f8648410f9818df3a1f43419d5c30313f430712033937ae57854c8" // hash + "000000000000000000000000000000000000000000000000000000000000001d" // v + "acd0d6c91242e514655815073f5f0e9aed671f68a4ed3e3e9d693095779f704b" // r + "01932751f4431c3b4c9d6fb1c826d138ee155ea72ac9013d66929f6a265386b4"); // s + + auto [success, addressBytes] = crypto::ecRecover(ref(params)); + BOOST_CHECK(success); // also success + BOOST_CHECK(addressBytes.empty()); // but return empty +} + +BOOST_AUTO_TEST_CASE(ecrecoverInvalidInputLenTest) +{ + bytes params = *bcos::fromHexString( + "aa0f7414b7f8648410f9818df3a1f43419d5c30313f430712033937ae57854c8" // hash + "000000000000000000000000000000000000000000000000000000000000001c" // v + "acd0d6c91242e514655815073f5f0e9aed671f68a4ed3e3e9d693095779f704b" // r + "01932751f4431c3b4c9d6fb1c826d138ee155ea72ac9013d66929f6a26538600"); // s + + auto [success, addressBytes] = crypto::ecRecover(ref(params)); + BOOST_CHECK(success); + auto address = + *bcos::toHexString(addressBytes.data() + 12, addressBytes.data() + 12 + 20, "0x"); + // 0x509eAd8B20064f21E35f920cB0c6d6cBC0C0Aa0d lower cases + BOOST_CHECK_EQUAL(address, "0x509ead8b20064f21e35f920cb0c6d6cbc0c0aa0d"); +} + +BOOST_AUTO_TEST_CASE(ecrecoverInvalidInputLenTest2) +{ + bytes params = *bcos::fromHexString( + "aa0f7414b7f8648410f9818df3a1f43419d5c30313f430712033937ae57854c8" // hash + "000000000000000000000000000000000000000000000000000000000000001c" // v + "acd0d6c91242e514655815073f5f0e9aed671f68a4ed3e3e9d693095779f704b"); // s + + auto [success, addressBytes] = crypto::ecRecover(ref(params)); + BOOST_CHECK(success); // also success + BOOST_CHECK(addressBytes.empty()); // but return empty +} + + BOOST_AUTO_TEST_SUITE_END() } // namespace bcos::test