我有一个大字符串$string
,当应用于时md5()
,给我
c4ca4238a0b923820dcc509a6f75849b
长度是32,我想减少它,所以
base64_encode(md5($string, true));
xMpCOKC5I4INzFCab3WEmw==
删除最后两个==
它给了我一个长度= 22的字符串。
还有其他更好的算法吗?
我不确定您是否意识到这md5
是一个哈希函数,因此是不可逆的。如果您不关心可逆性,您也可以将md5
哈希(或您喜欢的任何哈希*)修剪为任意数量的字符。所有这一切都会增加碰撞的可能性(我觉得这不会产生均匀的分布)。
如果您正在寻找可逆(即非破坏性)压缩,那么不要重新发明轮子。使用内置函数,例如gzdeflate()
orgzcompress()
或其他类似函数。
一种更好的方法是,不是将二进制转换为十六进制(如 md5 那样),然后将字符串转换为 base64,而是从十六进制 md5 直接转换为 base64。
由于十六进制是每个字符 16 位,而 base64 是每个字符 64 位,因此每 2 个十六进制字符将组成一个 base64 字符。
要执行转换,您可以执行以下操作:
这将产生一个 16 字符的 base64 字符串,其值与 md5 字符串的十六进制表示形式相同。
理论上,你可以对任何基地做同样的事情。如果我们有办法用 ASCII 编码 base128 字符串,我们可以得到一个 8 个字符的字符串。但是,由于字符集有限,我认为base64是常用的最高基数。
length
您想要的字符串越小.. 的数量越小possible combination
有声望的可能性总数
总可能性 = n r
由于我们正在处理base64具有可打印的输出,这意味着我们只有 64 个字符
n = 64
如果您正在查看 22 个字母的长度
n r = 64 22 = 5,444,517,870,735,015,415,413,993,718,908,291,383,296 种可能性
回到你的问题:有没有更好的算法?
将具有良好哈希的字符串截断为所需的长度,因为总的可能性和冲突是固定的
$string = "the fox jumps over the lazy brown dog";
echo truncateHash($string, 8);
输出
9TWbFjOl
使用的功能
function truncateHash($str, $length) {
$hash = hash("sha256", $str, true);
return substr(base64_encode($hash), 0, $length);
}
不确定 MD5 是否适合您,但我会假设您有理由坚持使用此算法并正在寻找更短的表示。有几种可能性可以生成具有不同字母的较短字符串:
MD5 的最短可能形式是它的二进制表示,要获得这样的字符串,您可以简单地调用:
$binaryMd5 = md5($input, true);
这个字符串可以像数据库中的任何其他字符串一样存储,它只需要 16 个字符。只需确保使用mysqli_real_escape_string()
或使用参数化查询 (PDO) 进行正确的转义。
Base64 编码将生成一个带有以下字母的字符串:[0-9 AZ az + /] 并使用 '=' 作为填充。这种编码非常快,但有时会包含不需要的字符“+/=”。
$base64Md5 = base64_encode(md5($input, true));
MD5 哈希的输出长度始终为 24 个字符。
base62 编码仅使用字母表 [0-9 AZ az]。这样的字符串可以安全地用于任何目的,例如 URL 中的标记,而且它们非常紧凑。我写了一个base62 编码器,它能够将二进制字符串转换为 base62 字母表。这可能不是最快的实现,但我的目标是编写可理解的代码。同一个类可以很容易地适应不同的字母。
$base62Md5 = StoBase62Encoder::base62encode(md5($input, true));
MD5 散列的输出长度从 16 到 22 个字符不等。
这种编码生成较短的字符串,
print base64_encode(hash("crc32b",$string,1));
输出
qfQIdw==
我从您的帖子中读到您正在搜索散列算法而不是压缩。
php中有各种标准的散列算法。看看 PHP散列函数。根据您要散列的内容,有不同的方法。小心并计算平均碰撞概率。
但是,您似乎正在搜索“压缩”,它输出给定字符串的最小可能大小的字符。如果你这样做了,那么看看Lempel-Ziv-Welch ( php implementation ) 或其他。
Base 91看起来是最节省空间的二进制到 ASCII 可打印编码算法(这似乎是您想要的)。
我还没有看到 PHP 实现,但是如果您的软件必须与其他软件一起使用,我会坚持使用 Base 64;它是众所周知的,闪电般的速度,随处可用。
首先,回答您的问题:是的,有更好的算法(如果“更好”是指“更短”)。
将该hash()
函数(它是 PHP 核心的一部分,自 PHP 5.1.2 起默认启用)与任何、adler32
、fnv132
、crc32
或crc32b
算法一起使用。fnv132
joaat
如果对您当前的情况没有更深入的了解,您不妨选择您认为听起来最酷的那个。
这是一个例子:
hash('crc32b', $string)
我设置了一个在线示例,您可以使用它。
其次,我想指出,您所问的问题几乎与 stackoverflow 上的另一个问题完全相同。