我是服务器端编程的全新手。目前我正在编写一个服务来存储从ios app发送的用户文件。我想为每个文件生成一个唯一的ID,并将其用作文件名。问题是,许多解决方案,例如使用哈希函数,我在网上发现有碰撞的风险。那么这样做的首选方式是什么?我知道AWS s3会为每个文件生成一个唯一的ID。他们是如何实现这一目标的?
答案 0 :(得分:3)
您使用的任何编程语言都可能具有GUID(有时称为UUID)库,可以将其视为通用唯一。见https://en.wikipedia.org/wiki/Universally_unique_identifier
Hashing根本不会解决这个问题,因为哈希的意思是两个相同的输入应该产生两个相同的输出。因此,如果两个用户上传ThisIsAFile.pdf
,则必须说a89na3
并且会发生冲突。
答案 1 :(得分:0)
一种可能的方法是生成一些宽随机 id。如果你生成几个字符的随机名称,如_5E960vkoXF8_6t2yfMbEM0A_6uBsy060PxH_2YKKKmZkTR6
,则可以使碰撞概率小到可以忽略不计(例如,你的系统需要运行数十亿年才能观察到一次碰撞)。如果您想估计该概率,请使用birthday problem方法。
(如果你的概率足够小,碰撞并不总是一个问题)
UUID正在利用这个想法。所以最简单的方法就是使用生成它们的库函数,例如: uuid_generate。您可能也想这样做(这是代码您自己的随机id生成器),但您需要注意随机性。
至少,你可以使用一个好 PRNG(例如Mersenne twister个)来定期(并在启动时)播种一些随机噪音,例如使用/dev/random
(仔细阅读 random(4) ...)或getrandom(2)。或者您可以购买一些随机生成的硬件源(如OneRNG)。
BTW,如果您认为用户的文件内容没有改变(因此每个文件在创建时写入一次),您可以对它们使用一些cryptographic hash函数(如SHA 256)。然后,如果两个不同的用户准确上传相同的内容(例如,GPLv3的文本),您将把它一次存储在磁盘上(在某些< em>共享文件)。该 https://www.softwareheritage.org/项目正在使用这种技术。
(出于基数原因,碰撞在理论上仍然存在,但非常不可能)
你不想让collisions在数学上不可能。你可能想要让它们变得非常不可能:如果概率小于10 -50 (或者只是10 -30 大约2 -100 )你可能不应该关心(因为在碰撞可能发生之前我们的地球行星会消失)。