diff --git a/resources/sql/patches/20130530.sessionhash.php b/resources/sql/patches/20130530.sessionhash.php --- a/resources/sql/patches/20130530.sessionhash.php +++ b/resources/sql/patches/20130530.sessionhash.php @@ -14,7 +14,7 @@ $conn, 'UPDATE %T SET sessionKey = %s WHERE userPHID = %s AND type = %s', PhabricatorUser::SESSION_TABLE, - PhabricatorHash::digest($session['sessionKey']), + PhabricatorHash::weakDigest($session['sessionKey']), $session['userPHID'], $session['type']); } diff --git a/src/applications/auth/controller/PhabricatorAuthController.php b/src/applications/auth/controller/PhabricatorAuthController.php --- a/src/applications/auth/controller/PhabricatorAuthController.php +++ b/src/applications/auth/controller/PhabricatorAuthController.php @@ -194,7 +194,7 @@ // hijacking registration sessions. $actual = $account->getProperty('registrationKey'); - $expect = PhabricatorHash::digest($registration_key); + $expect = PhabricatorHash::weakDigest($registration_key); if (!phutil_hashes_are_identical($actual, $expect)) { $response = $this->renderError( pht( diff --git a/src/applications/auth/controller/PhabricatorAuthLoginController.php b/src/applications/auth/controller/PhabricatorAuthLoginController.php --- a/src/applications/auth/controller/PhabricatorAuthLoginController.php +++ b/src/applications/auth/controller/PhabricatorAuthLoginController.php @@ -194,7 +194,7 @@ $registration_key = Filesystem::readRandomCharacters(32); $account->setProperty( 'registrationKey', - PhabricatorHash::digest($registration_key)); + PhabricatorHash::weakDigest($registration_key)); $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites(); $account->save(); diff --git a/src/applications/auth/controller/PhabricatorAuthOneTimeLoginController.php b/src/applications/auth/controller/PhabricatorAuthOneTimeLoginController.php --- a/src/applications/auth/controller/PhabricatorAuthOneTimeLoginController.php +++ b/src/applications/auth/controller/PhabricatorAuthOneTimeLoginController.php @@ -135,7 +135,7 @@ ->setTokenResource($target_user->getPHID()) ->setTokenType($password_type) ->setTokenExpires(time() + phutil_units('1 hour in seconds')) - ->setTokenCode(PhabricatorHash::digest($key)) + ->setTokenCode(PhabricatorHash::weakDigest($key)) ->save(); unset($unguarded); diff --git a/src/applications/auth/controller/PhabricatorAuthTerminateSessionController.php b/src/applications/auth/controller/PhabricatorAuthTerminateSessionController.php --- a/src/applications/auth/controller/PhabricatorAuthTerminateSessionController.php +++ b/src/applications/auth/controller/PhabricatorAuthTerminateSessionController.php @@ -16,7 +16,7 @@ $query->withIDs(array($id)); } - $current_key = PhabricatorHash::digest( + $current_key = PhabricatorHash::weakDigest( $request->getCookie(PhabricatorCookies::COOKIE_SESSION)); $sessions = $query->execute(); diff --git a/src/applications/auth/engine/PhabricatorAuthSessionEngine.php b/src/applications/auth/engine/PhabricatorAuthSessionEngine.php --- a/src/applications/auth/engine/PhabricatorAuthSessionEngine.php +++ b/src/applications/auth/engine/PhabricatorAuthSessionEngine.php @@ -110,7 +110,7 @@ $session_table = new PhabricatorAuthSession(); $user_table = new PhabricatorUser(); $conn_r = $session_table->establishConnection('r'); - $session_key = PhabricatorHash::digest($session_token); + $session_key = PhabricatorHash::weakDigest($session_token); $cache_parts = $this->getUserCacheQueryParts($conn_r); list($cache_selects, $cache_joins, $cache_map, $types_map) = $cache_parts; @@ -240,7 +240,7 @@ // This has a side effect of validating the session type. $session_ttl = PhabricatorAuthSession::getSessionTypeTTL($session_type); - $digest_key = PhabricatorHash::digest($session_key); + $digest_key = PhabricatorHash::weakDigest($session_key); // Logging-in users don't have CSRF stuff yet, so we have to unguard this // write. @@ -306,7 +306,7 @@ ->execute(); if ($except_session !== null) { - $except_session = PhabricatorHash::digest($except_session); + $except_session = PhabricatorHash::weakDigest($except_session); } foreach ($sessions as $key => $session) { @@ -755,7 +755,7 @@ $parts[] = $email->getVerificationCode(); } - return PhabricatorHash::digest(implode(':', $parts)); + return PhabricatorHash::weakDigest(implode(':', $parts)); } diff --git a/src/applications/auth/factor/PhabricatorTOTPAuthFactor.php b/src/applications/auth/factor/PhabricatorTOTPAuthFactor.php --- a/src/applications/auth/factor/PhabricatorTOTPAuthFactor.php +++ b/src/applications/auth/factor/PhabricatorTOTPAuthFactor.php @@ -39,7 +39,7 @@ ->withTokenResources(array($user->getPHID())) ->withTokenTypes(array($totp_token_type)) ->withExpired(false) - ->withTokenCodes(array(PhabricatorHash::digest($key))) + ->withTokenCodes(array(PhabricatorHash::weakDigest($key))) ->executeOne(); if (!$temporary_token) { // If we don't have a matching token, regenerate the key below. @@ -58,7 +58,7 @@ ->setTokenResource($user->getPHID()) ->setTokenType($totp_token_type) ->setTokenExpires(time() + phutil_units('1 hour in seconds')) - ->setTokenCode(PhabricatorHash::digest($key)) + ->setTokenCode(PhabricatorHash::weakDigest($key)) ->save(); unset($unguarded); } diff --git a/src/applications/auth/provider/PhabricatorAuthProvider.php b/src/applications/auth/provider/PhabricatorAuthProvider.php --- a/src/applications/auth/provider/PhabricatorAuthProvider.php +++ b/src/applications/auth/provider/PhabricatorAuthProvider.php @@ -474,7 +474,7 @@ true); } - return PhabricatorHash::digest($phcid); + return PhabricatorHash::weakDigest($phcid); } protected function verifyAuthCSRFCode(AphrontRequest $request, $actual) { diff --git a/src/applications/auth/query/PhabricatorAuthSessionQuery.php b/src/applications/auth/query/PhabricatorAuthSessionQuery.php --- a/src/applications/auth/query/PhabricatorAuthSessionQuery.php +++ b/src/applications/auth/query/PhabricatorAuthSessionQuery.php @@ -85,7 +85,7 @@ if ($this->sessionKeys) { $hashes = array(); foreach ($this->sessionKeys as $session_key) { - $hashes[] = PhabricatorHash::digest($session_key); + $hashes[] = PhabricatorHash::weakDigest($session_key); } $where[] = qsprintf( $conn_r, diff --git a/src/applications/base/controller/PhabricatorController.php b/src/applications/base/controller/PhabricatorController.php --- a/src/applications/base/controller/PhabricatorController.php +++ b/src/applications/base/controller/PhabricatorController.php @@ -98,7 +98,7 @@ if (!$user->isLoggedIn()) { - $user->attachAlternateCSRFString(PhabricatorHash::digest($phsid)); + $user->attachAlternateCSRFString(PhabricatorHash::weakDigest($phsid)); } $request->setUser($user); diff --git a/src/applications/celerity/resources/CelerityResources.php b/src/applications/celerity/resources/CelerityResources.php --- a/src/applications/celerity/resources/CelerityResources.php +++ b/src/applications/celerity/resources/CelerityResources.php @@ -14,7 +14,7 @@ public function getCelerityHash($data) { $tail = PhabricatorEnv::getEnvConfig('celerity.resource-hash'); - $hash = PhabricatorHash::digest($data, $tail); + $hash = PhabricatorHash::weakDigest($data, $tail); return substr($hash, 0, 8); } diff --git a/src/applications/config/check/PhabricatorPathSetupCheck.php b/src/applications/config/check/PhabricatorPathSetupCheck.php --- a/src/applications/config/check/PhabricatorPathSetupCheck.php +++ b/src/applications/config/check/PhabricatorPathSetupCheck.php @@ -107,7 +107,7 @@ if ($bad_paths) { foreach ($bad_paths as $path_part => $message) { - $digest = substr(PhabricatorHash::digest($path_part), 0, 8); + $digest = substr(PhabricatorHash::weakDigest($path_part), 0, 8); $this ->newIssue('config.PATH.'.$digest) diff --git a/src/applications/diffusion/controller/DiffusionServeController.php b/src/applications/diffusion/controller/DiffusionServeController.php --- a/src/applications/diffusion/controller/DiffusionServeController.php +++ b/src/applications/diffusion/controller/DiffusionServeController.php @@ -652,7 +652,7 @@ } $lfs_pass = $password->openEnvelope(); - $lfs_hash = PhabricatorHash::digest($lfs_pass); + $lfs_hash = PhabricatorHash::weakDigest($lfs_pass); $token = id(new PhabricatorAuthTemporaryTokenQuery()) ->setViewer(PhabricatorUser::getOmnipotentUser()) diff --git a/src/applications/diffusion/gitlfs/DiffusionGitLFSTemporaryTokenType.php b/src/applications/diffusion/gitlfs/DiffusionGitLFSTemporaryTokenType.php --- a/src/applications/diffusion/gitlfs/DiffusionGitLFSTemporaryTokenType.php +++ b/src/applications/diffusion/gitlfs/DiffusionGitLFSTemporaryTokenType.php @@ -22,7 +22,7 @@ $lfs_user = self::HTTP_USERNAME; $lfs_pass = Filesystem::readRandomCharacters(32); - $lfs_hash = PhabricatorHash::digest($lfs_pass); + $lfs_hash = PhabricatorHash::weakDigest($lfs_pass); $ttl = PhabricatorTime::getNow() + phutil_units('1 day in seconds'); diff --git a/src/applications/files/engine/PhabricatorChunkedFileStorageEngine.php b/src/applications/files/engine/PhabricatorChunkedFileStorageEngine.php --- a/src/applications/files/engine/PhabricatorChunkedFileStorageEngine.php +++ b/src/applications/files/engine/PhabricatorChunkedFileStorageEngine.php @@ -102,7 +102,7 @@ } public static function getChunkedHashForInput($input) { - $rehash = PhabricatorHash::digest($input); + $rehash = PhabricatorHash::weakDigest($input); // Add a suffix to identify this as a chunk hash. $rehash = substr($rehash, 0, -2).'-C'; diff --git a/src/applications/metamta/receiver/PhabricatorObjectMailReceiver.php b/src/applications/metamta/receiver/PhabricatorObjectMailReceiver.php --- a/src/applications/metamta/receiver/PhabricatorObjectMailReceiver.php +++ b/src/applications/metamta/receiver/PhabricatorObjectMailReceiver.php @@ -201,7 +201,7 @@ public static function computeMailHash($mail_key, $phid) { $global_mail_key = PhabricatorEnv::getEnvConfig('phabricator.mail-key'); - $hash = PhabricatorHash::digest($mail_key.$global_mail_key.$phid); + $hash = PhabricatorHash::weakDigest($mail_key.$global_mail_key.$phid); return substr($hash, 0, 16); } diff --git a/src/applications/people/storage/PhabricatorUser.php b/src/applications/people/storage/PhabricatorUser.php --- a/src/applications/people/storage/PhabricatorUser.php +++ b/src/applications/people/storage/PhabricatorUser.php @@ -389,7 +389,7 @@ // Generate a token hash to mitigate BREACH attacks against SSL. See // discussion in T3684. $token = $this->getRawCSRFToken(); - $hash = PhabricatorHash::digest($token, $salt); + $hash = PhabricatorHash::weakDigest($token, $salt); return self::CSRF_BREACH_PREFIX.$salt.substr( $hash, 0, self::CSRF_TOKEN_LENGTH); } @@ -435,7 +435,7 @@ for ($ii = -$csrf_window; $ii <= 1; $ii++) { $valid = $this->getRawCSRFToken($ii); - $digest = PhabricatorHash::digest($valid, $salt); + $digest = PhabricatorHash::weakDigest($valid, $salt); $digest = substr($digest, 0, self::CSRF_TOKEN_LENGTH); if (phutil_hashes_are_identical($digest, $token)) { return true; @@ -459,7 +459,7 @@ $time_block = floor($epoch / $frequency); $vec = $vec.$key.$time_block; - return substr(PhabricatorHash::digest($vec), 0, $len); + return substr(PhabricatorHash::weakDigest($vec), 0, $len); } public function getUserProfile() { diff --git a/src/applications/settings/panel/PhabricatorPasswordSettingsPanel.php b/src/applications/settings/panel/PhabricatorPasswordSettingsPanel.php --- a/src/applications/settings/panel/PhabricatorPasswordSettingsPanel.php +++ b/src/applications/settings/panel/PhabricatorPasswordSettingsPanel.php @@ -48,7 +48,7 @@ ->setViewer($user) ->withTokenResources(array($user->getPHID())) ->withTokenTypes(array($password_type)) - ->withTokenCodes(array(PhabricatorHash::digest($key))) + ->withTokenCodes(array(PhabricatorHash::weakDigest($key))) ->withExpired(false) ->executeOne(); } diff --git a/src/applications/settings/panel/PhabricatorSessionsSettingsPanel.php b/src/applications/settings/panel/PhabricatorSessionsSettingsPanel.php --- a/src/applications/settings/panel/PhabricatorSessionsSettingsPanel.php +++ b/src/applications/settings/panel/PhabricatorSessionsSettingsPanel.php @@ -44,7 +44,7 @@ ->withPHIDs($identity_phids) ->execute(); - $current_key = PhabricatorHash::digest( + $current_key = PhabricatorHash::weakDigest( $request->getCookie(PhabricatorCookies::COOKIE_SESSION)); $rows = array(); diff --git a/src/infrastructure/util/PhabricatorHash.php b/src/infrastructure/util/PhabricatorHash.php --- a/src/infrastructure/util/PhabricatorHash.php +++ b/src/infrastructure/util/PhabricatorHash.php @@ -5,12 +5,15 @@ const INDEX_DIGEST_LENGTH = 12; /** - * Digest a string for general use, including use which relates to security. + * Digest a string using HMAC+SHA1. + * + * Because a SHA1 collision is now known, this method should be considered + * weak. Callers should prefer @{method:digestWithNamedKey}. * * @param string Input string. * @return string 32-byte hexidecimal SHA1+HMAC hash. */ - public static function digest($string, $key = null) { + public static function weakDigest($string, $key = null) { if ($key === null) { $key = PhabricatorEnv::getEnvConfig('security.hmac-key'); } @@ -37,7 +40,7 @@ } for ($ii = 0; $ii < 1000; $ii++) { - $result = self::digest($result, $salt); + $result = self::weakDigest($result, $salt); } return $result;