我读过关于md5哈希的维基百科文章,但我仍然无法理解哈希怎么不能“重组”回到原始文本。
有人可以向对密码学知之甚少的人解释这是如何运作的吗?该功能的哪一部分使其单向?
答案 0 :(得分:49)
由于到目前为止每个人都只是简单地定义了哈希函数,我会咬人。
单向函数不仅仅是一个散列函数 - 一个丢失信息的函数 - 而是一个函数f
,给定一个图像y
(“SE”或现有的294)答案),很难找到一个前映像x,f(x)=y
。
这就是为什么它们被单向调用的原因:您可以计算图像,但无法找到给定图像的预图像。
直到现在在现有答案中提出的普通哈希函数都没有这个属性。它们都不是单向加密哈希函数。例如,给定“SE”,您可以轻松地选择输入“SXXXE”,这是一个具有X-encode(“SXXXE”)= SE属性的输入。
没有“简单”的单向函数。他们必须很好地混合他们的输入,不仅你不会在输出中识别输入,但是你也不会识别另一个输入。
SHA-1和MD5曾经是流行的单向函数,但它们几乎都被打破了(专家知道如何为给定的图像创建预图像,或者几乎能够这样做)。正在进行一项竞赛,以选择新的标准竞赛,其名称为SHA-3。
反转单向函数的一种显而易见的方法是计算许多图像并将它们保存在一个表中,该表将每个图像与产生它的前图像相关联。为了使这在实践中不可能,所有单向函数都有一个大输出,至少64位但可能更大(最多,比方说512位)。
编辑:大多数加密哈希函数如何工作?
通常它们的核心是一个函数,它对一个位块(block cipher)进行复杂的转换。该函数应该是近似双射的(它不应该将太多的序列映射到同一图像,因为这会导致后面的弱点)但它不一定是完全双射的。并且此函数迭代固定次数,足以使输入(或任何可能的输入)无法识别。
以Skein为例,它是SHA-3上下文的强有力候选者之一。其核心功能重复72次。函数的创建者知道如何有时将输出与某些输入相关联的唯一迭代次数是25.他们说它的“安全系数”为2.9。
答案 1 :(得分:43)
考虑一个非常基本的哈希 - 对于输入字符串,返回每个字符的ASCII值之和。
hash( 'abc' ) = ascii('a')+ascii('b')+ascii('c')
= 97 + 98 + 99
= 294
现在,给定哈希值294,你能说出原始字符串是什么吗?显然不是,因为'abc'和'cba'(和无数其他人)给出了相同的哈希值。
加密哈希函数的工作方式相同,但显然算法要复杂得多。总是会发生冲突,但是如果你知道s
的字符串h
哈希值,那么构造另一个字符串应该非常困难(“计算上不可行”)也是h
的哈希值。
答案 2 :(得分:31)
在这里拍摄一个简单的类比,而不是复杂的解释。
首先,让我们将主题分为两部分,单向操作和散列。什么是单向操作,为什么要一个?
调用单向操作,因为它们不可逆。加法和乘法等大多数典型操作都可以反转,而模除法不能反转。为什么这很重要?因为你想提供一个输出值,1)在没有原始输入的情况下很难复制,2)无法从输出中找出输入。
添加:
4 + 3 = 7
这可以通过取总和并减去其中一个加数来反转
7 - 3 = 4
<强>乘法强>:
4 * 5 = 20
这可以通过取出产品并除以其中一个因素来反转
20 / 4 = 5
模块划分:
22 % 7 = 1
这是不能逆转的,因为你没有可以对商进行操作而红利可以重构除数(反之亦然)。
你能找到一个填写“?”的操作吗?是什么?
1 ? 7 = 22
1 ? 22 = 7
话虽如此,单向散列函数具有与模除法相同的数学质量。
让我们说我给了你一个钥匙给一个有一千个储物柜的公共汽车总站的储物柜,并要求你把它交给我的银行家。作为一个聪明的人,更不用说可疑了,你会立即查看钥匙,看看钥匙上写有什么储物柜号码。知道了这一点,我做了一些狡猾的事情;首先,我发现两个数字,当使用模数除法给出一个数字在1到1000之间时,第二个我删除原始数字并在其上写上数字对的除数,第二个我选择了一个有一个数字的总线终端通过让人们每天用钥匙尝试一个储物柜来保护储物柜免受歹徒的伤害,第三,银行家已经知道了分红,所以当他拿到钥匙时,他可以做数学计算并找出剩余部分并知道打开哪个储物柜。
如果我明智地选择操作数,我可以接近商与被除数之间的一对一关系,迫使你尝试每个储物柜,因为答案将可能输入的结果扩展到所需数字的范围内,终端可用的储物柜。基本上,这意味着即使您知道其中一个操作数,也无法获得有关剩余部分的任何知识。
所以,现在我可以“信任”你将钥匙交给合法的主人而不用担心你可以轻易猜到它属于哪个储物柜。当然,您可以通过暴力搜索所有储物柜,但这需要将近3年的时间,我的银行家有足够的时间来使用钥匙并清空储物柜。
有关不同哈希函数的详细信息,请参阅其他答案。
答案 3 :(得分:10)
这是一个非常简单的例子。假设我是一个初学密码学家,我创建了一个哈希函数,它执行以下操作:
int SimpleHash(file) {
return 0 if file.length is even;
return 1 if file.length is odd;
}
现在是测试。 SimpleHash(specialFile)
是0. 我的原始文件是什么?
显然,没有办法知道(尽管你很可能很容易发现我的哈希基于文件长度)。没有办法根据哈希“重新构建”我的文件,因为哈希不包含我的文件所做的一切。
答案 4 :(得分:8)
哈希是一种(非常)有损编码。
为了给你一个更简单的例子,想象一个名为X编码的5个字母单词的虚构双字母编码。 X编码的算法很简单:取字的第一个和最后一个字母。
所以,
X-encode( SAUCE ) = SE
X-encode( BLOCK ) = BK
显然,您无法从其编码SE重建SAUCE(假设我们的可能输入范围是所有5个字母的单词)。这个词可以很容易地成为SPACE。
顺便说一句,SAUCE和SPACE都将SE作为编码产生的事实被称为 collision ,你可以看到X-ecoding不会产生非常好的哈希值。 :)
答案 5 :(得分:8)
答案 6 :(得分:3)
阵列
有些眯眼,关联数组看起来非常像哈希。主要区别在于哈希名称上缺少%符号,并且一次只能为它们分配一个键。因此,可以说$foo{'key'} = 1;
,但只有@keys = keys(foo);
。熟悉的函数,如每个,键和值都像现在一样工作(并在Perl 2中添加了删除)。
Perl 3有三种完整的数据类型:它在哈希名称上有%符号,允许一次分配整个哈希,并添加了dbmopen(现在不赞成使用tie)。 Perl 4使用逗号分隔的哈希键来模拟多维数组(现在可以使用数组引用更好地处理它们)。
Perl 5采用了将关联数组称为哈希的巨大飞跃。 (据我所知,它是第一种引用数据结构的语言,而不是“哈希表”或类似的东西。)有点讽刺的是,它还将相关代码从hash.c移到了hv.c.
命名法
如前所述,字典是由唯一键索引的无序值集合。它们有时被称为关联数组或映射。它们可以通过多种方式实现,其中一种方法是使用称为哈希表的数据结构(这就是Perl所称的哈希)。
Perl使用术语“hash”是一些潜在混淆的根源,因为散列函数的输出有时也称为散列(特别是在加密上下文中),并且因为散列表通常不称为哈希值其他
为安全起见,请将数据结构称为哈希表,并仅在明显的Perl特定上下文中使用术语“哈希”。