Skip to content

Instantly share code, notes, and snippets.

@divinity76
Last active December 6, 2023 01:14
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save divinity76/3eb1846fb5478120afd6e37d251a381f to your computer and use it in GitHub Desktop.
Save divinity76/3eb1846fb5478120afd6e37d251a381f to your computer and use it in GitHub Desktop.
hash collisions
<?php
declare(strict_types = 1);
ini_set("memory_limit", "-1");
$algo = "xxh64";
$dictionary = "crackstation.txt";
// MODE_dict_in_ram_hashes_in_ram($algo, $file);
MODE_dict_on_disk_hash_on_sqlite($algo, $dictionary);
function MODE_dict_on_disk_hash_on_sqlite(string $algo, string $dictionary): void
{
$sqlite_file = __FILE__ . ".sqlite3";
if (file_exists($sqlite_file)) {
if (! unlink($sqlite_file)) {
throw new \RuntimeException("unable to unlink sqlite3 file!");
}
}
$db = new \PDO('sqlite:' . $sqlite_file, '', '', array(
\PDO::ATTR_EMULATE_PREPARES => false,
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
\PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC
));
$db->exec('PRAGMA synchronous = OFF');
$db->exec('PRAGMA journal_mode = OFF');
$sql = 'CREATE TABLE t (
h BLOB PRIMARY KEY,
w BLOB NOT NULL) WITHOUT ROWID;';
$db->exec($sql);
$fp = fopen($dictionary, "rb");
$stm = $db->prepare("INSERT INTO t VALUES(?,?)");
$hash = "";
$word = "";
$stm->bindParam(1, $hash);
$stm->bindParam(2, $word);
while (($word = fgets($fp))) {
$word = rtrim($word, "\n");
$hash = hash($algo, $word, true);
try {
$stm->execute();
} catch (\Throwable $ex) {
$collision = $db->query("SELECT w FROM t WHERE h = " . $db->quote($hash))
->fetch(\PDO::FETCH_NUM)[0];
print_collision($collision, $word);
}
//echo ".";
}
var_dump($db->query("SELECT COUNT(*) FROM t")->fetch());
}
function MODE_dict_on_disk_hashes_in_ram(string $algo, string $dictionary): void
{
$fp = fopen($dictionary, "rb");
$hashes = [];
$counter = 0;
register_shutdown_function(function () use (&$counter) {
var_dump([
"counter" => $counter
]);
});
while (($word = fgets($fp))) {
++ $counter;
$word = rtrim($word, "\n");
$hash = hash($algo, $word, true);
if (isset($hashes[$hash])) {
print_collision($hashes[$hash], $word);
}
$hashes[$hash] = $word;
}
}
function MODE_dict_in_ram_hashes_in_ram(string $algo, string $dictionary): void
{
echo "loading..";
$words = file($dictionary, FILE_IGNORE_NEW_LINES);
echo ". done!\n";
$hashes = array();
foreach ($words as $word) {
$hash = hash($algo, $word, true);
if (isset($hashes[$hash])) {
print_collision($hashes[$hash], $word);
}
$hashes[$hash] = $word;
}
}
function print_collision(string $str1, string $str2): void
{
echo "\"{$str1}\" (hex " . bin2hex($str1) . " ) collides with \"{$str2}\" (hex " . bin2hex($str2) . " )\n";
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment