mhash

(PHP 4, PHP 5, PHP 7, PHP 8)

mhash计算哈希

警告

从 PHP 8.1.0 开始,此函数已弃用。强烈建议不要依赖此函数。

描述

mhash(int $algo, string $data, ?string $key = null): string|false

mhash() 对由 algo 指定的哈希函数应用于 data

参数

algo

哈希 ID。其中一个 MHASH_hashname 常量。

data

用户输入,作为字符串。

key

如果指定,该函数将返回生成的 HMAC。HMAC 是用于消息身份验证的带密钥散列,或者简而言之,依赖于指定密钥的消息摘要。并非 mhash 中支持的所有算法都可以在 HMAC 模式下使用。

返回值

返回生成的哈希(也称为摘要)或 HMAC 作为字符串,或在错误时返回 false

变更日志

版本 描述
8.1.0 此函数已被弃用。请改用 hash_*() 函数
8.0.0 key 现在可以为空。

添加注释

用户贡献的注释 13 个注释

0
holdoffhunger at gmail dot com
12 年前
此处的 MHash 函数在向 mhash 函数提供密钥时列出了一个免责声明: “并非 mhash 中支持的所有算法都可以在 HMAC 模式下使用。” 那么,哪些算法会崩溃,哪些算法在进行带密钥的 HMAC 散列时效果良好? 那些破坏性的算法是:Adler32、CRC32、CRC32B 和 GOST。这些是与 MHash 应用软件包一起列出的前四个预定义常量:https://php.net/manual/en/mhash.constants.php 。 为这些算法中的一个提供 HMAC 密钥(字符串长度大于 1)会创建以下错误消息: “警告:mhash() [function.mhash]:mhash 初始化失败在 [(文件夹位置)] 第 181 行”。 如果你真的想使用这些算法来创建你的 HMAC 哈希值,HASH-Message Digest Framework 软件包中的 Hash_hmac() 函数可以完美地完成此任务。

再次强调,这是在字符串长度大于 1 的情况下。 为什么字符串长度大于 1? 好吧,如果键值为空,则它将完全被忽略为参数。 因此,如果你向 mhash 函数提供与 HMAC 散列不兼容的算法和一个空白的 HMAC 密钥(""),它的作用与它没有收到任何 HMAC 密钥一样。 这与 HASH-MDF 的 Hash_hmac() 函数的工作方式不同。 在 Hash_hmac() 函数的情况下,提供空白的 HMAC 密钥将使用该空白密钥来生成 HMAC 哈希值。 即使对于可以进行 HMAC 散列的函数,例如 MD5 或 SHA1,如果 MHash() 收到空白的 HMAC 密钥,它也会忽略该密钥,只返回标准非 HMAC 散列的结果。 可能不建议使用空白的 HMAC 密钥,但需要注意的是,如果提供的 HMAC 密钥为空,则散列算法将完全改变。

一些演示代码

<?php

// 作者:[email protected]

// 预设数据
// ---------------------------------------------------

$string_to_hash = "The hash_hmac() function better to use for these purposes.";
$blank_hmac_key = "";

// MHash - 带和不带 HMAC 参数的散列
// ---------------------------------------------------

$mhash_result_with_hmac_parameter = bin2hex(mhash(MHASH_CRC32, $string_to_hash, $blank_hmac_key));
$mhash_result_without_hmac_parameter = bin2hex(mhash(MHASH_CRC32, $string_to_hash));

// MHash - 带和不带 HMAC 参数的散列
// ---------------------------------------------------

$hash_result_with_hmac_parameter = hash_hmac("crc32", $string_to_hash, $blank_hmac_key);
$hash_result_without_hmac_parameter = hash("crc32", $string_to_hash);

// 打印结果
// ---------------------------------------------------

print("MHASH (CRC32 算法) 带空白 HMAC 密钥: $mhash_result_with_hmac_parameter .<br>");
print(
"MHASH (CRC32 算法) 不带 HMAC 处理: $mhash_result_without_hmac_parameter .<br><br>");

print(
"HASH (CRC32 算法) 带空白 HMAC 密钥: $hash_result_with_hmac_parameter .<br>");
print(
"HASH (CRC32 算法) 不带 HMAC 处理: $hash_result_without_hmac_parameter .");

?>

结果
...................................

MHASH (CRC32 算法) 带空白 HMAC 密钥: f665c094 .
MHASH (CRC32 算法) 不带 HMAC 处理: f665c094 .

