php MySQL哈希函数实现

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/260236/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 22:06:26  来源:igfitidea点击:

MySQL Hashing Function Implementation

phpmysqlhashpasswords

提问by CMS

I know that php has md5(), sha1(), and the hash() functions, but I want to create a hash using the MySQL PASSWORD() function. So far, the only way I can think of is to just query the server, but I want a function (preferably in php or Perl) that will do the same thing without querying MySQL at all.

我知道 php 有 md5()、sha1() 和 hash() 函数,但我想使用 MySQL PASSWORD() 函数创建一个哈希。到目前为止,我能想到的唯一方法是只查询服务器,但我想要一个函数(最好在 php 或 Perl 中),它可以在不查询 MySQL 的情况下做同样的事情。

For example:

例如:

MySQL hash -> 464bb2cb3cf18b66

MySQL 哈希 -> 464bb2cb3cf18b66

MySQL5 hash -> *01D01F5CA7CA8BA771E03F4AC55EC73C11EFA229

MySQL5 哈希 -> *01D01F5CA7CA8BA771E03F4AC55EC73C11EFA229

Thanks!

谢谢!

回答by defines

I originally stumbled across this question in my own search for a PHP implementation of the two MySQL password hashing functions. I was unable to find any implementations, so I adapted my own from the MySQL source code (sql/password.c). The following are tested and working in PHP 5.2:

我最初在自己搜索两个 MySQL 密码散列函数的 PHP 实现时偶然发现了这个问题。我找不到任何实现,所以我从 MySQL 源代码 (sql/password.c) 中调整了自己的实现。以下内容已在 PHP 5.2 中测试和运行:

// The following is free for any use provided credit is given where due.
// This code comes with NO WARRANTY of any kind, including any implied warranty.

/**
 * MySQL "OLD_PASSWORD()" AKA MySQL323 HASH FUNCTION
 * This is the password hashing function used in MySQL prior to version 4.1.1
 * By Defines Fineout 10/9/2009 9:12:16 AM
**/
function mysql_old_password_hash($input, $hex = true)
{
  $nr = 1345345333; $add = 7; $nr2 = 0x12345671; $tmp = null;
  $inlen = strlen($input);
  for ($i = 0; $i < $inlen; $i++) {
    $byte = substr($input, $i, 1);
    if ($byte == ' ' || $byte == "\t") continue;
    $tmp = ord($byte);
    $nr ^= ((($nr & 63) + $add) * $tmp) + (($nr << 8) & 0xFFFFFFFF);
    $nr2 += (($nr2 << 8) & 0xFFFFFFFF) ^ $nr;
    $add += $tmp;
  }
  $out_a = $nr & ((1 << 31) - 1);
  $out_b = $nr2 & ((1 << 31) - 1);
  $output = sprintf("%08x%08x", $out_a, $out_b);
  if ($hex) return $output;
  return hex_hash_to_bin($output);
} //END function mysql_old_password_hash

/**
 * MySQL "PASSWORD()" AKA MySQLSHA1 HASH FUNCTION
 * This is the password hashing function used in MySQL since version 4.1.1
 * By Defines Fineout 10/9/2009 9:36:20 AM
**/
function mysql_password_hash($input, $hex = true)
{
  $sha1_stage1 = sha1($input, true);
  $output = sha1($sha1_stage1, !$hex);
  return $output;
} //END function mysql_password_hash

/**
 * Computes each hexidecimal pair into the corresponding binary octet.
 * Similar to mysql hex2octet function.
**/
function hex_hash_to_bin($hex)
{
  $bin = "";
  $len = strlen($hex);
  for ($i = 0; $i < $len; $i += 2) {
    $byte_hex = substr($hex, $i, 2);
    $byte_dec = hexdec($byte_hex);
    $byte_char = chr($byte_dec);
    $bin .= $byte_char;
  }
  return $bin;
} //END function hex_hash_to_bin

Hopefully someone else will find this useful as well :)

希望其他人也会发现这很有用:)

回答by CMS

If you are interested in the algorithm of this function, download the source code and see the file sql/password.c, or check thisimplementation.

如果您对该函数的算法感兴趣,请下载源代码并查看文件 sql/password.c,或查看实现。

回答by K-Gun

Yes, too late but I just came up this implementation on that page: http://dev.mysql.com/doc/refman/5.1/en/password-hashing.html

是的,太晚了,但我只是在该页面上提出了这个实现:http: //dev.mysql.com/doc/refman/5.1/en/password-hashing.html

Here is the equivalent php function to mysql password;

这里是mysql密码的等价php函数;

function mysql_41_password($in) {
    $p = sha1($in, true);
    $p = sha1($p);
    return '*'. strtoupper($p);
} 

回答by Davide Gualano

Why do you want to use mysql password() function? Even the Mysql documentation advises against this:

为什么要使用mysql的password()函数?甚至 Mysql 文档也建议不要这样做:

http://dev.mysql.com/doc/refman/5.0/en/encryption-functions.html#function_password

http://dev.mysql.com/doc/refman/5.0/en/encryption-functions.html#function_password

The PASSWORD() function is used by the authentication system in MySQL Server; you should not use it in your own applications

PASSWORD() 函数由 MySQL Server 中的身份验证系统使用;你不应该在你自己的应用程序中使用它

You can use md5() for example, wich is present in almost every programming language, php and perl included.

例如,您可以使用 md5(),它几乎存在于所有编程语言中,包括 php 和 perl。

回答by TFBW

Based on the PHP implementation above, here's a Perl example that works.

基于上面的 PHP 实现,这里有一个有效的 Perl 示例。

use Digest::SHA1 qw(sha1 sha1_hex);
sub password { "*".uc(sha1_hex(sha1($_[0]))) }

The password function returns the same as the MySQL5 PASSWORD() function.

密码函数返回与 MySQL5 PASSWORD() 函数相同。

In answer to "why would anyone want to do this?", I use it to generate SQL "CREATE USER" statements that don't contain plain-text passwords.

为了回答“为什么有人想要这样做?”,我使用它来生成不包含纯文本密码的 SQL“CREATE USER”语句。

回答by TFBW

Bad boys do that in bash with sha1sum ;)

坏男孩用 sha1sum 在 bash 中做到这一点;)

PHRASE="password"; P1=`echo -n "${PHRASE}"|sha1sum`; P2="*`echo -en $(echo -n ${P1%% *}|sed -E 's/([0-9a-f]{2})/\\x/g')|sha1sum -b`"; PASS="${P2%% *}"; echo "${PASS^^}"

OT, but anyway... :)

OT,但无论如何... :)

回答by Matthew Lenz

Perl 5 implementation of old_password() based on the PHP example.

基于 PHP 示例的 old_password() 的 Perl 5 实现。

sub old_hash_password {
    my ($password) = @_;

    my $nr = 1345345333;
    my $nr2 = 0x12345671;
    my $add = 7;

    for (my $i = 0; $i < length($password); $i++) {
        my $byte = substr($password, $i, 1);

        next if ($byte eq ' ' || $byte eq "\t");

        my $ord_b = ord($byte);
        $nr ^= ((($nr & 63) + $add) * $ord_b) + (($nr << 8) & 0xFFFFFFFF);
        $nr2 += (($nr2 << 8) & 0xFFFFFFFF) ^ $nr;
        $add += $ord_b;
    }

    my $out_a = $nr & ((1 << 31) - 1);
    my $out_b = $nr2 & ((1 << 31) - 1);

    return sprintf("%08x%08x", $out_a, $out_b);
}