是否有一种加密方式可以采用任意长度的字符串并生成一个10字符以下的哈希值?我想生成合理的唯一ID,但是基于消息内容,而不是随机的。
但是,如果不能使用任意长度的字符串,我可以将消息约束为整数值。但是,在这种情况下,对于两个连续的整数,散列必须不相似。
答案 0 :(得分:62)
您可以使用任何常用的哈希算法(例如SHA-1),这会给您一个比您需要的结果略长的结果。只需将结果截断到所需的长度,这可能就足够了。
例如,在Python中:
>>> import hashlib
>>> hash = hashlib.sha1("my message".encode("UTF-8")).hexdigest()
>>> hash
'104ab42f1193c336aa2cf08a2c946d5c6fd0fcdb'
>>> hash[:10]
'104ab42f11'
答案 1 :(得分:34)
如果你不需要一个强大的反对故意修改的算法,我发现了一个名为adler32的算法,可以产生相当短的(~8个字符)结果。从下拉列表中选择它以试用它:
答案 2 :(得分:10)
您需要散列内容以提供摘要。有许多哈希可用,但结果集中10个字符非常小。回过头来,人们使用CRC-32,它产生33位散列(基本上是4个字符加1位)。还有CRC-64产生65位散列。产生128位散列(16字节/字符)的MD5因加密目的而被视为已损坏,因为可以找到具有相同散列的两条消息。不用说,任何时候你从任意长度的消息中创建一个16字节的摘要,你最终会得到重复。摘要越短,碰撞的风险就越大。
但是,你担心两个连续消息(无论是否为整数)的散列不相似应该对所有散列都是真的。即使原始消息中的单个位更改也会产生截然不同的结果摘要。
所以,使用像CRC-64这样的东西(以及结果的基础-64')可以让你进入你正在寻找的社区。 p>
答案 3 :(得分:6)
您可以将hashlib库用于Python。 shake_128 和 shake_256 算法提供了可变长度的哈希。这是一些工作代码(Python3):
import hashlib
>>> my_string = 'hello shake'
>>> hashlib.shake_256(my_string.encode()).hexdigest(5)
'34177f6a0a'
请注意,使用长度参数 x (例如5),该函数将返回长度为 2x 的哈希值。
答案 4 :(得分:5)
总结一个对我有帮助的答案(注意@ erasgreenunk关于使用base-64编码的评论)。我的目标是创建一个 唯一的短字符串...
我没有专家,所以如果它有任何明显的错误,请更正此问题(在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
使用的不仅仅是十六进制字符(如果您使用hash.hexdigest()
,则会得到什么),因此它不太可能发生碰撞(即截断比十六进制摘要更安全。)
注意:使用UUID4(随机)。有关其他类型,请参阅http://en.wikipedia.org/wiki/Universally_unique_identifier。
答案 5 :(得分:3)
如果您需要"sub-10-character hash"
您可以使用 Fletcher-32 算法生成8个字符哈希(32位), CRC-32 或 Adler-32 。
CRC-32比Adler32慢20% - 100%。
Fletcher-32比Adler-32稍微可靠。它的计算成本低于Adler校验和:Fletcher vs Adler comparison。
下面给出了一个带有一些Fletcher实现的示例程序:
#include <stdio.h>
#include <string.h>
#include <stdint.h> // for uint32_t
uint32_t fletcher32_1(const uint16_t *data, size_t len)
{
uint32_t c0, c1;
unsigned int i;
for (c0 = c1 = 0; len >= 360; len -= 360) {
for (i = 0; i < 360; ++i) {
c0 = c0 + *data++;
c1 = c1 + c0;
}
c0 = c0 % 65535;
c1 = c1 % 65535;
}
for (i = 0; i < len; ++i) {
c0 = c0 + *data++;
c1 = c1 + c0;
}
c0 = c0 % 65535;
c1 = c1 % 65535;
return (c1 << 16 | c0);
}
uint32_t fletcher32_2(const uint16_t *data, size_t l)
{
uint32_t sum1 = 0xffff, sum2 = 0xffff;
while (l) {
unsigned tlen = l > 359 ? 359 : l;
l -= tlen;
do {
sum2 += sum1 += *data++;
} while (--tlen);
sum1 = (sum1 & 0xffff) + (sum1 >> 16);
sum2 = (sum2 & 0xffff) + (sum2 >> 16);
}
/* Second reduction step to reduce sums to 16 bits */
sum1 = (sum1 & 0xffff) + (sum1 >> 16);
sum2 = (sum2 & 0xffff) + (sum2 >> 16);
return (sum2 << 16) | sum1;
}
int main()
{
char *str1 = "abcde";
char *str2 = "abcdef";
size_t len1 = (strlen(str1)+1) / 2; // '\0' will be used for padding
size_t len2 = (strlen(str2)+1) / 2; //
uint32_t f1 = fletcher32_1(str1, len1);
uint32_t f2 = fletcher32_2(str1, len1);
printf("%u %X \n", f1,f1);
printf("%u %X \n\n", f2,f2);
f1 = fletcher32_1(str2, len2);
f2 = fletcher32_2(str2, len2);
printf("%u %X \n",f1,f1);
printf("%u %X \n",f2,f2);
return 0;
}
输出:
4031760169 F04FC729
4031760169 F04FC729
1448095018 56502D2A
1448095018 56502D2A
同意Test vectors:
"abcde" -> 4031760169 (0xF04FC729)
"abcdef" -> 1448095018 (0x56502D2A)
Adler-32对于具有几百个字节的短消息具有弱点,因为这些消息的校验和对32个可用位的覆盖率较差。检查一下:
The Adler32 algorithm is not complex enough to compete with comparable checksums
答案 6 :(得分:2)
您可以使用具有PHP,Javascript,Python等实现的哈希库。有关详细信息,请查看this link
答案 7 :(得分:0)
只需在终端(在MacOS或Linux上)上运行此程序即可:
ProcessInfo.processInfo.environment["SKIP_VERIFICATION"]
8个字符长。
答案 8 :(得分:0)
现在是2019年,还有更好的选择。即xxhash。
~ echo test | xxhsum
2d7f1808da1fa63c stdin
答案 9 :(得分:-1)
我最近需要一些简单的字符串缩减功能。基本上,代码看起来像这样(前面的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会以输入字符串结束(0 * 37 + value = value)。如果您想在过程结束时“可读”,Normalize将以增加冲突为代价调整转换后的字节。
来源:
https://github.com/cubiclesoft/cross-platform-cpp/blob/master/sync/sync_util.cpp