是否有一类散列算法,无论是理论上的还是实际的,根据下面的定义,类中的算法可能被认为是“反身”:
+运算符可能是串联或任何其他指定的操作,以将输出(hash1)组合回输入(“输入文本1”),以便算法(algo1)将产生完全相同的结果。即输入和输入+输出上的冲突。 +运算符必须组合两个输入的全部,算法可能不会丢弃部分输入。
该算法必须在输出中产生128位熵。 它可能(但不一定)在加密方面难以将输出反转回一个或两个可能的输入。
我不是数学家,但一个好的答案可能包括为什么这类算法不存在的证据。然而,这不是一个抽象的问题。我真的很想在我的系统中使用这样的算法,如果确实存在的话。
答案 0 :(得分:1)
当然,这是一个微不足道的:
def algo1(input):
sum = 0
for i in input:
sum += ord(i)
return chr(sum % 256) + chr(-sum % 256)
连接结果,“哈希”不会改变。当你可以反转哈希时,很容易想出类似的东西。
答案 1 :(得分:1)
在ephemiat's answer的基础上,我认为你可以这样做:
选择您喜欢的对称密钥块密码(例如:AES)。具体来说,假设它在128位块上运行。对于给定密钥K,分别用Enc(K,块)和Dec(K,块)表示加密函数和解密函数,因此block = Dec(K,Enc(K,block))= Enc(K,十二月(K,街区))。
将输入分为128位块数组(必要时填充)。您可以选择固定密钥K,也可以将其作为哈希输入的一部分。在下文中,我们假设它是固定的。
def hash(input):
state = arbitrary 128-bit initialization vector
for i = 1 to len(input) do
state = state ^ Enc(K, input[i])
return concatenate(state, Dec(K, state))
此函数返回256位散列。通过一个警告来验证它是否满足“反身性”条件应该不是太难 - 在连接散列之前必须将输入填充到整数个128位块。换句话说,代替最初指定的hash(input)= hash(input + hash(input)),我们有hash(input)= hash(input'+ hash(input)),其中input'只是填充输入。我希望这不是太麻烦。
答案 2 :(得分:1)
是的,您可以使用CRC获得此效果。
您需要做的是:
[Initial state] >- input string -> [A] >- hash -> [A] ...
Here is one way to find the hash。 (注意:CRC32示例中的数字有误,但算法有效。)
这是Java中的一个实现。注意:我使用的是32位CRC(小于你指定的64位),因为它是在标准库中实现的,但是使用第三方库代码可以轻松地将其扩展为更大的哈希值。
public static byte[] hash(byte[] input) {
CRC32 crc = new CRC32();
crc.update(input);
int reg = ~ (int) crc.getValue();
return delta(reg, reg);
}
public static void main(String[] args) {
byte[] prefix = "Hello, World!".getBytes(Charsets.UTF_8);
System.err.printf("%s => %s%n", Arrays.toString(prefix), Arrays.toString(hash(prefix)));
byte[] suffix = hash(prefix);
byte[] combined = ArrayUtils.addAll(prefix, suffix);
System.err.printf("%s => %s%n", Arrays.toString(combined), Arrays.toString(hash(combined)));
}
private static byte[] delta(int from, int to) {
ByteBuffer buf = ByteBuffer.allocate(8);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.putInt(from);
buf.putInt(to);
for (int i = 8; i-- > 4;) {
int e = CRCINVINDEX[buf.get(i) & 0xff];
buf.putInt(i - 3, buf.getInt(i - 3) ^ CRC32TAB[e]);
buf.put(i - 4, (byte) (e ^ buf.get(i - 4)));
}
return Arrays.copyOfRange(buf.array(), 0, 4);
}
private static final int[] CRC32TAB = new int[0x100];
private static final int[] CRCINVINDEX = new int[0x100];
static {
CRC32 crc = new CRC32();
for (int b = 0; b < 0x100; ++ b) {
crc.update(~b);
CRC32TAB[b] = 0xFF000000 ^ (int) crc.getValue();
CRCINVINDEX[CRC32TAB[b] >>> 24] = b;
crc.reset();
}
}
答案 3 :(得分:0)
好吧,我可以告诉你,你不会得到不存在的证据。这是一个例子:
operator +(a,b):计算a的64位散列,b的64位散列,并连接位串,返回128位散列。
algo1:对于某个128位值,忽略最后64位并计算前64位的一些散列。
非正式地,任何产生第一个运算符的algo1作为其第一步都可以。也许并不像你想要的那样有趣,但它符合要求。它也不是没有现实世界的例子。许多密码哈希算法会截断它们的输入。
答案 4 :(得分:0)
我很确定这样一个“反身散列”函数(如果它确实存在于多个微不足道的意义上)在正常意义上不会是一个有用的散列函数。
对于“普通”反身散列函数的示例:
int hash(Object obj) { return 0; }