使用 PHP 构建 MD5 彩虹表生成器的完整过程
在信息安全领域,**彩虹表(Rainbow Table)**是一种通过预计算哈希值和对应原始值的方式来破解密码的工具。为了实现一个简单高效的 MD5 彩虹表生成器,我使用了 PHP 和 MySQL,本文将详细介绍整个实现过程,并深入探讨如何解决开发中遇到的问题。
项目背景和需求
在项目的初始阶段,我们需要一个自动化生成 MD5 彩虹表的工具,并将生成的数据存储在 MySQL 数据库中。主要功能包括:
- 批量生成 MD5 哈希和对应的原始字符串。
- 去重处理,避免重复存储相同的 MD5 哈希。
- 可扩展性,支持任意字符集和字符串长度。
- 高效插入数据,避免性能瓶颈。
然而,在实现的过程中遇到了两个关键问题:
- 每次刷新页面时,因没有去重导致重复数据大量生成。
- 设置批量生成的目标条数(如 10,000 条),但数据量却无法稳定在目标值。
接下来,我们将详细拆解整个解决方案和代码实现。
数据库设计
在生成彩虹表之前,我们需要设计存储数据的数据库表。
数据表结构
表名为 rainbow_table
,包含以下字段:
- id: 自增主键,用于标识每条记录。
- hash: 存储 MD5 哈希值。
- original: 存储原始字符串。
- unique_hash: 创建唯一约束,确保哈希值不重复。
SQL 表的创建代码如下:
sql
CREATE TABLE rainbow_table (
id INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
hash VARCHAR(32) NOT NULL,
original VARCHAR(255) NOT NULL,
UNIQUE KEY unique_hash (hash)
);
如果表不存在,我们会在 PHP 脚本中动态创建它,确保代码的鲁棒性。
PHP 脚本实现
核心逻辑概述
- 字符集配置:可以自由定义生成字符串所使用的字符集,包括大小写字母、数字和特殊符号。
- 随机生成字符串:通过随机组合字符,生成指定长度的字符串。
- MD5 哈希计算:将随机字符串计算为 MD5 哈希值。
- 数据插入与去重 :使用
INSERT IGNORE
避免重复插入。 - 批量生成与页面自动刷新:每次生成一定数量的数据后自动刷新页面,持续生成。
完整 PHP 代码如下:
php
<?php
$servername = "localhost";
$username = "md5";
$password = "123456";
$dbname = "md5";
$tableName = "rainbow_table";
// 创建数据库连接
$conn = new mysqli($servername, $username, $password, $dbname);
// 检查连接是否成功
if ($conn->connect_error) {
die("连接失败: " . $conn->connect_error);
}
// 检查表是否存在,如果不存在则创建
$tableExists = $conn->query("SHOW TABLES LIKE '$tableName'")->num_rows > 0;
if (!$tableExists) {
$createTableSql = "CREATE TABLE $tableName (
id INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
hash VARCHAR(32) NOT NULL,
original VARCHAR(255) NOT NULL,
UNIQUE KEY unique_hash (hash)
)";
if ($conn->query($createTableSql) === TRUE) {
echo "表 $tableName 创建成功<br>";
} else {
die("创建表错误: " . $conn->error);
}
}
// 彩虹表生成函数
function generateRainbowTable($charset, $batchSize, $conn, $tableName) {
$charsetLength = strlen($charset);
$count = 0;
$maxLength = 18; // 设置随机字符串最大长度
while ($count < $batchSize) {
// 随机生成字符串长度
$length = rand(1, $maxLength);
$count += generateRandomCombination($charset, $length, $charsetLength, $conn, $batchSize - $count, $tableName);
}
echo "生成了 $count 条记录\n";
}
function generateRandomCombination($charset, $length, $charsetLength, $conn, $remaining, $tableName) {
if ($remaining <= 0) return 0;
$currentString = '';
for ($i = 0; $i < $length; $i++) {
$currentString .= $charset[rand(0, $charsetLength - 1)];
}
$hash = md5($currentString);
// 使用 INSERT IGNORE 避免重复插入
$stmt = $conn->prepare("INSERT IGNORE INTO $tableName (hash, original) VALUES (?, ?)");
$stmt->bind_param("ss", $hash, $currentString);
$stmt->execute();
return $stmt->affected_rows > 0 ? 1 : 0;
}
// 配置
$charset = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.@#*?!$%^&()-_=+[]{}|;:,.<>~'; // 定义字符集
$batchSize = 2000; // 每次生成 2000 条
generateRainbowTable($charset, $batchSize, $conn, $tableName);
$conn->close();
?>
关键点解析
-
随机生成字符串
php$length = rand(1, $maxLength); $currentString .= $charset[rand(0, $charsetLength - 1)];
使用
rand()
随机生成字符串长度,再通过字符集随机组合字符,生成目标字符串。 -
避免重复插入
php$stmt = $conn->prepare("INSERT IGNORE INTO $tableName (hash, original) VALUES (?, ?)");
使用
INSERT IGNORE
确保插入数据时,遇到重复哈希值会自动跳过,避免浪费资源。 -
批量生成与计数
php$count += generateRandomCombination($charset, $length, $charsetLength, $conn, $batchSize - $count, $tableName);
每次生成一定数量的数据,直到达到目标批量数量。
前端自动刷新页面
为了实现自动化生成,我们在前端页面使用 JavaScript 设置定时刷新,每次刷新生成一批数据:
html
<script>
// 页面加载完成后自动刷新
window.onload = function() {
setTimeout(function() {
location.reload();
}, 1000); // 1秒后刷新页面
};
</script>
通过这种方式,可以在页面刷新时持续调用生成函数,直到数据库存储满足预期需求。
问题与优化方案
问题 1:重复数据导致效率低下
最初代码未去重,每次刷新生成的大量数据包含重复项,浪费了存储和计算资源。通过添加 INSERT IGNORE
和数据库唯一索引,解决了此问题。
问题 2:生成数据量不足
由于生成逻辑中可能因重复数据导致插入失败,数据总量无法达到目标条数。通过调整随机生成逻辑,确保生成字符串更加分散,提高了数据覆盖率。
结论
本文通过详细介绍一个 PHP 实现的 MD5 彩虹表生成器,展示了从数据库设计到代码优化的完整流程。通过随机生成字符串、去重插入以及前端自动刷新机制,实现了高效的批量生成工具。
该工具不仅适用于 MD5,还可拓展为其他哈希算法生成器(如 SHA-1 或 SHA-256)。未来可进一步优化数据生成算法,提高生成速度和覆盖范围。
最后我的MD5解密平台:md5.li