← PHP ltrim() 函数 PHP md5_file() 函数 →

PHP md5()函数详解:计算字符串MD5哈希值及raw参数区别

著
原创 2026-10-11 PHP 已有人查阅

一、md5()的基本定位

md5()是PHP的预定义字符串函数,用于计算一个字符串的MD5哈希值。MD5全称MessageDigestAlgorithm5,属于RSADataSecurity提出的一系列摘要算法。它的作用是把任意长度的输入转换成固定长度的输出,输出通常以32位十六进制字符串呈现。

哈希函数有几个基本特征:相同输入必然得到相同输出,不同输入理论上应得到不同输出,且从输出无法反推输入。md5()遵循这些特征,但它在现在安全标准下已经不再适合承担密码保护这类职责。

语法形式:

md5(string, raw);

二、参数说明

参数 说明 是否必需
string 要计算哈希值的字符串 必需
raw 指定输出格式 可选

raw参数控制返回值的格式:

  • raw=false:默认值,返回32位十六进制字符串,例如2fec392304a5c23ac138da22847f9b7c

  • raw=true:返回16位原始二进制格式,内容不可直接阅读,适合需要紧凑存储或后续二进制处理的场景

raw参数容易被忽略。多数场景下用默认的十六进制字符串就够了,因为便于比较、存储和日志查看。只有在明确需要节省空间或与二进制协议对接时,才会用到原始格式。

三、返回值与特性

md5()返回计算后的哈希值,原字符串不受影响。它接受的是字符串输入,如果传入其他类型,PHP会按类型转换规则处理,这一点在严格模式下需要留意。

MD5的输出长度是固定的。十六进制格式固定32个字符,原始二进制格式固定16个字节。这个固定长度特性让它可以用于校验数据是否被改动,但不能用于还原原始内容。

一个需要明确的认识是:MD5属于快速哈希算法。它的设计目标是计算效率高,而不是抵抗破解。正因为它快,攻击者可以在单位时间内尝试大量输入,配合彩虹表等手段,短字符串的MD5值很容易被反查出来。

四、代码号学习编程实例

实例一:计算字符串的MD5值

<?php
$str = "PHP";
echo "原始字符串:" . $str . "<br>";
echo "MD5 哈希值:" . md5($str);

输出为2fec392304a5c23ac138da22847f9b7c。同一字符串每次运行结果一致,这是哈希函数的确定性决定的。

实例二:用MD5值做简单比对

<?php
$str = "PHP";
$expected = "2fec392304a5c23ac138da22847f9b7c";
if (md5($str) === $expected) {
    echo "字符串与预期哈希值匹配";
}

这种写法常见于校验文件是否被完整传输,或者确认某段内容与记录一致。比较时建议用===而不是==,避免类型转换带来的意外。

实例三:对比两种输出格式

<?php
$str = "PHP";
echo "十六进制格式:" . md5($str) . "<br>";
echo "原始二进制格式:" . md5($str, true) . "<br>";
echo "原始格式长度:" . strlen(md5($str, true));

原始二进制格式在浏览器中会显示为乱码,这是正常现象,因为它本身就是字节序列而非可读文本。它的长度固定为16字节,比十六进制格式短一半。

实例四:哈希不匹配的情形

<?php
$str = "PHP";
echo "实际哈希值:" . md5($str) . "<br>";
if (md5($str) === "8b1a9953c4611296a827abf8c47804d7") {
    echo "匹配成功";
} else {
    echo "哈希值不一致,条件不成立";
}

8b1a9953c4611296a827abf8c47804d7是另一个字符串的MD5值,与"PHP"不匹配,所以判断分支不会进入。这个例子说明哈希比对的结果只有两种:一致或不一致。

五、本节课程知识要点

  1. md5()返回固定长度的哈希值,默认32位十六进制,raw为true时返回16字节二进制。

  2. 相同输入得到相同输出,可用于完整性校验和内容比对。

  3. MD5是快速哈希算法,计算效率高,但抗破解能力弱。

  4. 不应将md5()用于密码存储,原因包括计算速度快、易受彩虹表攻击、无盐值时相同密码哈希相同。

  5. 比较哈希值时使用===,避免松散比较带来的类型问题。

  6. raw参数按需使用,常规场景保持默认十六进制格式即可。

六、项目经验与使用边界

为什么不建议用md5()存密码。这是关于md5()最需要说清楚的一点。密码存储的核心要求是“即使数据库泄露,攻击者也难以还原出原始密码”。MD5的计算速度太快,一块普通显卡每秒可以计算数十亿次MD5,配合预先计算好的彩虹表,常见密码几乎瞬间就能被反查。加上很多项目直接md5($password)而不加盐,相同密码在数据库里哈希值一样,一旦一个被破解,其他用户也跟着受影响。

替代方案的选择。PHP提供了password_hash()和password_verify(),它们使用bcrypt或Argon2这类专门为密码存储设计的算法,自带盐值、计算成本可调,能显著提高破解的代价。新项目应当优先使用这套接口,而不是自己用md5()加盐拼接。

md5()仍然适合的场景。它并非没有用处。文件完整性校验、缓存键生成、非安全场景下的内容指纹、去重判断等,仍然可以用md5()。这些场景关注的是“内容是否变化”,而不是“能否抵抗攻击”。在这些用途下,md5()的速度反而是优点。

一个踩坑经历。早期做文件上传去重时,用md5_file()对文件内容取哈希,把哈希值作为文件名存储。后来发现两个内容不同但MD5相同的文件理论上存在碰撞可能,虽然实际概率极低,但在需要严格区分的场景下不够稳妥。后来改用sha256并配合文件大小一起判断,才更放心。这件事的启发是:MD5碰撞在普通业务中不常见,但在设计存储键或做安全判断时,选择更强的算法成本并不高。

关于raw参数的实际体会。大多数项目从头到尾用的都是默认十六进制格式,raw参数很少被用到。如果要做二进制存储,比如把哈希值存入BINARY(16)字段,raw格式能节省一半空间,但读取和调试时不够直观。取舍时看具体需求,不要为了省空间牺牲可维护性。

md5()是一个计算字符串MD5哈希值的函数,用法直接,输出格式由raw参数控制。它的价值在于快速生成内容指纹,用于校验和比对。它的局限在于安全性不足,不能承担密码保护职责。理解这两面,才能在项目中用对地方:需要校验内容时可以用,需要保护密码时应当换用password_hash()系列函数。

← PHP ltrim()函数用法详解:移除字符串左侧空白字符与自定义字符 PHP md5_file()函数用法详解:计算文件MD5哈希与完整性校验 →
分享笔记 (共有 篇笔记)
验证码:
微信公众号