Java将哈希转换为随机字符串
Posted
技术标签:
【中文标题】Java将哈希转换为随机字符串【英文标题】:Java convert hash to random string 【发布时间】:2012-03-10 07:43:37 【问题描述】:我正在尝试开发一个在彩虹表生成器中使用的归约函数。
归约函数的基本原理是它接受一个哈希,执行一些计算,然后返回一个一定长度的字符串。
目前我正在使用 SHA1 哈希,我需要返回一个长度为 3 的字符串。我需要将字符串由以下任意三个随机字符组成:
abcdefghijklmnopqrstuvwxyz0123456789
我面临的主要问题是我编写的任何归约函数总是返回已经生成的字符串。并且一个好的归约函数很少会返回重复的字符串。
任何人都可以就实现此目的提出任何想法吗?或者任何关于哈希到字符串操作的建议都会很棒。
提前致谢
乔什
【问题讨论】:
【参考方案1】:所以听起来你有 20 位基数 255(SHA1 哈希的长度)需要映射到基数 36 的三位数字。我只需从哈希字节、模数中创建一个 BigInteger 36^3,并返回以 36 为底的字符串。
public static final BigInteger N36POW3 = new BigInteger(""+36*36*36));
public static String threeDigitBase36(byte[] bs)
return new BigInteger(bs).mod(N36POW3).toString(36);
// ...
threeDigitBase36(sha1("foo")); // => "96b"
threeDigitBase36(sha1("bar")); // => "y4t"
threeDigitBase36(sha1("bas")); // => "p55"
threeDigitBase36(sha1("zip")); // => "ej8"
当然会有冲突,就像当你将任何空间映射到一个更小的空间时,但熵应该比比上述解决方案更愚蠢的东西要好。
【讨论】:
我的错。我会删除那个答案。这是一个与同余关系中的逆存在相关的属性(在这种情况下你不需要)。 非常感谢,它们都是超级答案,但我接受了 Bohemian 的答案,因为它略短。感谢所有的cmets; *** 上的人再次证明自己没有得到足够的报酬,无论他们在做什么!!! @JoshuaCraven:非常欢迎!另请注意,我的答案和 Bohemian 的答案都可能返回长度为 1、2 或 3 的字符串,因此如果长度小于 3,您需要用零填充返回的字符串。【参考方案2】:应用KISS原则:
SHA 只是一个字符串String
的 JDK 哈希码“足够随机”
Integer
可以在任何基础上渲染
这一行代码就可以做到:
public static String shortHash(String sha)
return Integer.toString(sha.hashCode() & 0x7FFFFFFF, 36).substring(0, 3);
注意:& 0x7FFFFFFF
将符号位归零(哈希码可以是负数,否则会以负号开头)。
编辑 - 保证哈希长度
我最初的解决方案是幼稚的——它没有处理int
哈希小于100
(基数 36)的情况——这意味着它会打印少于 3 个字符。此代码修复了该问题,同时仍保持值“随机”。也避免了substring()
的调用,所以性能应该会更好。
static int min = Integer.parseInt("100", 36);
static int range = Integer.parseInt("zzz", 36) - min;
public static String shortHash(String sha)
return Integer.toString(min + (sha.hashCode() & 0x7FFFFFFF) % range, 36);
此代码通过强制其介于 100
和 zzz
之间来保证最终哈希有 3 个字符 - 以 36 为底的最低和最高 3 字符哈希,同时仍使其“随机”。
【讨论】:
很抱歉再次提出另一个明智的回答问题。但是,如果我将 (0, 3) 的答案中的子字符串更改为 (0, 4),那么在 4 个字符以下生成的子字符串的数量就会成为一个很大的问题。此外,该功能似乎运行得非常缓慢。你能解释一下为什么会这样吗? @JoshuaCraven 好的 - 我添加了更多代码来解决您的问题。顺便说一句,你也提出了很好的观点。 ***的东西。非常感谢您的帮助!!以上是关于Java将哈希转换为随机字符串的主要内容,如果未能解决你的问题,请参考以下文章