BryanDavis has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/247923

Change subject: Add Auth\Password::hashEquals() function
......................................................................

Add Auth\Password::hashEquals() function

Add a wrapper/polyfill function for PHP 5.6's hash_equals() timing safe
string comparison function. The polyfill version is adapted from
MediaWiki's hash_equals() polyfill function.

Use the new function in Auth\Password::comparePasswordToHash() in place
of the previous identity equality check.

Change-Id: I698a43fe9d2624642a8d36c61f003ee6715c7cac
---
M src/Auth/Password.php
M tests/Auth/PasswordTest.php
2 files changed, 52 insertions(+), 1 deletion(-)


  git pull ssh://gerrit.wikimedia.org:29418/wikimedia/slimapp 
refs/changes/23/247923/1

diff --git a/src/Auth/Password.php b/src/Auth/Password.php
index d77ae28..6a66be2 100644
--- a/src/Auth/Password.php
+++ b/src/Auth/Password.php
@@ -54,7 +54,7 @@
                        $check = md5( $plainText );
                }
 
-               return $check === $hash;
+               return self::hashEquals( $hash, $check );
        }
 
 
@@ -243,6 +243,46 @@
 
 
        /**
+        * Check whether a user-provided string is equal to a fixed-length 
secret
+        * string without revealing bytes of the secret string through timing
+        * differences.
+        *
+        * Implementation for PHP deployments which do not natively have
+        * hash_equals taken from MediaWiki's hash_equals() polyfill function.
+        *
+        * @param string $known Fixed-length secret string to compare against
+        * @param string $input User-provided string
+        * @return bool True if the strings are the same, false otherwise
+        */
+       public static function hashEquals( $known, $input ) {
+               if ( function_exists( 'hash_equals' ) ) {
+                       return hash_equals( $known, $input );
+
+               } else {
+                       // hash_equals() polyfill taken from MediaWiki
+                       if ( !is_string( $known ) ) {
+                               return false;
+                       }
+                       if ( !is_string( $input ) ) {
+                               return false;
+                       }
+
+                       $len = strlen( $known );
+                       if ( $len !== strlen( $input ) ) {
+                               return false;
+                       }
+
+                       $result = 0;
+                       for ( $i = 0; $i < $len; $i++ ) {
+                               $result |= ord( $known[$i] ) ^ ord( $input[$i] 
);
+                       }
+
+                       return $result === 0;
+               }
+       }
+
+
+       /**
         * Construction of utility class is not allowed.
         */
        private function __construct() {
diff --git a/tests/Auth/PasswordTest.php b/tests/Auth/PasswordTest.php
index 814fba8..18a2286 100644
--- a/tests/Auth/PasswordTest.php
+++ b/tests/Auth/PasswordTest.php
@@ -43,6 +43,7 @@
 
        /**
         * @covers ::comparePasswordToHash
+        * @covers ::hashEquals
         */
        public function testComparePasswordToHash() {
                $enc = Password::encodePassword( 'password' );
@@ -61,4 +62,14 @@
                $this->assertEquals( 16, strlen( $p ) );
        }
 
+       /**
+        * @covers ::hashEquals
+        */
+       public function testHashEquals() {
+               $this->assertFalse( Password::hashEquals( false, '' ) );
+               $this->assertFalse( Password::hashEquals( '', false ) );
+               $this->assertFalse( Password::hashEquals( 'a', '' ) );
+               $this->assertFalse( Password::hashEquals( 'a', 'b' ) );
+               $this->assertTrue( Password::hashEquals( 'a', 'a' ) );
+       }
 }

-- 
To view, visit https://gerrit.wikimedia.org/r/247923
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I698a43fe9d2624642a8d36c61f003ee6715c7cac
Gerrit-PatchSet: 1
Gerrit-Project: wikimedia/slimapp
Gerrit-Branch: master
Gerrit-Owner: BryanDavis <[email protected]>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to