【问题标题】:PHP SHA1 gives different result than expectedPHP SHA1 给出的结果与预期不同
【发布时间】:2011-08-24 22:22:37
【问题描述】:

这真的让我吃惊——这应该很简单,但我不知道有什么区别。

我有这个函数来生成盐:

private function _generateSalt($max = 128)
{
    $characterList = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#¤%&/()~";
    $i = 0;
    $salt = "";
    do {
        $salt .= $characterList{mt_rand(0,strlen($characterList)-1)};
         $i++;
    } while ($i < $max);
    return $salt;
}

非常基本(?)

并尝试从中创建一个 SHA1 哈希,这给了我一个不同的结果:

$salt = $this->_generateSalt();
$password = $salt.$password;
echo sha1($password);

$password 是用户输入生成的字符串。 回显的散列字符串是错误的。我不知道为什么。

var_dump($password); 在添加盐之后给了我预期的字符串大小 - 将结果复制并粘贴到在线 SHA1 服务或通过 MySQL CLI 对字符串进行散列给出正确的结果。就像我不想散列的 $password 变量中有一些不可见的东西。但是我怎样才能找出为什么会这样呢? var_dump()、trim() 和比较结果没有得到任何帮助?

【问题讨论】:

  • 在将它们连接在一起之前转储密码和盐并粘贴结果(对于一次调用,当然每次盐都是不同的,您应该将其与密码一起保存在某处)。对于给定的 EXACT 字符串,您收到的 sha1 字符串是什么?您希望收到什么?
  • 我最好的猜测是有一个你在某处看不到的字符(例如:空格)
  • 我问的是 php 版本,因为如果你下载了最新版本的 php (5.3.7),它在没有单元测试的情况下被愚蠢地发布,并且包含一个严重的加密错误,实际上禁用了加密功能 - developers.slashdot.org/story/11/08/22/2332217/…
  • @Veseliq:我发现问题实际上来自盐。生成、回显并复制粘贴到 sha1 函数的字符串给出了与脚本中回显的 sha1 字符串不同的结果。但是谁能确定我的盐发生器出了什么问题?
  • 再次,告诉你的盐。并了解每次盐分都不一样。如果您将盐复制并粘贴到在线 SHA1 哈希生成器,然后再次运行脚本 - 由于新的盐,它将给出新的结果。还要去掉所有非字母数字的特殊字符——据我所知,这个字符甚至不是 ASCII:¤。因此,如果您在以不同编码编码的字符串下运行 sha1,它可能会搞砸。

标签: php sha1


【解决方案1】:

去掉所有非字母数字的特殊字符——据我所知,这个字符甚至不是 ASCII:¤。因此,如果您在以不同编码编码的字符串下运行 sha1,可能会搞砸。

(此答案是从 cmets 复制粘贴并添加为答案,因为提问者的要求似乎可以解决问题)

【讨论】:

    【解决方案2】:

    生成盐的更好方法是:

    // True for cryptographically strong, FALSE otherwise
    $salt_strong = TRUE;
    
    // The length
    $salt_length = 32;
    
    // Create the salt and load the results into a local var
    $salt = bin2hex( openssl_random_pseudo_bytes( $salt_length , $salt_strong ) );
    

    【讨论】:

    • 问题是“为什么这不起作用”,而不是“我怎样才能做得更好”。
    • 我不认为让弱代码工作对任何人都有好处。他在密码散列过程中使用 mt_rand() ,这是一个巨大的禁忌。任何值得他“盐”的 php 开发人员都知道,mt_rand() 使用的 Mersenne Twister 很弱,不应用于任何可能需要抵御密码攻击的事情。因此,我为他提供了一个更简单的解决方案,需要更少的代码,更不容易出错,加密安全并且......会工作。
    • 这不能回答问题。另外,这需要安装openssl,这会带来兼容性问题。
    【解决方案3】:

    这行不应该: $salt .= $characterList{mt_rand(0,strlen($characterList)-1)};

    看起来像这样:$salt .= $characterList[mt_rand(0,strlen($characterList)-1)];

    【讨论】:

    • 不,您可以通过 {} 和 [] 访问字符串中的单个字符。
    • 谢谢。我没有意识到这一点。
    猜你喜欢
    • 2021-04-11
    • 2021-06-06
    • 2019-03-17
    • 2012-10-12
    • 1970-01-01
    • 2020-12-10
    • 2017-06-15
    • 1970-01-01
    • 2011-11-28
    相关资源
    最近更新 更多