为什么这个unhash函数不能反转这个散列?
问题描述:
我写了一个用于密码和密钥生成的散列函数,但很快就意识到能够颠倒散列值是非常有价值的,所以我写了一个相反的函数,但是它的工作量很大。我不明白为什么这个DOESNT工作。为什么这个unhash函数不能反转这个散列?
function hash64(n:uint):uint
{
n = (~n) + (n << 21);
n = n^(n >> 24);
n = (n + (n << 3)) + (n << 8);
n = n ^(n >> 14);
n = (n + (n << 2)) + (n << 4);
n = n^(n >> 28);
n = n + (n << 31);
return n;
}
function unhash64(n:uint):uint
{
n = (~n) - (n >> 21);
n = n^(n << 24);
n = (n - (n >> 3)) - (n >> 8);
n = n^(n << 14);
n = (n - (n >> 2)) - (n >> 4);
n = n^(n << 28);
n = n - (n >> 31);
return n;
}
输出馈送1000时:
Hashed from 1000: 1221775646
Unhash output: 1963490760
答
第一个明显的问题是,它不是在时间镜像。那有时工作(如果操作的顺序并不重要),但通常y = f(g(x))
的倒数是x = g⁻¹(f⁻¹(y))
。 f最后被应用,所以它必须先被撤消。比较:如果你先穿上你的袜子,然后穿上你的鞋子,那么你应该先脱下你的鞋子然后脱下你的袜子。
此外,许多反向错误开始。例如,m = n^(n >> 24)
的倒数是n = m^(m >> 24)
,并且m = (n + (n << 2)) + (n << 4)
的倒数是n = m * 0x3cf3cf3d
(它是modular multiplicative inverse)。这并不像换档的方向那么简单。
没有测试,但这些都是以正确的顺序所有的倒数:
n = n * 0x80000001;
n = n^(n >> 28);
n = n * 0x3cf3cf3d;
n = n^(n >> 14)^(n >> 28);
n = n * 0x1c03dd39;
n = n^(n >> 24);
n = (n + 1) * 0xffdfffff;
答
哈希是不可逆的。如果您想要隐藏原始输入的可逆函数,请改为使用加密。只要您拥有正确的密钥,加密就被设计为可逆的。
已经有众所周知的密码和密钥生成技术。如果你试图设计自己的版本,那么他们将是不安全的。这并不重要,所有你想要做的就是把你的小弟弟藏起来。如果你在商业领域工作,那么你可能会被起诉,所以使用所有标准的现有安全方法。您可能需要研究像PBKDF2或argon2这样的密钥派生函数。
你期望什么? 1000? – Organis
是的,这是不可能的吗? – ZxZ
这就是密码学的重点,实际上:它不应该有可能从哈希中重新创建原始数据。否则,在过去的几年里,不是蛮力的,而是它。 – Organis