HASH (CRC32 算法) 带空白 HMAC 密钥: 3041f4f8 .
HASH (CRC32 算法) 不带 HMAC 处理: f665c094 .
0
holdoffhunger at gmail dot com
12 年前
两个密码软件包,MHash 和 HASH Message Digest Framework,都具有相同的算法,然而,它们有时在对同一数据应用相同的算法时会产生截然不同的结果。 SHA-x 算法(由国家安全局设计)似乎都具有产生其哈希值的具体标准,因此它们的结果相似。 即使是两个 MD5 实现也会产生相同的结果,对于 Gost、RipeMD、CRC32、Whirlpool、Snefru256(在 MHash 中称为 'Snefru256',在 HASH-MDF 中简称为 'Snefru')和 Tiger(HASH-MDF 中的三轮版本简称为 MHash 中的 'Tigerx')也是如此。

但是,CRC32B 和 Adler32 算法在从 MHash 或 HASH-MDF 调用时会产生不同的结果,这可能是因为它们是旨在用作校验和的散列算法,而不是可以生成字符串作为特定信息片段的唯一标识符的东西。 因此,如果你在公开发布的数据中发布哈希结果,最好说明它是 MHash 还是 HASH-MDF 算法的实现。 否则,哈希值将无法作为特定数据片段或文件的唯一标识符提供太多用处。

一些更好的解释我的意思的示例代码

<?php

// 作者:[email protected]

// SHA-1 哈希
// ---------------------------------------------------

$mhash_sha1_results = bin2hex(mhash(MHASH_SHA1, "secret"));
$hash_mdf_sha1_results = hash("sha1", "secret", FALSE);

print(
"MHash SHA-1: $mhash_sha1_results .<br>");
print(
"HASH-MDF SHA-1: $hash_mdf_sha1_results .<br><br>");

// Whirlpool 哈希
// ---------------------------------------------------

$mhash_whirlpool_results = bin2hex(mhash(MHASH_WHIRLPOOL, "secret"));
$hash_mdf_whirlpool_results = hash("whirlpool", "secret", FALSE);

print(
"MHash Whirlpool: $mhash_whirlpool_results .<br>");
print(
"HASH-MDF Whirlpool: $hash_mdf_whirlpool_results .<br><br>");

// CRC32B 哈希
// ---------------------------------------------------

$mhash_crc32b_results = bin2hex(mhash(MHASH_CRC32B, "secret"));
$hash_mdf_crc32b_results = hash("crc32b", "secret", FALSE);

print(
"MHash CRC32B: $mhash_crc32b_results .<br>");
print(
"HASH-MDF CRC32B: $hash_mdf_crc32b_results .<br><br>");

// Adler32 哈希
// ---------------------------------------------------

$mhash_adler32_results = bin2hex(mhash(MHASH_ADLER32, "secret"));
$hash_mdf_adler32_results = hash("adler32", "secret", FALSE);

print(
"MHash Adler32: $mhash_adler32_results .<br>");
print(
"HASH-MDF Adler32: $hash_mdf_adler32_results .<br><br>");

?>

预期结果
........................

MHash SHA-1: e5e9fa1ba31ecd1ae84f75caaa474f3a663f05f4 .
HASH-MDF SHA-1: e5e9fa1ba31ecd1ae84f75caaa474f3a663f05f4 .

MHash Whirlpool: e061b87a674ae3880e159ab55ed35d
6c5e8a6aefac6ab08304a50588018d
377b28639bb15fdeedf006d57e45f7
b4298e6dfefceaf7c92c826a708fe6d
1156eb3 .

HASH-MDF Whirlpool: e061b87a674ae3880e159ab55ed35d
6c5e8a6aefac6ab08304a50588018d
377b28639bb15fdeedf006d57e45f7
b4298e6dfefceaf7c92c826a708fe6d
1156eb3 .

MHash CRC32B: e5e8a25c .
HASH-MDF CRC32B: 5ca2e8e5 .

MHash Adler32: 8702d108 .
HASH-MDF Adler32: 08d10287 .
0
hm2k at php dot net
15 年前
mhash 支持现在出现在 Pear PHP_Compat 包中,用于在不使用 mhash 构建 PHP 的情况下提供支持。
0
numien(at)deathwyrm(dot)com
17 年前
---引用---
pack("H*", md5($str)) == mhash(MHASH_MD5, $str)
pack("H*", sha1($str)) == mhash(MHASH_SHA1, $str)
---/引用---

这是一种非常低效的做法。你可以直接在 md5 或 sha1 后面加上 ", true" 来获取二进制输出,而不是将其转换为十六进制,然后再转换回来。

