【问题标题】:MySQL SHA1 hash does not matchMySQL SHA1 哈希不匹配
【发布时间】:2013-11-15 21:34:32
【问题描述】:

我对 MySQL 用户表有一个奇怪的问题。我很快创建了一个简化版本作为测试用例。

我有下表

CREATE TABLE IF NOT EXISTS `users` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `identity` varchar(255) NOT NULL,
  `credential` varchar(255) NOT NULL,
  `credentialSalt` varchar(255) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=ucs2 AUTO_INCREMENT=2 ;

INSERT INTO `users` (`id`, `identity`, `credential`, `credentialSalt`) VALUES
(1, 'test', '7288edd0fc3ffcbe93a0cf06e3568e28521687bc', '123');

然后我运行以下查询

SELECT id,
       IF (credential = SHA1(CONCAT('test', credentialSalt)), 1, 0) AS dynamicSaltMatches,
       credentialSalt AS dynamicSalt,
       SHA1(CONCAT('test', credentialSalt)) AS dynamicSaltHash,
       IF (credential = SHA1(CONCAT('test', 123)), 1, 0) AS staticSaltMatches,
       123 AS staticSalt,
       SHA1(CONCAT('test', 123)) AS staticSaltHash
FROM   users
WHERE  identity = 'test'

这给了我以下结果

动态盐不匹配,而静态盐确实匹配。

这让我大吃一惊。有人可以帮我指出造成这种情况的原因吗?

我的 MySQL 版本是 5.5.29

【问题讨论】:

    标签: mysql passwords sha


    【解决方案1】:

    这是因为您的表格的默认字符集。您似乎在 UTF8 数据库上运行此程序,而 SHA1() 中的某些内容在使用不同字符集时存在问题。

    如果您将表声明更改为以下内容,它将再次匹配:

    CREATE TABLE IF NOT EXISTS `users` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `identity` varchar(255) NOT NULL,
      `credential` varchar(255) NOT NULL,
      `credentialSalt` varchar(255) NOT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=2 ;
    

    SQL Fiddle

    由于robertklep commented 将字符串显式转换为字符也可以,基本上确保在使用SHA1() 进行比较时使用相同的字符集

    作为the encryption functions documentation says:

    许多加密和压缩函数返回结果可能包含任意字节值的字符串。如果要存储这些结果,请使用具有 VARBINARY 或 BLOB 二进制字符串数据类型的列。这将避免尾随空格删除或字符集转换可能会更改数据值的潜在问题,例如,如果您使用非二进制字符串数据类型(CHAR、VARCHAR、TEXT)可能会发生这种情况。

    这是changed in version 5.5.3:

    从 MySQL 5.5.3 开始,返回值是连接字符集中的非二进制字符串。 5.5.3之前,返回值为二进制字符串;请参阅本节开头关于将值用作非二进制字符串的注释。

    【讨论】:

    • 显式转换似乎也可以解决问题:SHA1(CONCAT('test', CAST(credentialSalt AS CHAR)))
    • 是的,谢谢@robertklep;如果你不介意,我已经半偷了你的评论。
    • 非常感谢您快速而有帮助的回答。在测试用例中,这解决了问题! (正如你所指出的,我不小心使用了错误的字符集)但是,原始表是 UTF8,列是 UTF8,连接是 UTF8,问题仍然存在。 CAST(... AS CHAR) 确实 也解决了原始表上的问题。你知道还有什么原因吗?
    • SHOW VARIABLES LIKE 'character_set%'; 向你展示了@Maurice 什么?
    • 它向我显示了以下内容:http://imgur.com/ycKUg5R 我猜这不是它应该显示的 xD
    猜你喜欢
    • 2014-02-26
    • 1970-01-01
    • 2010-10-11
    • 2014-10-01
    • 2021-04-23
    • 2011-09-12
    • 1970-01-01
    • 1970-01-01
    • 2010-10-11
    相关资源
    最近更新 更多