/**
  * Hash a one-time login key for storage as a temporary token.
  *
  * @param PhabricatorUser User this key is for.
  * @param PhabricatorUserEmail Optionally, email to verify when
  *  link is used.
  * @param string The one time login key.
  * @return string Hash of the key.
  * task onetime
  */
 private function getOneTimeLoginKeyHash(PhabricatorUser $user, PhabricatorUserEmail $email = null, $key = null)
 {
     $parts = array($key, $user->getAccountSecret());
     if ($email) {
         $parts[] = $email->getVerificationCode();
     }
     return PhabricatorHash::digest(implode(':', $parts));
 }
 /**
  * Compute a chunked file hash for the viewer.
  *
  * We can not currently compute a real hash for chunked file uploads (because
  * no process sees all of the file data).
  *
  * We also can not trust the hash that the user claims to have computed. If
  * we trust the user, they can upload some `evil.exe` and claim it has the
  * same file hash as `good.exe`. When another user later uploads the real
  * `good.exe`, we'll just create a reference to the existing `evil.exe`. Users
  * who download `good.exe` will then receive `evil.exe`.
  *
  * Instead, we rehash the user's claimed hash with account secrets. This
  * allows users to resume file uploads, but not collide with other users.
  *
  * Ideally, we'd like to be able to verify hashes, but this is complicated
  * and time consuming and gives us a fairly small benefit.
  *
  * @param PhabricatorUser Viewing user.
  * @param string Claimed file hash.
  * @return string Rehashed file hash.
  */
 public static function getChunkedHash(PhabricatorUser $viewer, $hash)
 {
     if (!$viewer->getPHID()) {
         throw new Exception(pht('Unable to compute chunked hash without real viewer!'));
     }
     $input = $viewer->getAccountSecret() . ':' . $hash . ':' . $viewer->getPHID();
     return self::getChunkedHashForInput($input);
 }