4

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

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

有类似的等价物OLD_PASSWORD()吗?

4

3 回答 3

8

我尝试直接在 SQL 中为 OLD_PASSWORD 编写替换用户定义的函数,它似乎正在工作。该代码是本文中的 PHP 版本的翻译。

DROP FUNCTION IF EXISTS OLD_PASSWORD;
DELIMITER $$
CREATE FUNCTION OLD_PASSWORD (input BLOB) 
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;

  IF (input = '' OR input IS NULL) THEN
    RETURN input;
  END IF;

  
  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(LPAD(HEX(nr),8,'0'), LPAD(HEX(nr2),8,'0'))); 
        
  RETURN output;
END$$
DELIMITER ;

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

于 2018-10-24T17:00:12.367 回答
7

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

如果像我们上面的例子一样,你没有超级用户(Google CloudSQL 不支持它们),那么就需要一个替换算法。以下是不同语言的替换:

C | 珀尔| PHP | 蟒蛇| SQL

免责声明:MySQL 的旧密码功能在现代安全中是个笑话,如果可能的话,不应使用;这些算法一团糟。

于 2016-10-02T16:47:34.817 回答
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'))); 
于 2019-08-21T12:18:06.827 回答