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