更简单的方法
md5($str, true) == mhash(MHASH_MD5, $str)
sha1($str, true) == mhash(MHASH_SHA1, $str)
0
marcel446 at yahoo dot com
19 年前
如果你没有注意到,Lance 的函数与用于获取 HMAC 的哈希函数无关,因此如果使用 php 中的 sha1() 函数而不是 md5(),则会获得 sha1 HMAC。
试试看。
再次感谢 Lance
0
robbie [at] averill [dot] co [dot] nz
19 年前
当我第一次阅读 mhash 的文档时,这让我有点困惑。接受哈希的函数将它们作为整数而不是字符串接受。在这种情况下,MHASH_MD5 = 1。它是一个常量,而不是字符串。

我只是想指出这一点,以便任何感到困惑的人都可以阅读它。这就是 mhash_get_hash_name() 的用途。你输入常量(它是一个整数),它会返回哈希名称。
0
fernan at ispwest dot com
19 年前
非常感谢 Lance 展示了如何在不安装 mhash 的 perl 扩展的情况下创建 mhash。

我一直要求我的网站托管管理员用 mhash 扩展重新编译 Perl,但我不想这样做。结果,我们公司无法获得信用卡授权,因为他们需要使用 mhash 函数的指纹。现在,它运行良好。

非常感谢,Lance.....

Fernan
0
jerry d0t wilborn at fast d0t net
20 年前
回复 Lance 的帖子

该函数返回 hmac 的十六进制表示形式,如果你想将其转换为 mhash 原生返回的值(二进制),请使用:pack("H*", hmac(变量...));
0
lance_rushing at hot* spamfree *mail dot com
21 年前
不要忘记 php 有两个内置的哈希算法

md5() 和 sha1()

因此,如果你使用:mhash(MHASH_MD5, $str) 或 mhash(MHASH_SHA1, $str),你可以使用 md5($str) 或 sha1($str)。

** 但请记住,md5() 和 sha1() 生成十六进制输出,而 mhash() 生成二进制输出。所以 **

md5($str) == bin2hex(mhash(MHASH_MD5, $str))
sha1($str) == bin2hex(mhash(MHASH_SHA1, $str))

以及

pack("H*", md5($str)) == mhash(MHASH_MD5, $str)
pack("H*", sha1($str)) == mhash(MHASH_SHA1, $str)

(只需记住使用 pack() 或 bin2hex() 来获取所需的输出)

-Lance
0
lance_rushing at hot* spamfree *mail dot com
21 年前
想创建一个 md5 HMAC,但没有安装 hmash?

使用以下代码

function hmac ($key, $data)
{
// RFC 2104 HMAC 实现,用于 php。
// 创建一个 md5 HMAC。
// 消除了计算 HMAC 时安装 mhash 的必要性
// 由 Lance Rushing 编写

$b = 64; // md5 的字节长度
if (strlen($key) > $b) {
$key = pack("H*",md5($key));
}
$key = str_pad($key, $b, chr(0x00));
$ipad = str_pad('', $b, chr(0x36));
$opad = str_pad('', $b, chr(0x5c));
$k_ipad = $key ^ $ipad ;
$k_opad = $key ^ $opad;

return md5($k_opad . pack("H*",md5($k_ipad . $data)));
}

-----
测试
在安装了 mhash 的服务器上运行以下代码

$key = 'Jefe';
$data = "what do ya want for nothing?";
echo hmac($key, $data);
echo "&lt;br&gt;\n";
echo bin2hex (mhash(MHASH_MD5, $data, $key));

应该输出

750c783e6ab0b503eaa86e310a5db738
750c783e6ab0b503eaa86e310a5db738

哈希愉快。
-1
jeremy s
10 年前
以下是如何计算 NTLM 哈希

<?php
function ntlm_hash($txt)
{
$txt = iconv('UTF-8', 'UTF-16LE', $txt);
$md4 = bin2hex(mhash(MHASH_MD4, $txt));

return
strtoupper($md4);
}

echo
ntlm_hash('ClearTextPasswd');
echo
"\n";
-1
paulj at 5emedia dot net
22 年前
许多摘要算法(尤其是 MD5)如果对小于算法输出的數據进行哈希,安全性会降低。我建议将密钥/盐与原始数据进行哈希,以提高其安全性。
-2
luc at 2113 dot ch
22 年前
Netscape 消息传递/目录服务器 4+ 使用 SHA-1
在 ldap 数据库 (slapd) 中存储密码。
密码首先进行 SHA-1 哈希,然后进行 base64 编码

$pwd = "secret";
$hash = "{SHA}".base64_encode( mHash(MHASH_SHA1, $pwd));
echo "Hash: ". $hash ;
To Top