模糊数据库ID

时间:2010-03-03 20:05:15

标签: php mysql database

我有一个主键自动递增的表。我希望有一个与主键关联的图像,但我不希望显示主键。将图像命名为:

$filename = md5($primarykey + $secret_string) . '.jpg';

是一个很好的解决方案吗?

我担心可能会发生冲突并且文件被覆盖。

另一个选择当然是生成一个随机字符串,检查它是不是作为文件存在并将其存储在数据库中......但如果没有必要,id不想存储其他数据。

另一个选项是逻辑转换youtube url样式,例如1 = a 2 = b但是具有随机顺序,例如1 = x 2 = m ...但是那时它有可能被解码...加上md5可能比任何youtube网址功能都要轻。

我猜我会处理超过两百万条记录,那么碰撞的可能性是什么?您会选择哪个选项,还是想到更好的方法?

10 个答案:

答案 0 :(得分:2)

使用linear congruential generator。如果正确选择值,那么您将拥有一个周期非常长的伪随机序列。没有碰撞,但请注意,这只是一种混淆方法,不会提供任何真正的安全性(但我认为这不是你想要的)。

答案 1 :(得分:2)

  

我猜我正在处理   两百万条记录是什么呢   可能是碰撞的引擎盖?

根据Wikipedia,您需要超过2 * 10 ^ 19条记录才能获得至少一次碰撞的50%概率,所以我想您不必担心。< / p>

答案 2 :(得分:1)

您提供的准则非常适合做这项工作。您不必担心冲突,数据库使用的整数不会产生与其他任何相同的md5哈希值。

如果你想真的肯定:这是一个小小的测试脚本;)

<?php
for($i = 0; $i < 1000000; ++$i) {
    $hash = md5($i);
    if(isset($x[$hash])) { die("COLLISION!"); }
    $x[$hash] = true;
}        }
echo "All is well";

一个更复杂的解决方案似乎浪费你的时间,但是如果你想要更短的ID,你可以给每张图片提供一个短的随机生成的id(并检查它是否已经在生成时间使用并且生成另一个如果那是情况下)

答案 3 :(得分:0)

如果您想使用该ID,但不想透露该ID,并且希望碰撞风险较低;一种选择是使用ID的哈希值。散列将是一致的,不可逆的,并且(除了大的数据集 - 2 32 ish取决于所使用的散列)对于每张照片是唯一的。你似乎在你的问题中有了基本的想法:

$filename = md5($primarykey + $secret_string) . '.jpg';

您可以将MD5替换为您选择的哈希更好的算法。优选具有较大输出的东西。基于浏览各种文章以回应评论,似乎SHA512或类似的东西会更合适。

答案 4 :(得分:0)

你有两种选择:

  • 生成一些东西&amp;验证没有冲突
  • 生成一些东西&amp;希望没有碰撞

您通常可以使用以下选项: - 哈希 - 随机生成的字符串 - 一个UUID

哈希 如果您选择哈希,请选择碰撞发生率较低的内容。此外,在进行哈希时,请考虑为什么要隐藏数据库ID。如果你正在使用普通数字,你可以花很长时间找出你的哈希值,你绝对需要加盐。 salted hash的优点是生成速度快,碰撞机会少(在小情况下绝对不需要验证这些,所以更快的插入)。缺点是任何适当的实现将是SHA256或更好,这意味着它很长。如果要保存数据库/索引空间,可以执行一些十六进制转换,这可能比您想要的更多。

随机字符串 这可以生成任何适合您的长度,任何字符集或数字a-Z0-9。这也意味着在URI,REQUEST数据等中使用的较短字符串中的“更多”数据。缺点是您必须检查它是否在数据库中。

UUID 就像一个哈希,快速生成,相当低的碰撞机会,并且可以被修改成比纯输出“更少”丑陋。

我的建议 不要这样做。我之前必须处理一个非常大的实现,从一个非常小的实现发展而来。最终你开始做“聪明”的事情,比如创建完全唯一的标识符(例如内容类型+你的标识符)并开始看到它的某些价值,但是你必须处理规模。缩放这是非常困难的。数据库针对ID作为主键进行了优化,如果您希望将其垂直扩展,则需要考虑大量的内容。如果必须,仅将其用于外部客户端交互。

答案 5 :(得分:0)

通常,为了掩盖URL中的数据库ID,您实际上会对id进行加密,因为隐藏的内容需要是可逆的,服务器才能从隐藏的id中查找数据库记录。对于将数据库ID映射到文件名的情况,可逆性可能不那么重要,但它是一种简单的模式,也可以消除冲突的可能性。

您需要使用base64或十六进制编码将加密数据转换为ASCII,例如:

base64_encode(encrypt(id, secret_key))

解码:

decrypt(base64_decode(id), secret_key)

(上面是伪代码,你必须在PHP中找到合适的函数)

您不需要任何太过花哨的加密。像DES这样的简单分组密码就足够了。

答案 6 :(得分:0)

我同意使用Base64。你也可以使用Guid。或者只是将文件名存储在表格中,我已经完成了。

另外,请注意避免孤立的文件。

答案 7 :(得分:0)

诸如MD5之类的散列算法不是一个很好的解决方案,因为定义为不确保唯一性(它们创建具有有限数量值的散列)。

你想要的是加密。看看javax.crypto.Cipher。

答案 8 :(得分:0)

如果您可以添加列,请在表格中添加GUID作为UNIQUE列,并使用<GUID>.jpg作为键名。 GUID算法不应该在可预见的未来产生重复,但只是在UNIQUE约束的情况下会抓住这个。

答案 9 :(得分:-1)

只需使用主键的哈希值即可。发生碰撞的可能性很小。