Java将哈希转换为随机字符串

Jos*_*ven 6 java string hash reduction

我正在尝试开发一种在彩虹表生成器中使用的缩减功能.

缩减函数背后的基本原理是它接受散列,执行一些计算,并返回一定长度的字符串.

目前我正在使用SHA1哈希,我需要返回一个长度为3的字符串.我需要在以下任意三个随机字符上组成字符串:

abcdefghijklmnopqrstuvwxyz0123456789
Run Code Online (Sandbox Code Playgroud)

我面临的主要问题是我编写的任何缩减函数总是返回已经生成的字符串.一个好的缩减函数只会很少返回重复的字符串.

有人可以提出任何想法来实现这一目标吗?或者对哈希到字符串操作的任何建议都会很棒.

提前致谢

玩笑

mae*_*ics 6

所以听起来你有20个数字的基数255(SHA1哈希的长度),你需要映射到基数36的三个数字.我只是从哈希字节,模数36 ^ 3和一个BigInteger,返回基数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"
Run Code Online (Sandbox Code Playgroud)

当然会有碰撞,就像你将任何空间映射到一个较小的空间时一样,但是熵应该比上面的解决方案更好.


Boh*_*ian 4

应用KISS原则:

  • SHA 只是一个字符串
  • 的 JDK 哈希码String“足够随机”
  • Integer可以在任何基地渲染

这行代码就可以做到这一点:

public static String shortHash(String sha) {
    return Integer.toString(sha.hashCode() & 0x7FFFFFFF, 36).substring(0, 3);
}
Run Code Online (Sandbox Code Playgroud)

注意:是& 0x7FFFFFFF将符号位归零(哈希码可以是负数,否则会以前导减号呈现)。

编辑 - 保证哈希长度

int我最初的解决方案很幼稚 - 它没有处理哈希值小于(基数 36)的情况100- 这意味着它将打印少于 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);
}
Run Code Online (Sandbox Code Playgroud)

此代码通过强制最终哈希值介于100zzz- 基数 36 中的最低和最高 3 字符哈希值之间,保证最终哈希值具有 3 个字符,同时仍使其“随机”。