diff options
-rw-r--r-- | src/bitcoinrpc.cpp | 2 | ||||
-rw-r--r-- | src/test/util_tests.cpp | 11 | ||||
-rw-r--r-- | src/util.h | 15 |
3 files changed, 27 insertions, 1 deletions
diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp index a14f5e7060..d22809ce69 100644 --- a/src/bitcoinrpc.cpp +++ b/src/bitcoinrpc.cpp @@ -476,7 +476,7 @@ bool HTTPAuthorized(map<string, string>& mapHeaders) return false; string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64); string strUserPass = DecodeBase64(strUserPass64); - return strUserPass == strRPCUserColonPass; + return TimingResistantEqual(strUserPass, strRPCUserColonPass); } // diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp index fd936517fd..abfd882655 100644 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -291,4 +291,15 @@ BOOST_AUTO_TEST_CASE(util_seed_insecure_rand) } } +BOOST_AUTO_TEST_CASE(util_TimingResistantEqual) +{ + BOOST_CHECK(TimingResistantEqual(std::string(""), std::string(""))); + BOOST_CHECK(!TimingResistantEqual(std::string("abc"), std::string(""))); + BOOST_CHECK(!TimingResistantEqual(std::string(""), std::string("abc"))); + BOOST_CHECK(!TimingResistantEqual(std::string("a"), std::string("aa"))); + BOOST_CHECK(!TimingResistantEqual(std::string("aa"), std::string("a"))); + BOOST_CHECK(TimingResistantEqual(std::string("abc"), std::string("abc"))); + BOOST_CHECK(!TimingResistantEqual(std::string("abc"), std::string("aba"))); +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/src/util.h b/src/util.h index 9aea564406..c9614d3055 100644 --- a/src/util.h +++ b/src/util.h @@ -437,6 +437,21 @@ static inline uint32_t insecure_rand(void) */ void seed_insecure_rand(bool fDeterministic=false); +/** + * Timing-attack-resistant comparison. + * Takes time proportional to length + * of first argument. + */ +template <typename T> +bool TimingResistantEqual(const T& a, const T& b) +{ + if (b.size() == 0) return a.size() == 0; + size_t accumulator = a.size() ^ b.size(); + for (size_t i = 0; i < a.size(); i++) + accumulator |= a[i] ^ b[i%b.size()]; + return accumulator == 0; +} + /** Median filter over a stream of values. * Returns the median of the last N numbers */ |