OLD_PASSWORD函数在5.7.5+中

时间:2016-06-02 15:43:11

标签: mysql mysql-5.7

我正在使用遗留代码库,目前使用OLD_PASSWORD()作为简单的散列函数。此代码库现在需要连接到运行MySQL 5.7最新版本的数据库。

相当于PASSWORD()似乎是:UPPER(SHA1(UNHEX(SHA1(password))))

是否有与OLD_PASSWORD()类似的等效内容?

3 个答案:

答案 0 :(得分:5)

除非服务器允许设置全局变量,否则似乎没有使用MySQL函数的OLD_PASSWORD()。通过执行查询SET @@global.old_passwords = 1;,作为具有超级权限的用户,PASSWORD()函数会使用OLD_PASSWORD()算法对密码进行哈希处理。

如果像上面的情况一样,您没有超级用户(Google CloudSQL不支持它们),则需要替换算法。以下是不同语言的替代品:

C | Perl | PHP | Python | SQL

免责声明:MySQL在现代安全中的密码功能are a joke,如果可能的话,应该。此外,在查看上述算法后,我对任何head asploding概不负责!

答案 1 :(得分:1)

我试图直接在SQL中为OLD_PASSWORD写一个替换用户定义的函数,看来它正在工作。该代码是本文中PHP版本的翻译。

DROP FUNCTION IF EXISTS OLD_PASSWORD;
DELIMITER $$
CREATE FUNCTION OLD_PASSWORD (input CHAR(250)) 
RETURNS CHAR(16)
DETERMINISTIC
BEGIN 
  DECLARE nr BIGINT;
  DECLARE nr2 BIGINT;
  DECLARE ad BIGINT;
  DECLARE inlen INT;
  DECLARE i INT;
  DECLARE b CHAR;
  DECLARE tmp INT;
  DECLARE output CHAR(16);

  SET nr = 1345345333;
  SET nr2 = 0x12345671;
  SET ad = 7;
  SET inlen = LENGTH(input);
  SET i = 1;

  WHILE i <= inlen DO
    SET b = MID(input, i, 1);
    IF b != ' ' AND b != '\t' THEN
      SET tmp = ORD(b);
      SET nr = nr ^ ((((nr & 63) + ad) * tmp) + ((nr << 8) & 0xFFFFFFFF));
      SET nr2 = nr2 + (((nr2 << 8) & 0xFFFFFFFF) ^ nr);
      SET ad = ad + tmp;
    END IF;
    SET i = i + 1;
  END WHILE;

  SET nr  = nr  & ((1 << 31) - 1);
  SET nr2 = nr2 & ((1 << 31) - 1);      
  SET output = LOWER(CONCAT(HEX(nr), HEX(nr2)));

  RETURN output;
END$$
DELIMITER ;

希望这会有所帮助。但是请注意:将这种格式的密码保存起来并不安全。

答案 2 :(得分:1)

max的答案很好,除了有时会失败。

例如,当输入字符串为“ my”时,返回值是长度为15而不是16的字符串。这是因为返回值的初始字符为0。只需尝试

select old_password('my'); 

确认这一点。

补救措施是将lpad()函数应用于hex(nr)和hex(nr2)-下一行

SET output = LOWER(CONCAT(HEX(nr), HEX(nr2)));

应更改为

SET output = LOWER(CONCAT(LPAD(HEX(nr),8,'0'), LPAD(HEX(nr2),8,'0')));