From 7450ec001961b228aeec917b6ddf626d283900ec Mon Sep 17 00:00:00 2001 From: Gregor Harlan Date: Tue, 7 Apr 2026 23:19:00 +0200 Subject: [PATCH 1/3] Remove sha1 pre-hashing from password handling Previously, passwords were sha1-hashed before being passed to password_hash/password_verify (a leftover from client-side hashing in REDAXO 5.x). This removes the sha1 layer entirely: - Remove `$isPreHashed` parameter from `setLogin`, `passwordHash`, `passwordVerify` - Remove client-side sha1 hashing from login form and `sha1.js` asset - Add legacy fallback in `BackendLogin::passwordVerify` for old sha1-wrapped password hashes, with automatic rehashing on next login - Use `static::` instead of `self::` for `passwordVerify` in `Login::checkLogin` to enable late static binding Co-Authored-By: Claude Opus 4.6 (1M context) --- assets/sha1.js | 12 ---------- boot/backend.php | 5 +--- pages/login.php | 11 +-------- pages/profile/index.php | 3 ++- src/Security/BackendLogin.php | 31 +++++++++++++++++++++++- src/Security/BackendPasswordPolicy.php | 3 +-- src/Security/Login.php | 33 +++++--------------------- tests/Security/BackendLoginTest.php | 18 +++++++------- 8 files changed, 50 insertions(+), 66 deletions(-) delete mode 100644 assets/sha1.js diff --git a/assets/sha1.js b/assets/sha1.js deleted file mode 100644 index 2d90e6614b..0000000000 --- a/assets/sha1.js +++ /dev/null @@ -1,12 +0,0 @@ -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ -/* SHA-1 implementation in JavaScript | (c) Chris Veness 2002-2010 | www.movable-type.co.uk */ -/* - see http://csrc.nist.gov/groups/ST/toolkit/secure_hashing.html */ -/* http://csrc.nist.gov/groups/ST/toolkit/examples.html */ -/* http://www.movable-type.co.uk/scripts/sha1.html */ -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ -var Sha1={}; -Sha1.hash=function(b,a){if(a=typeof a=="undefined"?true:a)b=Utf8.encode(b);var g=[1518500249,1859775393,2400959708,3395469782];b+=String.fromCharCode(128);for(var c=Math.ceil((b.length/4+2)/16),h=Array(c),e=0;e>>32-a};Sha1.toHexStr=function(b){for(var a="",g,c=7;c>=0;c--){g=b>>>c*4&15;a+=g.toString(16)}return a};var Utf8={}; -Utf8.encode=function(b){b=b.replace(/[\u0080-\u07ff]/g,function(a){a=a.charCodeAt(0);return String.fromCharCode(192|a>>6,128|a&63)});return b=b.replace(/[\u0800-\uffff]/g,function(a){a=a.charCodeAt(0);return String.fromCharCode(224|a>>12,128|a>>6&63,128|a&63)})}; -Utf8.decode=function(b){b=b.replace(/[\u00e0-\u00ef][\u0080-\u00bf][\u0080-\u00bf]/g,function(a){a=(a.charCodeAt(0)&15)<<12|(a.charCodeAt(1)&63)<<6|a.charCodeAt(2)&63;return String.fromCharCode(a)});return b=b.replace(/[\u00c0-\u00df][\u0080-\u00bf]/g,function(a){a=(a.charCodeAt(0)&31)<<6|a.charCodeAt(1)&63;return String.fromCharCode(a)})}; diff --git a/boot/backend.php b/boot/backend.php index 0f5e4e78e6..cd5f7a7205 100644 --- a/boot/backend.php +++ b/boot/backend.php @@ -150,9 +150,7 @@ if (($rexUserLogin || $passkey) && !CsrfToken::factory('backend_login')->isValid()) { $loginCheck = I18n::msg('csrf_token_invalid'); } else { - // the server side encryption of pw is only required - // when not already encrypted by client using javascript - $login->setLogin($rexUserLogin, $rexUserPsw, Request::post('javascript', 'boolean')); + $login->setLogin($rexUserLogin, $rexUserPsw); $login->setPasskey('' === $passkey ? null : $passkey); $login->setStayLoggedIn($rexUserStayLoggedIn); $loginCheck = $login->checkLogin(); @@ -234,7 +232,6 @@ Asset::addJsFile(Url::coreAssets('jquery-ui.custom.min.js'), [Asset::JS_IMMUTABLE => true]); Asset::addJsFile(Url::coreAssets('jquery-pjax.min.js'), [Asset::JS_IMMUTABLE => true]); Asset::addJsFile(Url::coreAssets('standard.js'), [Asset::JS_IMMUTABLE => true]); -Asset::addJsFile(Url::coreAssets('sha1.js'), [Asset::JS_IMMUTABLE => true]); Asset::addJsFile(Url::coreAssets('clipboard-copy-element.js'), [Asset::JS_IMMUTABLE => true]); Asset::addJsFile(Url::coreAssets('js/mediapool.js'), [Asset::JS_IMMUTABLE]); diff --git a/pages/login.php b/pages/login.php index 983bce57b4..e869e1e1ea 100644 --- a/pages/login.php +++ b/pages/login.php @@ -53,7 +53,7 @@ function disableLogin() { $content .= '
- '; +'; $formElements = []; @@ -132,15 +132,6 @@ function disableLogin() {