哈希函数产生短哈希?

是否有单向encryption,可以采取任何长度的string,并产生一个10字符以下的散列? 我想要产生合理的唯一的ID,但基于消息内容,而不是随机的。

不过,如果任意长度的string是不可能的,我可以把消息限制为整数值。 但是,在这种情况下,散列必须不是相似的两个连续的整数。

您可以使用任何常用的散列algorithm(如SHA-1),这会给您一个比您需要的稍长的结果。 简单地截断结果到所需的长度,这可能是足够好的。

例如,在Python中:

>>> import hashlib >>> hash = hashlib.sha1("my message".encode("UTF-8")).hexdigest() >>> hash '104ab42f1193c336aa2cf08a2c946d5c6fd0fcdb' >>> hash[:10] '104ab42f11' 

如果你不需要一个强有力的修改algorithm,我发现了一个叫做adler32的algorithm,可以产生很短的( 〜8个字符)的结果。 从下拉列表中select它来尝试一下:

http://www.sha1-online.com/

你需要对内容进行散列以产生一个摘要。 有很多哈希可用,但是对于结果集来说,十个字符是相当小的。 回头来看,人们使用CRC-32,它产生一个33位散列(基本上是4个字符加一位)。 还有CRC-64产生一个65位散列。 产生128位散列(16字节/字符)的MD5由于密码学目的而被认为是中断的,因为可以find两个具有相同散列的消息。 不言而喻,任何时候你从任意长度的消息中创build一个16字节的摘要,你将最终得到重复。 消化越短,碰撞的风险就越大。

然而,你担心哈希不会相似的两个连续的消息(无论是否是整数)应该是真实的所有哈希值。 原始信息中即使只是一点点变化,也会产生极大地不同的结果摘要。

所以,使用像CRC-64(和基地64的结果)应该让你在你要找的邻里。

只是总结一个对我有帮助的答案(注意@ erasmospunk关于使用base-64编码的评论)。 我的目标是有一个很短的string, 大多是独特的…

我不是专家,所以如果有任何明显的错误,请纠正这个问题(在Python中,像接受的答案一样):

 import base64 import hashlib import uuid unique_id = uuid.uuid4() # unique_id = UUID('8da617a7-0bd6-4cce-ae49-5d31f2a5a35f') hash = hashlib.sha1(str(unique_id).encode("UTF-8")) # hash.hexdigest() = '882efb0f24a03938e5898aa6b69df2038a2c3f0e' result = base64.b64encode(hash.digest()) # result = b'iC77DySgOTjliYqmtp3yA4osPw4=' 

这里的result是使用了不止hex字符(如果使用了hash.hexdigest() ,你会得到什么),所以它不太可能发生冲突(也就是说,应该比hex摘要更安全的截断)。

注意:使用UUID4(随机)。 其他types见http://en.wikipedia.org/wiki/Universally_unique_identifier

您可以使用现有的哈希algorithm产生短小的内容,如MD5(128位)或SHA1(160)。 然后,可以通过将摘要的各个部分与其他部分异或来进一步缩短。 这会增加碰撞的机会,但不会像截断摘要一样糟糕。

另外,可以将原始数据的长度作为结果的一部分,以使其更加独特。 例如,将MD5摘要的前半部分与后半部分异或将导致64位。 为数据的长度增加32位(如果你知道长度总是适合于较less的位,则增加32位)。 这将导致一个96位(12字节)的结果,然后你可以变成24个字符的hexstring。 或者,你可以使用base 64编码,使其更短。

您可以使用具有PHP,Javascript,Python等实现的hashids库。有关更多详细信息,请查看此链接

我最近需要一些简单的string缩减function。 基本上,代码看起来像这样(C / C ++代码提前):

 size_t ReduceString(char *Dest, size_t DestSize, const char *Src, size_t SrcSize, bool Normalize) { size_t x, x2 = 0, z = 0; memset(Dest, 0, DestSize); for (x = 0; x < SrcSize; x++) { Dest[x2] = (char)(((unsigned int)(unsigned char)Dest[x2]) * 37 + ((unsigned int)(unsigned char)Src[x])); x2++; if (x2 == DestSize - 1) { x2 = 0; z++; } } // Normalize the alphabet if it looped. if (z && Normalize) { unsigned char TempChr; y = (z > 1 ? DestSize - 1 : x2); for (x = 1; x < y; x++) { TempChr = ((unsigned char)Dest[x]) & 0x3F; if (TempChr < 10) TempChr += '0'; else if (TempChr < 36) TempChr = TempChr - 10 + 'A'; else if (TempChr < 62) TempChr = TempChr - 36 + 'a'; else if (TempChr == 62) TempChr = '_'; else TempChr = '-'; Dest[x] = (char)TempChr; } } return (SrcSize < DestSize ? SrcSize : DestSize); } 

它可能比可能有更多的冲突,但它并不打算用作密码散列函数。 如果遇到太多碰撞,你可以尝试各种乘法器(即将37改为另一个素数)。 这段代码的一个有趣的特性是,当Src比Dest短时,Dest以inputstring原样结束(0 * 37 + value = value)。 如果在stream程结束时需要“可读”的内容,Normalize会以增加冲突为代价来调整转换后的字节。

资源:

https://github.com/cubiclesoft/cross-platform-cpp/blob/master/sync/sync_util.cpp