Issue #3053956 by alexpott, neeravbm, aleevas, voleger, Berdir: Deprecate \Drupal\Component\Utility\Crypt::hashEquals() in favour of PHP's builtin hash_equals()
parent
a3ce6e70ed
commit
17153a2605
|
@ -679,7 +679,7 @@ function drupal_valid_test_ua($new_prefix = NULL) {
|
|||
$test_hmac = Crypt::hmacBase64($check_string, $key);
|
||||
// Since we are making a local request a 600 second time window is allowed,
|
||||
// and the HMAC must match.
|
||||
if ($time_diff >= 0 && $time_diff <= 600 && Crypt::hashEquals($test_hmac, $hmac)) {
|
||||
if ($time_diff >= 0 && $time_diff <= 600 && hash_equals($test_hmac, $hmac)) {
|
||||
$test_prefix = $prefix;
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -91,10 +91,13 @@ class Crypt {
|
|||
* @return bool
|
||||
* Returns TRUE when the two strings are equal, FALSE otherwise.
|
||||
*
|
||||
* @todo Deprecate in favor of hash_equals().
|
||||
* https://www.drupal.org/node/3053956
|
||||
* @deprecated in drupal:8.8.0 and is removed from drupal:9.0.0.
|
||||
* Use PHP's built-in hash_equals() function instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/3054488
|
||||
*/
|
||||
public static function hashEquals($known_string, $user_string) {
|
||||
@trigger_error(__CLASS__ . '::hashEquals() is deprecated in drupal:8.8.0 and is removed from drupal:9.0.0. Use PHP\'s built-in hash_equals() function instead. See https://www.drupal.org/node/3054488', E_USER_DEPRECATED);
|
||||
return hash_equals($known_string, $user_string);
|
||||
}
|
||||
|
||||
|
|
|
@ -87,7 +87,7 @@ class CsrfTokenGenerator {
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
return Crypt::hashEquals($this->computeToken($seed, $value), $token);
|
||||
return hash_equals($this->computeToken($seed, $value), $token);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
|
||||
namespace Drupal\Core\Password;
|
||||
|
||||
use Drupal\Component\Utility\Crypt;
|
||||
|
||||
/**
|
||||
* Secure password hashing functions based on the Portable PHP password
|
||||
* hashing framework.
|
||||
|
@ -248,8 +246,8 @@ class PhpassHashedPassword implements PasswordInterface {
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
// Compare using hashEquals() instead of === to mitigate timing attacks.
|
||||
return $computed_hash && Crypt::hashEquals($stored_hash, $computed_hash);
|
||||
// Compare using hash_equals() instead of === to mitigate timing attacks.
|
||||
return $computed_hash && hash_equals($stored_hash, $computed_hash);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -72,7 +72,7 @@ class ContextualController implements ContainerInjectionInterface {
|
|||
|
||||
$rendered = [];
|
||||
foreach ($ids as $key => $id) {
|
||||
if (!isset($tokens[$key]) || !Crypt::hashEquals($tokens[$key], Crypt::hmacBase64($id, Settings::getHashSalt() . \Drupal::service('private_key')->get()))) {
|
||||
if (!isset($tokens[$key]) || !hash_equals($tokens[$key], Crypt::hmacBase64($id, Settings::getHashSalt() . \Drupal::service('private_key')->get()))) {
|
||||
throw new BadRequestHttpException('Invalid contextual ID specified.');
|
||||
}
|
||||
$element = [
|
||||
|
|
|
@ -111,7 +111,7 @@ class ManagedFile extends FormElement {
|
|||
elseif (\Drupal::currentUser()->isAnonymous()) {
|
||||
$token = NestedArray::getValue($form_state->getUserInput(), array_merge($element['#parents'], ['file_' . $file->id(), 'fid_token']));
|
||||
$file_hmac = Crypt::hmacBase64('file-' . $file->id(), \Drupal::service('private_key')->get() . Settings::getHashSalt());
|
||||
if ($token === NULL || !Crypt::hashEquals($file_hmac, $token)) {
|
||||
if ($token === NULL || !hash_equals($file_hmac, $token)) {
|
||||
$force_default = TRUE;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -109,7 +109,7 @@ class ImageStyleDownloadController extends FileDownloadController {
|
|||
// starts with styles/.
|
||||
$valid = !empty($image_style) && $this->streamWrapperManager->isValidScheme($scheme);
|
||||
if (!$this->config('image.settings')->get('allow_insecure_derivatives') || strpos(ltrim($target, '\/'), 'styles/') === 0) {
|
||||
$valid &= Crypt::hashEquals($image_style->getPathToken($image_uri), $request->query->get(IMAGE_DERIVATIVE_TOKEN, ''));
|
||||
$valid &= hash_equals($image_style->getPathToken($image_uri), $request->query->get(IMAGE_DERIVATIVE_TOKEN, ''));
|
||||
}
|
||||
if (!$valid) {
|
||||
// Return a 404 (Page Not Found) rather than a 403 (Access Denied) as the
|
||||
|
|
|
@ -125,7 +125,7 @@ class OEmbedIframeController implements ContainerInjectionInterface {
|
|||
// Hash the URL and max dimensions, and ensure it is equal to the hash
|
||||
// parameter passed in the query string.
|
||||
$hash = $this->iFrameUrlHelper->getHash($url, $max_width, $max_height);
|
||||
if (!Crypt::hashEquals($hash, $request->query->get('hash', ''))) {
|
||||
if (!hash_equals($hash, $request->query->get('hash', ''))) {
|
||||
throw new AccessDeniedHttpException('This resource is not available');
|
||||
}
|
||||
|
||||
|
|
|
@ -187,7 +187,7 @@ class MediaLibraryState extends ParameterBag {
|
|||
* The hashed parameters.
|
||||
*/
|
||||
public function isValidHash($hash) {
|
||||
return Crypt::hashEquals($this->getHash(), $hash);
|
||||
return hash_equals($this->getHash(), $hash);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -87,7 +87,7 @@ class EntityAutocompleteController extends ControllerBase {
|
|||
$selection_settings = $this->keyValue->get($selection_settings_key, FALSE);
|
||||
if ($selection_settings !== FALSE) {
|
||||
$selection_settings_hash = Crypt::hmacBase64(serialize($selection_settings) . $target_type . $selection_handler, Settings::getHashSalt());
|
||||
if (!Crypt::hashEquals($selection_settings_hash, $selection_settings_key)) {
|
||||
if (!hash_equals($selection_settings_hash, $selection_settings_key)) {
|
||||
// Disallow access when the selection settings hash does not match the
|
||||
// passed-in key.
|
||||
throw new AccessDeniedHttpException('Invalid selection settings key.');
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
namespace Drupal\toolbar\Controller;
|
||||
|
||||
use Drupal\Component\Utility\Crypt;
|
||||
use Drupal\Core\Access\AccessResult;
|
||||
use Drupal\Core\Ajax\AjaxResponse;
|
||||
use Drupal\Core\Controller\ControllerBase;
|
||||
|
@ -49,7 +48,7 @@ class ToolbarController extends ControllerBase {
|
|||
*/
|
||||
public function checkSubTreeAccess($hash) {
|
||||
$expected_hash = _toolbar_get_subtrees_hash()[0];
|
||||
return AccessResult::allowedIf($this->currentUser()->hasPermission('access toolbar') && Crypt::hashEquals($expected_hash, $hash))->cachePerPermissions();
|
||||
return AccessResult::allowedIf($this->currentUser()->hasPermission('access toolbar') && hash_equals($expected_hash, $hash))->cachePerPermissions();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
namespace Drupal\user;
|
||||
|
||||
use Drupal\Component\Datetime\TimeInterface;
|
||||
use Drupal\Component\Utility\Crypt;
|
||||
use Drupal\Core\Entity\ContentEntityForm;
|
||||
use Drupal\Core\Entity\EntityConstraintViolationListInterface;
|
||||
use Drupal\Core\Entity\EntityRepositoryInterface;
|
||||
|
@ -131,7 +130,7 @@ abstract class AccountForm extends ContentEntityForm {
|
|||
// so it persists even on subsequent Ajax requests.
|
||||
if (!$form_state->get('user_pass_reset') && ($token = $this->getRequest()->get('pass-reset-token'))) {
|
||||
$session_key = 'pass_reset_' . $account->id();
|
||||
$user_pass_reset = isset($_SESSION[$session_key]) && Crypt::hashEquals($_SESSION[$session_key], $token);
|
||||
$user_pass_reset = isset($_SESSION[$session_key]) && hash_equals($_SESSION[$session_key], $token);
|
||||
$form_state->set('user_pass_reset', $user_pass_reset);
|
||||
}
|
||||
|
||||
|
|
|
@ -226,7 +226,7 @@ class UserController extends ControllerBase {
|
|||
$this->messenger()->addError($this->t('You have tried to use a one-time login link that has expired. Please request a new one using the form below.'));
|
||||
return $this->redirect('user.pass');
|
||||
}
|
||||
elseif ($user->isAuthenticated() && ($timestamp >= $user->getLastLoginTime()) && ($timestamp <= $current) && Crypt::hashEquals($hash, user_pass_rehash($user, $timestamp))) {
|
||||
elseif ($user->isAuthenticated() && ($timestamp >= $user->getLastLoginTime()) && ($timestamp <= $current) && hash_equals($hash, user_pass_rehash($user, $timestamp))) {
|
||||
user_login_finalize($user);
|
||||
$this->logger->notice('User %name used one-time login link at time %timestamp.', ['%name' => $user->getDisplayName(), '%timestamp' => $timestamp]);
|
||||
$this->messenger()->addStatus($this->t('You have just used your one-time login link. It is no longer necessary to use this link to log in. Please change your password.'));
|
||||
|
@ -324,7 +324,7 @@ class UserController extends ControllerBase {
|
|||
$account_data = $this->userData->get('user', $user->id());
|
||||
if (isset($account_data['cancel_method']) && !empty($timestamp) && !empty($hashed_pass)) {
|
||||
// Validate expiration and hashed password/login.
|
||||
if ($timestamp <= $current && $current - $timestamp < $timeout && $user->id() && $timestamp >= $user->getLastLoginTime() && Crypt::hashEquals($hashed_pass, user_pass_rehash($user, $timestamp))) {
|
||||
if ($timestamp <= $current && $current - $timestamp < $timeout && $user->id() && $timestamp >= $user->getLastLoginTime() && hash_equals($hashed_pass, user_pass_rehash($user, $timestamp))) {
|
||||
$edit = [
|
||||
'user_cancel_notify' => isset($account_data['cancel_notify']) ? $account_data['cancel_notify'] : $this->config('user.settings')->get('notify.status_canceled'),
|
||||
];
|
||||
|
|
|
@ -40,7 +40,7 @@ catch (HttpExceptionInterface $e) {
|
|||
if (Settings::get('rebuild_access', FALSE) ||
|
||||
($request->query->get('token') && $request->query->get('timestamp') &&
|
||||
((REQUEST_TIME - $request->query->get('timestamp')) < 300) &&
|
||||
Crypt::hashEquals(Crypt::hmacBase64($request->query->get('timestamp'), Settings::get('hash_salt')), $request->query->get('token'))
|
||||
hash_equals(Crypt::hmacBase64($request->query->get('timestamp'), Settings::get('hash_salt')), $request->query->get('token'))
|
||||
)) {
|
||||
// Clear user cache for all major platforms.
|
||||
$user_caches = [
|
||||
|
|
|
@ -148,4 +148,17 @@ class CryptTest extends TestCase {
|
|||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Legacy test of Drupal\Component\Utility\Crypt::hashEquals() method.
|
||||
*
|
||||
* @expectedDeprecation Drupal\Component\Utility\Crypt::hashEquals() is deprecated in drupal:8.8.0 and is removed from drupal:9.0.0. Use PHP's built-in hash_equals() function instead. See https://www.drupal.org/node/3054488
|
||||
* @group legacy
|
||||
*/
|
||||
public function testHashEquals() {
|
||||
$a_hash = Crypt::hashBase64('a');
|
||||
$b_hash = Crypt::hashBase64('b');
|
||||
$this->assertTrue(Crypt::hashEquals($a_hash, $a_hash));
|
||||
$this->assertFalse(Crypt::hashEquals($a_hash, $b_hash));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue