directory-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From elecha...@apache.org
Subject svn commit: r1688300 - in /directory/shared/trunk/ldap/model/src: main/java/org/apache/directory/api/ldap/model/password/ test/java/org/apache/directory/api/ldap/model/password/
Date Mon, 29 Jun 2015 20:30:52 GMT
Author: elecharny
Date: Mon Jun 29 20:30:51 2015
New Revision: 1688300

URL: http://svn.apache.org/r1688300
Log:
timing attack patch

Added:
    directory/shared/trunk/ldap/model/src/test/java/org/apache/directory/api/ldap/model/password/
    directory/shared/trunk/ldap/model/src/test/java/org/apache/directory/api/ldap/model/password/PasswordUtilTest.java
Modified:
    directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/password/PasswordUtil.java

Modified: directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/password/PasswordUtil.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/password/PasswordUtil.java?rev=1688300&r1=1688299&r2=1688300&view=diff
==============================================================================
--- directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/password/PasswordUtil.java
(original)
+++ directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/password/PasswordUtil.java
Mon Jun 29 20:30:51 2015
@@ -27,7 +27,6 @@ import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 import java.security.SecureRandom;
 import java.security.spec.KeySpec;
-import java.util.Arrays;
 import java.util.Date;
 
 import javax.crypto.SecretKeyFactory;
@@ -275,14 +274,51 @@ public class PasswordUtil
             byte[] userPassword = PasswordUtil.encryptPassword( receivedCredentials, encryptionMethod.getAlgorithm(),
                 encryptionMethod.getSalt() );
 
-            // Now, compare the two passwords.
-            return Arrays.equals( userPassword, encryptedStored );
+            return compareBytes( userPassword, encryptedStored );
         }
         else
         {
-            return Arrays.equals( storedCredentials, receivedCredentials );
+            return compareBytes( receivedCredentials, storedCredentials );
         }
     }
+    
+    
+    /**
+     * Compare two byte[] in a constant time. This is necessary because using an Array.equals()
is
+     * not Timing attack safe ([1], [2] and [3]), a breach that can be exploited to break
some hashes.
+     * 
+     *  [1] https://en.wikipedia.org/wiki/Timing_attack
+     *  [2] http://rdist.root.org/2009/05/28/timing-attack-in-google-keyczar-library/
+     *  [3] https://cryptocoding.net/index.php/Coding_rules
+     */
+    private static boolean compareBytes( byte[] provided, byte[] stored )
+    {
+        if ( stored == null )
+        {
+            return provided == null;
+        }
+        else if ( provided == null )
+        {
+            return false;
+        }
+        
+        // Now, compare the two passwords, using a constant time method
+        if ( stored.length != provided.length )
+        {
+            return false;
+        }
+        
+        // loop on *every* byte in both passwords, and at the end, if one char at least is
different, return false.
+        int result = 0;
+        
+        for ( int i = 0; i < stored.length; i++ )
+        {
+            // If both bytes are equal, xor will be == 0, otherwise it will be != 0 and so
will result.
+            result |= ( stored[i] ^ provided[i] );
+        }
+        
+        return result == 0;
+    }
 
 
     /**

Added: directory/shared/trunk/ldap/model/src/test/java/org/apache/directory/api/ldap/model/password/PasswordUtilTest.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap/model/src/test/java/org/apache/directory/api/ldap/model/password/PasswordUtilTest.java?rev=1688300&view=auto
==============================================================================
--- directory/shared/trunk/ldap/model/src/test/java/org/apache/directory/api/ldap/model/password/PasswordUtilTest.java
(added)
+++ directory/shared/trunk/ldap/model/src/test/java/org/apache/directory/api/ldap/model/password/PasswordUtilTest.java
Mon Jun 29 20:30:51 2015
@@ -0,0 +1,59 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+
+package org.apache.directory.api.ldap.model.password;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertFalse;
+
+import org.apache.directory.api.util.Strings;
+import org.junit.Test;
+
+/**
+ * A test for the PasswordUtil class.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class PasswordUtilTest
+{
+
+    @Test
+    public void compareCredentialTest()
+    {
+        // Simple cases
+        assertTrue( PasswordUtil.compareCredentials( null, null ) );
+        assertTrue( PasswordUtil.compareCredentials( new byte[]{}, new byte[]{} ) );
+        assertTrue( PasswordUtil.compareCredentials( new byte[]{ 0x01 }, new byte[]{ 0x01
} ) );
+        
+        // Simple failures
+        assertFalse( PasswordUtil.compareCredentials( null, new byte[]{ 0x01 } ) );
+        assertFalse( PasswordUtil.compareCredentials( new byte[]{ 0x01 }, null ) );
+        assertFalse( PasswordUtil.compareCredentials( new byte[]{ 0x01 }, new byte[]{ 0x02
} ) );
+        
+        // With some different lengths
+        assertFalse( PasswordUtil.compareCredentials( Strings.getBytesUtf8( "Password1" ),
Strings.getBytesUtf8( "Password1 " ) ) );
+
+        // With different passwords
+        assertFalse( PasswordUtil.compareCredentials( Strings.getBytesUtf8( "Password1" ),
Strings.getBytesUtf8( "password1" ) ) );
+
+        // With same passwords
+        assertTrue( PasswordUtil.compareCredentials( Strings.getBytesUtf8( "Password1" ),
Strings.getBytesUtf8( "Password1" ) ) );
+    }
+}



Mime
View raw message