Mitigate Timing Attacks On Basic RPC Authorization
authoralex <alex@alex-VirtualBox.(none)>
Sat, 24 Aug 2013 14:21:53 +0000 (18:21 +0400)
committeralex <alex@alex-VirtualBox.(none)>
Sat, 24 Aug 2013 14:21:53 +0000 (18:21 +0400)
Eliminates the possibility of timing attacks by changing the way the two passwords are compared.
It iterates through each char in the strings, and if the two chars it is comparing aren't the same, then it adds 1 to nReturn and the function, once it's done comparing all the chars, will return false. Previously, the function would return false on the first char that didn't match, allowing a possible attacker to run a timing attack.

See

https://github.com/bitcoin/bitcoin/pull/2886
http://rdist.root.org/2010/01/07/timing-independent-array-comparison/

for more detailed explanation.

src/bitcoinrpc.cpp
src/util.h

index d9ed3ac..645fa97 100644 (file)
@@ -490,7 +490,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);
 }
 
 //
index 83a4012..e83f554 100644 (file)
@@ -531,6 +531,20 @@ inline uint160 Hash160(const std::vector<unsigned char>& vch)
     return hash2;
 }
 
+/**
+ * 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