bool HTTPAuthorized(map<string, string>& mapHeaders)
{
string strAuth = mapHeaders["authorization"];
if (strAuth.substr(0,6) != "Basic ")
return false;
string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64);
string strUserPass = DecodeBase64(strUserPass64);
return strUserPass == strRPCUserColonPass;
}
Last string comparision strUserPass == strRPCUserColonPass gets compiled to:
do
{
if ( !len )
break;
less = *(_BYTE *)strUserPass < *(_BYTE *)strRPCUserColonPass;
eq = *(_BYTE *)strUserPass++ == *(_BYTE *)strRPCUserColonPass++;
--len;
}
while ( eq );
which is a byte-by-byte compare. Attacker with precise clock (being in the same LAN, for example) might learn the RPC password letter by letter, by trying passwords like 'a...", "b...", "c..." and observing which took the longest time to verify.
This code in bitcoinrpc.cpp:
if (mapArgs["-rpcpassword"].size() < 20)
MilliSleep(250);
protects from bruteforce for short password. Unfortunately, when run, bitcoind suggest a 32 chars password. Paradoxically short passwords are safer to use than longer ones, wrt to the timing leak.
Here's an example of time independent array comparison: http://rdist.root.org/2010/01/07/timing-independent-array-comparison/