简体   繁体   English

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

[英]Java convert hash to random string

I'm trying to develop a reduction function for use within a rainbow table generator. 我正在尝试开发一种在彩虹表生成器中使用的缩减功能。

The basic principle behind a reduction function is that it takes in a hash, performs some calculations, and returns a string of a certain length. 缩减函数背后的基本原理是它接受散列,执行一些计算,并返回一定长度的字符串。

At the moment I'm using SHA1 hashes, and I need to return a string with a length of three. 目前我正在使用SHA1哈希,我需要返回一个长度为3的字符串。 I need the string to be made up on any three random characters from: 我需要在以下任意三个随机字符上组成字符串:

abcdefghijklmnopqrstuvwxyz0123456789

The major problem I'm facing is that any reduction function I write, always returns strings that have already been generated. 我面临的主要问题是我编写的任何缩减函数总是返回已经生成的字符串。 And a good reduction function will only return duplicate strings rarely. 一个好的缩减函数只会很少返回重复的字符串。

Could anyone suggest any ideas on a way of accomplishing this? 有人可以提出任何想法来实现这一目标吗? Or any suggestions at all on hash to string manipulation would be great. 或者对哈希到字符串操作的任何建议都会很棒。

Thanks in advance 提前致谢

Josh 玩笑

So it sounds like you've got 20 digits of base 255 (the length of a SHA1 hash) that you need to map into three digits of base 36. I would simply make a BigInteger from the hash bytes, modulus 36^3, and return the string in base 36. 所以听起来你有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"

Of course there will be collisions, as when you map any space into a smaller one, but the entropy should be better than something even sillier than the above solution. 当然会有碰撞,就像你将任何空间映射到一个较小的空间时一样,但是熵应该比上面的解决方案更好。

Applying the KISS principle: 应用KISS原则:

  • An SHA is just a String SHA只是一个字符串
  • The JDK hashcode for String is "random enough" String的JDK哈希码是“随机的”
  • Integer can render in any base Integer可以在任何基础上呈现

This single line of code does it: 这一行代码就是这样的:

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

Note: The & 0x7FFFFFFF is to zero the sign bit (hash codes can be negative numbers, which would otherwise render with a leading minus sign). 注意: & 0x7FFFFFFF将符号位置零(哈希码可以是负数,否则将使用前导减号进行渲染)。

Edit - Guaranteeing hash length 编辑 - 保证哈希长度

My original solution was naive - it didn't deal with the case when the int hash is less than 100 (base 36) - meaning it would print less than 3 chars. 我的原始解决方案是天真的 - 当int哈希小于100 (基数36)时它没有处理这种情况 - 这意味着它将打印少于3个字符。 This code fixes that, while still keeping the value "random". 此代码修复了这一点,同时仍保持值“随机”。 It also avoids the substring() call, so performance should be better. 它还避免了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);
}

This code guarantees the final hash has 3 characters by forcing it to be between 100 and zzz - the lowest and highest 3-char hash in base 36, while still making it "random". 此代码通过强制它在100zzz之间保证最终散列有3个字符 - 基数36中的最低和最高3字符散列,同时仍然使其“随机”。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM