Author: thomasm
Date: Wed Mar 26 10:39:44 2014
New Revision: 1581782

URL: http://svn.apache.org/r1581782
Log:
OAK-1616 Password utility: prevent timing attacks

Modified:
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/util/PasswordUtil.java

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/util/PasswordUtil.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/util/PasswordUtil.java?rev=1581782&r1=1581781&r2=1581782&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/util/PasswordUtil.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/util/PasswordUtil.java
 Wed Mar 26 10:39:44 2014
@@ -175,7 +175,7 @@ public final class PasswordUtil {
                 }
 
                 String hash = generateHash(password, algorithm, salt, 
iterations);
-                return hashedPassword.equals(hash);
+                return compareSecure(hashedPassword, hash);
             } // hashedPassword is plaintext -> return false
         } catch (NoSuchAlgorithmException e) {
             log.warn(e.getMessage());
@@ -184,7 +184,36 @@ public final class PasswordUtil {
         }
         return false;
     }
-
+    
+    /**
+     * Compare two strings. The comparison is constant time: it will always 
loop
+     * over all characters and doesn't use conditional operations in the loop 
to
+     * make sure an attacker can not use a timing attack.
+     * 
+     * @param a
+     * @param b
+     * @return true if both parameters contain the same data.
+     */
+    private static boolean compareSecure(String a, String b) {
+        if ((a == null) || (b == null)) {
+            return (a == null) && (b == null);
+        }
+        int len = a.length();
+        if (len != b.length()) {
+            return false;
+        }
+        if (len == 0) {
+            return true;
+        }
+        // don't use conditional operations inside the loop
+        int bits = 0;
+        for (int i = 0; i < len; i++) {
+            // this will never reset any bits
+            bits |= a.charAt(i) ^ b.charAt(i);
+        }
+        return bits == 0;
+    }
+    
     //------------------------------------------------------------< private 
>---
 
     private static String generateHash(@Nonnull String pwd, @Nonnull String 
algorithm,


Reply via email to