Browse Source

Make RPC password resistant to timing attacks

Fixes issue#2838; this is a tweaked version of pull#2845 that
should not leak the length of the password and is more generic,
in case we run into other situations where we need
timing-attack-resistant comparisons.
0.8
Gavin Andresen 11 years ago committed by Warren Togami
parent
commit
5ee73ff86c
  1. 2
      src/bitcoinrpc.cpp
  2. 11
      src/test/util_tests.cpp
  3. 15
      src/util.h

2
src/bitcoinrpc.cpp

@ -479,7 +479,7 @@ bool HTTPAuthorized(map<string, string>& mapHeaders) @@ -479,7 +479,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);
}
//

11
src/test/util_tests.cpp

@ -323,4 +323,15 @@ BOOST_AUTO_TEST_CASE(util_seed_insecure_rand) @@ -323,4 +323,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()

15
src/util.h

@ -438,6 +438,21 @@ static inline uint32_t insecure_rand(void) @@ -438,6 +438,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
*/

Loading…
Cancel
Save