我想知道如何在给定输入字符串的情况下生成 GUID,以便相同的输入字符串产生相同的 GUID(有点像 MD5 哈希)。 MD5 哈希值的问题在于它们只是保证低冲突率,而不是唯一性。相反,我想要这样的东西:
guid('v1.0.0') == 1231231231123123123112312312311231231231
guid('v1.0.1') == 6154716581615471658161547165816154716581
guid('v1.0.2') == 1883939319188393931918839393191883939319
你会如何实现这种事情(最好是用 JavaScript)?甚至有可能做到吗?我不知道从哪里开始。像uuid module之类的东西不要使用种子字符串,并且它们不允许您使用自定义格式/字母表。
我不是在寻找 canonical UUID format ,而是一个 GUID,理想情况下仅由整数组成。
最佳答案
您需要定义文本字符串(例如“v1.0.0”)到 40 位长字符串(例如“123123...”)的一对一映射。这也称为双注入(inject),尽管在您的情况下,注入(inject)(从输入到输出的简单一对一映射,不一定是到)可能就足够了。正如您所注意到的,哈希函数不一定确保这种映射,但还有其他可能性,例如全周期 linear congruential generators (如果它们采用可以一对一映射到输入字符串值的种子),或其他可逆的功能。
但是,如果可能的输入字符串集大于可能的输出字符串集,则无法将所有输入字符串与所有输出字符串一对一映射(不创建重复项),因为 pigeonhole principle .
例如,您通常无法将所有 120 个字符的字符串与所有 40 位数字的字符串一对一映射,除非您以某种方式限制 120 个字符的字符串的格式。但是,如果您可以接受将输入字符串限制为不超过 1040 值(大约 132 位),或者如果您可以利用输入字符串,以便保证它们无损压缩到 40 个十进制数字(大约 132 位)或更少,这可能是也可能不可能。另请参阅 this question 。
该算法涉及两个步骤:
- 首先,通过构建字符串的
charCodeAt()
值,将字符串转换为BigInt
,类似于另一个答案中给出的stringToInt
方法。如果任何charCodeAt()
为 0x80 或更大,或者生成的BigInt
等于或大于BigInt(alphabet_length)**BigInt(output_length),则抛出错误)
。 - 然后,通过采用
BigInt
和输出字母表大小的模并将每个余数替换为输出字母表中的相应字符,将整数转换为另一个字符串,直到BigInt
达到 0。
关于javascript - 如何使用自定义字母表生成 GUID,其行为类似于 MD5 哈希(在 JavaScript 中)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63503924/