【问题标题】:Very fast hash function for hashing 8-16 byte strings用于散列 8-16 字节字符串的非常快的散列函数
【发布时间】:2017-06-23 17:17:33
【问题描述】:

我需要一个非常快速的字符串散列函数,它非常适合用 PHP 编写的 Web 应用程序。

我要解决的问题是在访问控制系统中为权限分配 ID。我正在考虑使用散列字符串来表示权限 ID。这样我就可以像这样检查权限:

if ($Auth->isAllowed($user, "blog.comment")) {
    // Do some operation
}
...

if ($Auth->isAllowed($user, "profile.avatar.change")) {
    // Do some other operation
}

数据库表会将权限哈希映射到用户的角色。要检查是否允许用户执行“profile.avatar.change”,将对相应的字符串进行哈希处理并对照 DB 表进行检查。

这非常方便,无需担心在不同模块之间维护唯一的权限 ID。但是散列函数应该非常高效。

【问题讨论】:

  • 散列是单向的,所以除了它的存在之外,没有什么可以检查散列的。
  • 最常见的方法是遵循linux的方法。 (使用 0-7 表示权限)。将 ID 分配给权限并执行 2^(id number) 以创建一个整数,然后以相同的方式展开它以确定您拥有哪些权限......或者只是传递带有一堆变量的对象/令牌并检查 $user- >can_change_stuff 或 $user->has_apples
  • @apokryfos,它不是重复的。这些都是我的问题。这个问题对字符串散列更具体。
  • @JayBlanchard,这正是我想要检查的 - 数据库表中是否存在某些特定权限。
  • 将 8-16 字节字符串散列为唯一字符串的最快方法是不对其执行任何操作。只需按原样存储即可。虽然很短。

标签: php string hash permissions access-control


【解决方案1】:

第一个问题是他为什么不使用简单的md5 函数?

尝试自己写哈希

其中一个most frequently referred function 是一个简单的散列伯恩斯坦函数,也称为Times 33 with Addition。它由 zend to make hashes for keys of associative arrayphp 中使用。在php 中可以这样实现:

function djb2($s){
    $word = str_split($s);
    $length = count($word);

    $hashAddress = 5381;
    for ($counter = 0; $counter < $length; $counter++){
        $hashAddress = (($hashAddress << 5) + $hashAddress) + $word[$counter];
    }
    return $hashAddress;
}
echo djb2("stackoverflow");

问题是当它以这种方式实现时,它相当慢。测试表明它比md5~3 倍。所以我们必须找到最快的internal implementation of a hash function

寻找最佳内部哈希

只需使用所有算法并测量时间来散列一百万个字符串。

function testing($algo, $str) {
    $start = microtime(true);
    for($ax = 0; $ax < 1000000; $ax++){
        hash($algo, $str);
    }

    $end = microtime(true);
    return ($end - $start);
}


$algos = hash_algos();
$times = [];

foreach($algos as $algo){
    $times[$algo] = testing($algo, "stackoverflow");
}

// sort by time ASC
asort($times);

foreach($times as $algo => $time){
    echo "$algo -> " . round($time, 2)."sec\n";
}

我的结果是:

fnv1a32 -> 0.29sec
fnv132 -> 0.3sec
crc32b -> 0.3sec
adler32 -> 0.3sec
crc32 -> 0.31sec
joaat -> 0.31sec
fnv1a64 -> 0.31sec
fnv164 -> 0.31sec
md4 -> 0.46sec
md5 -> 0.54sec
...
md2 -> 6.32sec

结果从执行到执行略有变化 - 前 8 个算法由于其关闭速度及其对服务器负载的依赖性而正在改组。

应该选择什么?

您可以使用上述前 8 个函数中的任何一个:$hash = hash('crc32', $string);。实际上,广泛使用的md5 函数仅比领导者慢 1.7 倍。

奖金

There are another functions like SuperFastHash,没有在 php 代码中实现,但比 crc32 快 4 倍。

【讨论】:

    【解决方案2】:

    在大多数情况下,散列函数的处理时间可以忽略不计。 如果你需要一点哈希(8 个字符),你可以简单地使用 crc32 函数。

    <?php
    $hash = hash('crc32', 'WhatDoYouWant');
    ?>
    

    您还可以将 hash 与 uniqid 结合以创建随机散列。

    <?php
    $hash = hash('crc32', uniqid());
    ?>
    

    【讨论】:

      【解决方案3】:

      使用xxHashPrestoDB 也使用它。 GitHub上的PHP实现

      【讨论】:

        猜你喜欢
        • 2011-12-25
        • 1970-01-01
        • 2013-11-16
        • 1970-01-01
        • 2020-03-17
        • 2011-02-07
        • 2011-04-11
        • 2012-10-30
        • 2011-09-30
        相关资源
        最近更新 更多