
Hash,一般翻译做"散列",也有直接音译为"哈希"的,就是把任意长度的输入(又叫做预映射, pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,而不可能从散列值来唯一的确定输入值。
数学表述为:h = H(M) ,其中H( )--单向散列函数,M--任意长度明文,h--固定长度散列值。
在信息安全领域中应用的Hash算法,还需要满足其他关键特性:
第一当然是单向性(one-way),从预映射,能够简单迅速的得到散列值,而在计算上不可能构造一个预映射,使其散列结果等于某个特定的散列值,即构造相应的M=H-1(h)不可行。这样,散列值就能在统计上唯一的表征输入值,因此,密码学上的 Hash 又被称为"消息摘要(message digest)",就是要求能方便的将"消息"进行"摘要",但在"摘要"中无法得到比"摘要"本身更多的关于"消息"的信息。
第二是抗冲突性(collision-resistant),即在统计上无法产生2个散列值相同的预映射。给定M,计算上无法找到M',满足H(M)=H(M') ,此谓弱抗冲突性;计算上也难以寻找一对任意的M和M',使满足H(M)=H(M') ,此谓强抗冲突性。要求"强抗冲突性"主要是为了防范所谓"生日攻击(birthday attack)",在一个10人的团体中,你能找到和你生日相同的人的概率是24%,而在同一团体中,有2人生日相同的概率是117%。类似的,当预映射的空间很大的情况下,算法必须有足够的强度来保证不能轻易找到"相同生日"的人。
第三是映射分布均匀性和差分分布均匀性,散列结果中,为 0 的 bit 和为 1 的 bit ,其总数应该大致相等;输入中一个 bit 的变化,散列结果中将有一半以上的 bit 改变,这又叫做"雪崩效应(avalanche effect)";要实现使散列结果中出现 1bit 的变化,则输入中至少有一半以上的 bit 必须发生变化。其实质是必须使输入中每一个 bit 的信息,尽量均匀的反映到输出的每一个 bit 上去;输出中的每一个 bit,都是输入中尽可能多 bit 的信息一起作用的结果。
Damgard 和 Merkle 定义了所谓"压缩函数(compression function)",就是将一个固定长度输入,变换成较短的固定长度的输出,这对密码学实践上 Hash 函数的设计产生了很大的影响。Hash函数就是被设计为基于通过特定压缩函数的不断重复"压缩"输入的分组和前一次压缩处理的结果的过程,直到整个消息都被压缩完毕,最后的输出作为整个消息的散列值。尽管还缺乏严格的证明,但绝大多数业界的研究者都同意,如果压缩函数是安全的,那么以上述形式散列任意长度的消息也将是安全的。这就是所谓 Damgard/Merkle 结构:
在下图中,任意长度的消息被分拆成符合压缩函数输入要求的分组,最后一个分组可能需要在末尾添上特定的填充字节,这些分组将被顺序处理,除了第一个消息分组将与散列初始化值一起作为压缩函数的输入外,当前分组将和前一个分组的压缩函数输出一起被作为这一次压缩的输入,而其输出又将被作为下一个分组压缩函数输入的一部分,直到最后一个压缩函数的输出,将被作为整个消息散列的结果。
MD5 和 SHA1 可以说是目前应用最广泛的Hash算法,而它们都是以 MD4 为基础设计的。
1) MD4
MD4(RFC 1320)是 MIT 的 Ronald L Rivest 在 1990 年设计的,MD 是 Message Digest 的缩写。它适用在32位字长的处理器上用高速软件实现--它是基于 32 位 *** 作数的位 *** 作来实现的。它的安全性不像RSA那样基于数学假设,尽管 Den Boer、Bosselaers 和 Dobbertin 很快就用分析和差分成功的攻击了它3轮变换中的 2 轮,证明了它并不像期望的那样安全,但它的整个算法并没有真正被破解过,Rivest 也很快进行了改进。
下面是一些MD4散列结果的例子:
MD4 ("") = 31d6cfe0d16ae931b73c59d7e0c089c0
MD4 ("a") = bde52cb31de33e46245e05fbdbd6fb24
MD4 ("abc") = a448017aaf21d8525fc10ae87aa6729d
MD4 ("message digest") = d9130a8164549fe818874806e1c7014b
MD4 ("abcdefghijklmnopqrstuvwxyz") = d79e1c308aa5bbcdeea8ed63df412da9
MD4 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") = 043f8582f241db351ce627e153e7f0e4
MD4 ("12345678901234567890123456789012345678901234567890123456789012345678901234567890") = e33b4ddc9c38f2199c3e7b164fcc0536
2) MD5
MD5(RFC 1321)是 Rivest 于1991年对MD4的改进版本。它对输入仍以512位分组,其输出是4个32位字的级联,与 MD4 相同。它较MD4所做的改进是:
1) 加入了第四轮
2) 每一步都有唯一的加法常数;
3) 第二轮中的G函数从((X ∧ Y) ∨ (X ∧ Z) ∨ (Y ∧ Z)) 变为 ((X ∧ Z) ∨ (Y ∧ ~Z))以减小其对称性;
4) 每一步都加入了前一步的结果,以加快"雪崩效应";
5) 改变了第2轮和第3轮中访问输入子分组的顺序,减小了形式的相似程度;
6) 近似优化了每轮的循环左移位移量,以期加快"雪崩效应",各轮的循环左移都不同。
尽管MD5比MD4来得复杂,并且速度较之要慢一点,但更安全,在抗分析和抗差分方面表现更好。
消息首先被拆成若干个512位的分组,其中最后512位一个分组是"消息尾+填充字节(1000)+64 位消息长度",以确保对于不同长度的消息,该分组不相同。64位消息长度的限制导致了MD5安全的输入长度必须小于264bit,因为大于64位的长度信息将被忽略。而4个32位寄存器字初始化为A=0x01234567,B=0x89abcdef,C=0xfedcba98,D=0x76543210,它们将始终参与运算并形成最终的散列结果。
接着各个512位消息分组以16个32位字的形式进入算法的主循环,512位消息分组的个数据决定了循环的次数。主循环有4轮,每轮分别用到了非线性函数
F(X, Y, Z) = (X ∧ Y) ∨ (~X ∧ Z)
G(X, Y, Z) = (X ∧ Z) ∨ (Y ∧ ~Z)
H(X, Y, Z) =X ⊕ Y ⊕ Z
I(X, Y, Z) = X ⊕ (Y ∨ ~Z)
这4轮变换是对进入主循环的512位消息分组的16个32位字分别进行如下 *** 作:将A、B、C、D的副本a、b、c、d中的3个经F、G、H、I运算后的结果与第4个相加,再加上32位字和一个32位字的加法常数,并将所得之值循环左移若干位,最后将所得结果加上a、b、c、d之一,并回送至ABCD,由此完成一次循环。
所用的加法常数由这样一张表T[i]来定义,其中i为164,T[i]是i的正弦绝对值之4294967296次方的整数部分,这样做是为了通过正弦函数和幂函数来进一步消除变换中的线性性。
当所有512位分组都运算完毕后,ABCD的级联将被输出为MD5散列的结果。下面是一些MD5散列结果的例子:
MD5 ("") = d41d8cd98f00b204e9800998ecf8427e
MD5 ("a") = 0cc175b9c0f1b6a831c399e269772661
MD5 ("abc") = 900150983cd24fb0d6963f7d28e17f72
MD5 ("message digest") = f96b697d7cb7938d525a2f31aaf161d0
MD5 ("abcdefghijklmnopqrstuvwxyz") = c3fcd3d76192e4007dfb496cca67e13b
MD5 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") = d174ab98d277d9f5a5611c2c9f419d9f
MD5 ("12345678901234567890123456789012345678901234567890123456789012345678901234567890") = 57edf4a22be3c955ac49da2e2107b67a
参考相应RFC文档可以得到MD4、MD5算法的详细描述和算法的C源代码。
3) SHA1 及其他
SHA1是由NIST NSA设计为同DSA一起使用的,访问http://wwwitlnistgov/fipspubs可以得到它的详细规范--[/url]"FIPS PUB 180-1 SECURE HASH STANDARD"。它对长度小于264的输入,产生长度为160bit的散列值,因此抗穷举(brute-force)性更好。SHA-1 设计时基于和MD4相同原理,并且模仿了该算法。因为它将产生160bit的散列值,因此它有5个参与运算的32位寄存器字,消息分组和填充方式与MD5相同,主循环也同样是4轮,但每轮进行20次 *** 作,非线性运算、移位和加法运算也与MD5类似,但非线性函数、加法常数和循环左移 *** 作的设计有一些区别,可以参考上面提到的规范来了解这些细节。下面是一些SHA1散列结果的例子:
SHA1 ("abc") = a9993e36 4706816a ba3e2571 7850c26c 9cd0d89d
SHA1 ("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq") = 84983e44 1c3bd26e baae4aa1 f95129e5 e54670f1
其他一些知名的Hash算法还有MD2、N-Hash、RIPE-MD、HAVAL等等。上面提到的这些都属于"纯"Hash算法。还有另2类Hash算法,一类就是基于对称分组算法的单向散列算法,典型的例子是基于DES的所谓Davies-Meyer算法,另外还有经IDEA改进的Davies-Meyer算法,它们两者目前都被认为是安全的算法。另一类是基于模运算/离散对数的,也就是基于公开密钥算法的,但因为其运算开销太大,而缺乏很好的应用前景。
没有通过分析和差分攻击考验的算法,大多都已经夭折在实验室里了,因此,如果目前流行的Hash算法能完全符合密码学意义上的单向性和抗冲突性,就保证了只有穷举,才是破坏Hash运算安全特性的唯一方法。为了对抗弱抗冲突性,我们可能要穷举个数和散列值空间长度一样大的输入,即尝试2^128或2^160个不同的输入,目前一台高档个人电脑可能需要10^25年才能完成这一艰巨的工作,即使是最高端的并行系统,这也不是在几千年里的干得完的事。而因为"生日攻击"有效的降低了需要穷举的空间,将其降低为大约122^64或122^80,所以,强抗冲突性是决定Hash算法安全性的关键。
在NIST新的 Advanced Encryption Standard (AES)中,使用了长度为128、192、256bit 的密钥,因此相应的设计了 SHA256、SHA384、SHA512,它们将提供更好的安全性。
Hash算法在信息安全方面的应用主要体现在以下的3个方面:
1) 文件校验
我们比较熟悉的校验算法有奇偶校验和CRC校验,这2种校验并没有抗数据篡改的能力,它们一定程度上能检测并纠正数据传输中的信道误码,但却不能防止对数据的恶意破坏。
MD5 Hash算法的"数字指纹"特性,使它成为目前应用最广泛的一种文件完整性校验和(Checksum)算法,不少Unix系统有提供计算md5 checksum的命令。它常被用在下面的2种情况下:
第一是文件传送后的校验,将得到的目标文件计算 md5 checksum,与源文件的md5 checksum 比对,由两者 md5 checksum 的一致性,可以从统计上保证2个文件的每一个码元也是完全相同的。这可以检验文件传输过程中是否出现错误,更重要的是可以保证文件在传输过程中未被恶意篡改。一个很典型的应用是ftp服务,用户可以用来保证多次断点续传,特别是从镜像站点下载的文件的正确性。
更出色的解决方法是所谓的代码签名,文件的提供者在提供文件的同时,提供对文件Hash值用自己的代码签名密钥进行数字签名的值,及自己的代码签名证书。文件的接受者不仅能验证文件的完整性,还可以依据自己对证书签发者和证书拥有者的信任程度,决定是否接受该文件。浏览器在下载运行插件和java小程序时,使用的就是这样的模式。
第二是用作保存二进制文件系统的数字指纹,以便检测文件系统是否未经允许的被修改。不少系统管理/系统安全软件都提供这一文件系统完整性评估的功能,在系统初始安装完毕后,建立对文件系统的基础校验和数据库,因为散列校验和的长度很小,它们可以方便的被存放在容量很小的存储介质上。此后,可以定期或根据需要,再次计算文件系统的校验和,一旦发现与原来保存的值有不匹配,说明该文件已经被非法修改,或者是被病毒感染,或者被木马程序替代。TripWire就提供了一个此类应用的典型例子。
更完美的方法是使用"MAC"。"MAC" 是一个与Hash密切相关的名词,即信息鉴权码(Message Authority Code)。它是与密钥相关的Hash值,必须拥有该密钥才能检验该Hash值。文件系统的数字指纹也许会被保存在不可信任的介质上,只对拥有该密钥者提供可鉴别性。并且在文件的数字指纹有可能需要被修改的情况下,只有密钥的拥有者可以计算出新的散列值,而企图破坏文件完整性者却不能得逞。
2) 数字签名
Hash 算法也是现代密码体系中的一个重要组成部分。由于非对称算法的运算速度较慢,所以在数字签名协议中,单向散列函数扮演了一个重要的角色。
在这种签名协议中,双方必须事先协商好双方都支持的Hash函数和签名算法。
签名方先对该数据文件进行计算其散列值,然后再对很短的散列值结果--如Md5是16个字节,SHA1是20字节,用非对称算法进行数字签名 *** 作。对方在验证签名时,也是先对该数据文件进行计算其散列值,然后再用非对称算法验证数字签名。
对 Hash 值,又称"数字摘要"进行数字签名,在统计上可以认为与对文件本身进行数字签名是等效的。而且这样的协议还有其他的优点:
首先,数据文件本身可以同它的散列值分开保存,签名验证也可以脱离数据文件本身的存在而进行。
再者,有些情况下签名密钥可能与解密密钥是同一个,也就是说,如果对一个数据文件签名,与对其进行非对称的解密 *** 作是相同的 *** 作,这是相当危险的,恶意的破坏者可能将一个试图骗你将其解密的文件,充当一个要求你签名的文件发送给你。因此,在对任何数据文件进行数字签名时,只有对其Hash值进行签名才是安全的。
3) 鉴权协议
如下的鉴权协议又被称作"挑战--认证模式:在传输信道是可被侦听,但不可被篡改的情况下,这是一种简单而安全的方法。
需要鉴权的一方,向将被鉴权的一方发送随机串("挑战"),被鉴权方将该随机串和自己的鉴权口令字一起进行 Hash 运算后,返还鉴权方,鉴权方将收到的Hash值与在己端用该随机串和对方的鉴权口令字进行 Hash 运算的结果相比较("认证"),如相同,则可在统计上认为对方拥有该口令字,即通过鉴权。
POP3协议中就有这一应用的典型例子:
S: +OK POP3 server ready <1896697170952@dbcmtviewcaus>
C: APOP mrose c4c9334bac560ecc979e58001b3e22fb
S: +OK maildrop has 1 message (369 octets)
在上面的一段POP3协议会话中,双方都共享的对称密钥(鉴权口令字)是tanstaaf,服务器发出的挑战是<1896697170952@dbcmtviewcaus>,客户端对挑战的应答是MD5("<1896697170952@dbcmtviewcaus>tanstaaf") = c4c9334bac560ecc979e58001b3e22fb,这个正确的应答使其通过了认证。
散列算法长期以来一直在计算机科学中大量应用,随着现代密码学的发展,单向散列函数已经成为信息安全领域中一个重要的结构模块,我们有理由深入研究其设计理论和应用方法。
哈希函数(Hash)自身具有三个特性:①可输入的字符串为任意大小;②产生固定大小(即存储规模)的输出,且这个大小可设定(随机数);③能进行有效计算。在比特币挖矿原理中,随机数是一个指定的解,基于某种率先加密的哈希函数具有单向性和隐秘性,既不能反向解出输入值也无法仅凭尝试找到输入值。此外,不同的输入产生不同的哈希函数,每次返回设定大小的位数形成信息摘要,极大地节省了网络存储规模。
Hash,一般翻译做“散列”,也有直接音译为“哈希”的,就是把任意长度的输入(又叫做预映射, pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,而不可能从散列值来唯一的确定输入值。简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数
散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。
[编辑本段]基本概念
若结构中存在关键字和K相等的记录,则必定在f(K)的存储位置上。由此,不需比较便可直接取得所查记录。称这个对应关系f为散列函数(Hash function),按这个思想建立的表为散列表。 对不同的关键字可能得到同一散列地址,即key1≠key2,而f(key1)=f(key2),这种现象称冲突。具有相同函数值的关键字对该散列函数来说称做同义词。综上所述,根据散列函数H(key)和处理冲突的方法将一组关键字映象到一个有限的连续的地址集(区间)上,并以关键字在地址集中的“象” 作为记录在表中的存储位置,这种表便称为散列表,这一映象过程称为散列造表或散列,所得的存储位置称散列地址。 若对于关键字集合中的任一个关键字,经散列函数映象到地址集合中任何一个地址的概率是相等的,则称此类散列函数为均匀散列函数(Uniform Hash function),这就是使关键字经过散列函数得到一个“随机的地址”,从而减少冲突。
[编辑本段]常用的构造散列函数的方法
散列函数能使对一个数据序列的访问过程更加迅速有效,通过散列函数,数据元素将被更快地定位ǐ 1 直接寻址法:取关键字或关键字的某个线性函数值为散列地址。即H(key)=key或H(key) = a•key + b,其中a和b为常数(这种散列函数叫做自身函数) 2 数字分析法 3 平方取中法 4 折叠法 5 随机数法 6 除留余数法:取关键字被某个不大于散列表表长m的数p除后所得的余数为散列地址。即 H(key) = key MOD p, p<=m。不仅可以对关键字直接取模,也可在折叠、平方取中等运算之后取模。对p的选择很重要,一般取素数或m,若p选的不好,容易产生同义词。
[编辑本段]处理冲突的方法
1 开放寻址法:Hi=(H(key) + di) MOD m, i=1,2,…, k(k<=m-1),其中H(key)为散列函数,m为散列表长,di为增量序列,可有下列三种取法: 1 di=1,2,3,…, m-1,称线性探测再散列; 2 di=1^2, (-1)^2, 2^2,(-2)^2, (3)^2, …, ±(k)^2,(k<=m/2)称二次探测再散列; 3 di=伪随机数序列,称伪随机探测再散列。 == 2 再散列法:Hi=RHi(key), i=1,2,…,k RHi均是不同的散列函数,即在同义词产生地址冲突时计算另一个散列函数地址,直到冲突不再发生,这种方法不易产生“聚集”,但增加了计算时间。 3 链地址法(拉链法) 4 建立一个公共溢出区
[编辑本段]查找的性能分析
散列表的查找过程基本上和造表过程相同。一些关键码可通过散列函数转换的地址直接找到,另一些关键码在散列函数得到的地址上产生了冲突,需要按处理冲突的方法进行查找。在介绍的三种处理冲突的方法中,产生冲突后的查找仍然是给定值与关键码进行比较的过程。所以,对散列表查找效率的量度,依然用平均查找长度来衡量。 查找过程中,关键码的比较次数,取决于产生冲突的多少,产生的冲突少,查找效率就高,产生的冲突多,查找效率就低。因此,影响产生冲突多少的因素,也就是影响查找效率的因素。影响产生冲突多少有以下三个因素: 1 散列函数是否均匀; 2 处理冲突的方法; 3 散列表的装填因子。 散列表的装填因子定义为:α= 填入表中的元素个数 / 散列表的长度 α是散列表装满程度的标志因子。由于表长是定值,α与“填入表中的元素个数”成正比,所以,α越大,填入表中的元素较多,产生冲突的可能性就越大;α越小,填入表中的元素较少,产生冲突的可能性就越小。 实际上,散列表的平均查找长度是装填因子α的函数,只是不同处理冲突的方法有不同的函数。 了解了hash基本定义,就不能不提到一些著名的hash算法,MD5 和 SHA-1 可以说是目前应用最广泛的Hash算法,而它们都是以 MD4 为基础设计的。那么他们都是什么意思呢 这里简单说一下: (1) MD4 MD4(RFC 1320)是 MIT 的 Ronald L Rivest 在 1990 年设计的,MD 是 Message Digest 的缩写。它适用在32位字长的处理器上用高速软件实现--它是基于 32 位 *** 作数的位 *** 作来实现的。 (2) MD5 MD5(RFC 1321)是 Rivest 于1991年对MD4的改进版本。它对输入仍以512位分组,其输出是4个32位字的级联,与 MD4 相同。MD5比MD4来得复杂,并且速度较之要慢一点,但更安全,在抗分析和抗差分方面表现更好 (3) SHA-1 及其他 SHA1是由NIST NSA设计为同DSA一起使用的,它对长度小于264的输入,产生长度为160bit的散列值,因此抗穷举(brute-force)性更好。SHA-1 设计时基于和MD4相同原理,并且模仿了该算法。 那么这些Hash算法到底有什么用呢 Hash算法在信息安全方面的应用主要体现在以下的3个方面: (1) 文件校验 我们比较熟悉的校验算法有奇偶校验和CRC校验,这2种校验并没有抗数据篡改的能力,它们一定程度上能检测并纠正数据传输中的信道误码,但却不能防止对数据的恶意破坏。 MD5 Hash算法的"数字指纹"特性,使它成为目前应用最广泛的一种文件完整性校验和(Checksum)算法,不少Unix系统有提供计算md5 checksum的命令。 (2) 数字签名 Hash 算法也是现代密码体系中的一个重要组成部分。由于非对称算法的运算速度较慢,所以在数字签名协议中,单向散列函数扮演了一个重要的角色。 对 Hash 值,又称"数字摘要"进行数字签名,在统计上可以认为与对文件本身进行数字签名是等效的。而且这样的协议还有其他的优点。 (3) 鉴权协议 如下的鉴权协议又被称作挑战--认证模式:在传输信道是可被侦听,但不可被篡改的情况下,这是一种简单而安全的方法。 MD5、SHA1的破解 2004年8月17日,在美国加州圣芭芭拉召开的国际密码大会上,山东大学王小云教授在国际会议上首次宣布了她及她的研究小组近年来的研究成果——对MD5、HAVAL-128、MD4和RIPEMD等四个著名密码算法的破译结果。 次年二月宣布破解SHA-1密码。
[编辑本段]实际应用
以上就是一些关于hash以及其相关的一些基本预备知识。那么在emule里面他具体起到什么作用呢 大家都知道emule是基于P2P (Peer-to-peer的缩写,指的是点对点的意思的软件), 它采用了"多源文件传输协议”(MFTP,the Multisource FileTransfer Protocol)。在协议中,定义了一系列传输、压缩和打包还有积分的标准,emule 对于每个文件都有md5-hash的算法设置,这使得该文件独一无二,并且在整个网络上都可以追踪得到。 什么是文件的hash值呢 MD5-Hash-文件的数字文摘通过Hash函数计算得到。不管文件长度如何,它的Hash函数计算结果是一个固定长度的数字。与加密算法不同,这一个Hash算法是一个不可逆的单向函数。采用安全性高的Hash算法,如MD5、SHA时,两个不同的文件几乎不可能得到相同的Hash结果。因此,一旦文件被修改,就可检测出来。 当我们的文件放到emule里面进行共享发布的时候,emule会根据hash算法自动生成这个文件的hash值,他就是这个文件唯一的身份标志,它包含了这个文件的基本信息,然后把它提交到所连接的服务器。当有他人想对这个文件提出下载请求的时候, 这个hash值可以让他人知道他正在下载的文件是不是就是他所想要的。尤其是在文件的其他属性被更改之后(如名称等)这个值就更显得重要。而且服务器还提供了,这个文件当前所在的用户的地址,端口等信息,这样emule就知道到哪里去下载了。 一般来讲我们要搜索一个文件,emule在得到了这个信息后,会向被添加的服务器发出请求,要求得到有相同hash值的文件。而服务器则返回持有这个文件的用户信息。这样我们的客户端就可以直接的和拥有那个文件的用户沟通,看看是不是可以从他那里下载所需的文件。 对于emule中文件的hash值是固定的,也是唯一的,它就相当于这个文件的信息摘要,无论这个文件在谁的机器上,他的hash值都是不变的,无论过了多长时间,这个值始终如一,当我们在进行文件的下载上传过程中,emule都是通过这个值来确定文件。 那么什么是userhash呢 道理同上,当我们在第一次使用emule的时候,emule会自动生成一个值,这个值也是唯一的,它是我们在emule世界里面的标志,只要你不卸载,不删除config,你的userhash值也就永远不变,积分制度就是通过这个值在起作用,emule里面的积分保存,身份识别,都是使用这个值,而和你的id和你的用户名无关,你随便怎么改这些东西,你的userhash值都是不变的,这也充分保证了公平性。其实他也是一个信息摘要,只不过保存的不是文件信息,而是我们每个人的信息。 那么什么是hash文件呢 我们经常在emule日志里面看到,emule正在hash文件,这里就是利用了hash算法的文件校验性这个功能了,文章前面已经说了一些这些功能,其实这部分是一个非常复杂的过程,目前在ftp,bt等软件里面都是用的这个基本原理,emule里面是采用文件分块传输,这样传输的每一块都要进行对比校验,如果错误则要进行重新下载,这期间这些相关信息写入met文件,直到整个任务完成,这个时候part文件进行重新命名,然后使用move命令,把它传送到incoming文件里面,然后met文件自动删除,所以我们有的时候会遇到hash文件失败,就是指的是met里面的信息出了错误不能够和part文件匹配,另外有的时候开机也要疯狂hash,有两种情况一种是你在第一次使用,这个时候要hash提取所有文件信息,还有一种情况就是上一次你非法关机,那么这个时候就是要进行排错校验了。 关于hash的算法研究,一直是信息科学里面的一个前沿,尤其在网络技术普及的今天,他的重要性越来越突出,其实我们每天在网上进行的信息交流安全验证,我们在使用的 *** 作系统密钥原理,里面都有它的身影,特别对于那些研究信息安全有兴趣的朋友,这更是一个打开信息世界的钥匙,他在hack世界里面也是一个研究的焦点。 一般的线性表、树中,记录在结构中的相对位置是随机的即和记录的关键字之间不存在确定的关系,在结构中查找记录时需进行一系列和关键字的比较。这一类查找方法建立在“比较”的基础上,查找的效率与比较次数密切相关。理想的情况是能直接找到需要的记录,因此必须在记录的存储位置和它的关键字之间建立一确定的对应关系f,使每个关键字和结构中一个唯一的存储位置相对应。因而查找时,只需根据这个对应关系f找到给定值K的像f(K)。若结构中存在关键字和K相等的记录,则必定在f(K)的存储位置上,由此不需要进行比较便可直接取得所查记录。在此,称这个对应关系f为哈希函数,按这个思想建立的表为哈希表(又称为杂凑法或散列表)。 哈希表不可避免冲突(collision)现象:对不同的关键字可能得到同一哈希地址 即key1≠key2,而hash(key1)=hash(key2)。具有相同函数值的关键字对该哈希函数来说称为同义词(synonym)。 因此,在建造哈希表时不仅要设定一个好的哈希函数,而且要设定一种处理冲突的方法。可如下描述哈希表:根据设定的哈希函数H(key)和所选中的处理冲突的方法,将一组关键字映象到一个有限的、地址连续的地址集(区间)上并以关键字在地址集中的“象”作为相应记录在表中的存储位置,这种表被称为哈希表。 对于动态查找表而言,1) 表长不确定;2)在设计查找表时,只知道关键字所属范围,而不知道确切的关键字。因此,一般情况需建立一个函数关系,以f(key)作为关键字为key的录在表中的位置,通常称这个函数f(key)为哈希函数。(注意:这个函数并不一定是数学函数) 哈希函数是一个映象,即:将关键字的集合映射到某个地址集合上,它的设置很灵活,只要这个地址集合的大小不超出允许范围即可。 现实中哈希函数是需要构造的,并且构造的好才能使用的好。 用途:加密,解决冲突问题。。。。 用途很广,比特精灵中就使用了哈希函数,你可 以自己看看。 具体可以学习一下数据结构和算法的书。
[编辑本段]字符串哈希函数
(著名的ELFhash算法) int ELFhash(char key) return h%MOD; }
——秘密的精华
在使用对称密码、公钥密码、消息认证码、数字签名等密码技术使用,都需要一个称为 密钥 的巨大数字。然而,数字本身的大小并不重要,重要的是 密钥空间的大小 ,也就是可能出现的密钥的总数量,因为密钥空间越大,进行暴力破解就越困难。密钥空间的大小是由 密钥长度 决定的。
对称密码DES的密钥的实质长度为56比特(7个字节)。
例如,
一个DES密钥用二进制可以表示为:
01010001 11101100 01001011 00010010 00111101 01000010 00000011
用十六进制则可以表示为:
51 EC 4B 12 3D 42 03
而用十进制则可以表示为:
2305928028626269955
在对称密码三重DES中,包括使用两个DES密钥的DES-EDE2和使用三个DES密钥的DES-EDE3这两种方式。
DES-EDE2的密钥长度实质长度为112比特(14字节),比如:
51 EC 4B 12 3D 42 03 30 04 D8 98 95 93 3F
DES-EDE3的密钥的实质长度为168比特(21字节),比如:
51 EC 4B 12 3D 42 03 30 04 D8 98 95 93 3F 24 9F 61 2A 2F D9 96
对称密码AES的密钥长度可以从128、192和256比特中进行选择,当密钥长度为256比特时,比如:
51 EC 4B 12 3D 42 03 30 04 D8 98 95 93 3F 24 9F 61 2A 2F D9 96
B9 42 DC FD A0 AE F4 5D 60 51 F1
密钥和明文是等价的 。假设明文具有100万的价值,那么用来加密这段明文的密钥也就是具有100万元的价值;如果明文值1亿元,密钥也就值1亿元;如果明文的内容是生死攸关的,那么密钥也同样是生死攸关的。
在对称密码中,加密和解密使用同一个密钥。由于发送者和接收者需要共享密钥,因此对称密码又称为共享密钥密码。对称密码中所使用的密钥必须对发送者和接收者以外的人保密,否则第三方就能够解密了。
在消息认证码中,发送者和接收者使用共享的密钥来进行认证。消息认证码只能由持有合法密钥的人计算出来。将消息认证码附加在通信报文后面,就可以识别通信内容是否被篡改或伪装,由于“持有合法的密钥”就是发送者和接收者合法身份的证明,因此消息认证码的密钥必须对发送者以外的人保密,否则就会产生篡改和伪装的风险。
在数字签名中,签名生成和验证使用不同的密钥,只有持有私钥的本人才能够生成签名,但由于验证签名使用的是公钥,因此任何人都能够验证签名。
对称密码和公钥密码的密钥都是用于确保机密性的密钥。如果不知道用于解密的合法密钥,就无法得知明文的内容。
相对地,消息认证码和数字签名所使用的密钥,则是用于认证的密钥。如果不知道合法的密钥,就无法篡改数据,也无法伪装本人的身份。
当我们访问以https://开头的网页时,Web服务器和浏览器之间会进行基于SSL/TLS的加密通信。在这样的通信中所使用的密钥是仅限于本次通信的一次密钥,下次通信时就不能使用了,想这样每次通信只能使用一次的密钥称为 会话密钥 。
由于会话密钥只在本次通信中有效,万一窃听者获取了本次通信的会话密钥,也只能破译本次通信的内容。
虽然每次通信都会更换会话密钥,但如果用来生成密钥的伪随机数生成器品质不好,窃听者就有可能预测出下次生成会话密钥,这样就会产生通信内容被破译的风险。
相对于每次通信更换的会话密钥,一直被重复使用的密钥称为 主密钥 。
一般来说,加密的对象是用户直接使用的信息,这样的情况下所使用的密钥称为CEK(Contents Encryting Key,内容加密密钥);相对地,用于加密密钥的密钥则称为KEK(Key Encryting Key,密钥加密密钥)。
在很多情况下,之前提到的会话密钥都是被作为CEK使用的,而主密钥则是被作为KEK使用的。
生成密钥的最好方法就是使用随机数,因为米哟啊需要具备不易被他人推测的性质。在可能的情况下最好使用能够生成密码学上的随机数的硬件设备,但一般我们都是使用伪随机数生成器这一专门为密码学用途设计的软件。
在生成密钥时,不能自己随便写出一些像“3F 23 52 28 E3”这样的数字。因为尽管你想生成的是随机的数字,但无论如何都无法避免人为偏差,而这就会成为攻击者的目标。
尽管生成伪随机数的算法有很多种,但密码学用途伪随机生成器必须是专门针对密码学用途而设计的。例如,有一些伪随机数生成器可以用于游戏和模拟算法,尽管这些伪随机数生成器所生成的数列看起也是随机的,但只要不是专门为密码学用途设计的,就不能用来生成密钥,因为这些伪随机数生成器不具备不可预测性这一性质。
有时候我们也会使用人类的可以记住的口令(pasword或passphrase)来生成密钥。口令指的是一种由多个单词组成的较长的password。
严格来说,我们很少直接使用口令来作为密钥使用,一般都是将口令输入单向散列函数,然后将得到的散列值作为密钥使用。
在使用口令生成密钥时,为了防止字典攻击,需要在口令上附加一串称为盐(salt)的随机数,然后在将其输入单向散列函数。这种方法称为“基于口令的密码(Password Based Encryption,PBE)”。
在使用对称密码时,如何在发送者和接收者之间共享密钥是一个重要的问题,要解决密钥配送问题,可以采用事先共享密钥,使用密钥分配中心,使用公钥密码等方法,除了上述方法,之前还提到一种解决密钥配送的问题的方法称为Diffie-Hellman密钥交换。
有一种提供通信机密性的技术称为 密钥更新 (key updating),这种方法就是在使用共享密钥进行通信的过程中,定期更改密钥。当然,发送者和接收者必须同时用同样的方法来改变密钥才行。
在更新密钥时,发送者和接收者使用单向散列函数计算当前密钥的散列值,并将这个散列值用作新的密钥。简单说,就是 用当前密钥散列值作为下一个密钥 。
我们假设在通信过程中的某个时间点上,密钥被窃听者获取了,那么窃听者就可以用这个密钥将之后的通信内容全部解密。但是,窃听者却无法解密更新密钥这个时间点之前的内容,因为这需要用单向散列函数的输出反算出单向散列函数的输入。由于单向散列函数具有单向性,因此就保证了这样的反算是非常困难的。
这种防止破译过去的通信内容机制,称为 后向安全 (backward security)。
由于会话密钥在通信过程中仅限于一次,因此我们不需要保存这种秘密。然而,当密钥需要重复使用时,就必须要考虑保存密钥的问题了。
人类是 无法记住具有实用长度的密钥 的。例如,像下面这样一个AES的128比特的密钥,一般人是很难记住的。
51 EC 4B 12 3D 42 03 30 04 DB 98 95 93 3F 24 9F
就算勉强记住了,也只过不是记住一个密钥而已。但如果要记住多个像这样的密钥并且保证不忘记,实际上是非常困难的。
我们记不住密钥,但如果将密钥保存下来又可能会被窃取。这真是一个头疼的问题。这个问题很难得到彻底解决,但我们可以考虑一些合理的解决方法。
将密钥保存生文件,并将这个文件保存在保险柜等安全地方。但是放在保险柜里的话,出门就无法使用了。这种情况,出门时就需要随身携带密钥。而如果将密钥放在存储卡随身携带的话,就会产生存储卡丢失、被盗等风险。
万一密钥被盗,为了能够让攻击者花更多的时间才能真正使用这个密钥,我们可以使用将密钥加密后保存的方法,当然,要将密钥加密,必须需要另一个密钥。像这样用于密码加密的密钥,一般称为KEK。
对密钥进行加密的方法虽然没有完全解决机密性的问题,但在现实中却是一个非常有效地方法,因为这样做可以减少需要保管密钥的数量。
假设计算机上有100万个文件,分别使用不同的密钥进行加密生成100万个密文,结果我们手上就产生了100万个密钥,而要保管100万个密钥是很困难的。
于是,我们用一个密钥(KEK)将这100万个密钥进行加密,那么现在我们只要保管者一个KEK就可以了,这一个KEK的价值相当于签名的100万个密钥的价值的总和。
用1个密钥来代替多个密钥进行保管的方法,和认证机构的层级化非常相似。在后者中,我们不需要信任多个认证机构,而只需要信任一个根CA就可以了。同样的,我们也不需要确保多个密钥的机密性,而只需要确保一个KEK的机密性就可以了。
密钥的作废和生成是同等重要的,这是因为密钥和明文是等价的。
假设Alice向Bob发送了一封加密邮件。Bob在解密之后阅读了邮件的内容,这时本次通信所使用的密钥对于Alice和Bob来说就不需要了。不在需要的密钥必须妥善删除,因为如果被窃听者Eve获取,之前发送的加密邮件就会被解密。
如果密钥是计算机上的一个文件,那么仅仅删除这个文件是不足以删除密钥的,因为有一些技术能够让删除的文件“恢复”。此外,很多情况下文件的内容还会残留在计算机的内存中,因此必须将这些痕迹完全抹去。简而言之,要完全删除密钥,不但要用到密码软件,还需要在设计计算机系统时对信息安全进行充分的考虑
如果包含密钥的文件被误删或者保管密钥的笔记本电脑损坏了,会怎么样?
如果丢失了对称密钥密码的共享密钥,就无法解密密文了。如果丢失了消息认证码的密钥,就无法向通信对象证明自己的身份了。
公钥密码中,一般不太会发送丢失公钥的情况,因为公钥是完全公开的,很有可能在其他电脑上存在副本。
最大的问题是丢失公钥密码的私钥。如果丢失了公钥密码的私钥,就无法解密用公钥密码加密的密文了。此外,如果丢失了数字签名的私钥,就无法生成数字签名了。
Diffie-Hellman密钥交换(Diffie-Hellman key exchange)是1976年由Whitfield Diffie和Martin Hellman共同发明的一种算法。使用这种算法,通信双方仅通过交换一些可以公开的信息就能够生成共享秘密数字,而这一秘密数字就可以被用作对称密码的密钥。IPsec 中就使用了经过改良的Diffie-Hellman密钥交换。
2 Alice 生成一个随机数A
A是一个1 ~ P-2之间的整数。这个数是一个只有Alice知道的密码数字,没有必要告诉Bob,也不能让Eve知道。
Alice计算出的密钥=Bob计算出的密钥
在步骤1-7中,双方交换数字一共有4个,P、G、G A mod P 和 G B mod P。根据这4个数字计算出Alice和Bob的共享密钥是非常困难的。
如果Eve能欧知道A和B的任意一个数,那么计算G AB 就很容易了,然而仅仅根据上面的4个数字很难求出A和B的。
根据G A mod P 计算出A的有效算法到现在还没有出现,这问题成为有限域(finite field) 的 离散对数问题 。
Diffie-Hellman密钥交换是利用了“离散对数问题”的复杂度来实现密钥的安全交换的,如果将“离散对数问题”改为“椭圆曲线上离散对数问题”,这样的算法就称为 椭圆曲线Diffie-Hellman 密钥交换。
椭圆曲线Diffie-Hellman密钥交换在总体流程上是不变的,只是所利用的数学问题不同而已。椭圆曲线Diffie-Hellman密钥交换能够用较短的密钥长度实现较高的安全性。
基于口令密码(password based encryption,PBE)就是一种根据口令生成密钥并用该密钥进行加密的方法。其中加密和解密使用同一个密钥。
PBE有很多种实现方法。例如RFC2898和RFC7292 等规范中所描述的PBE就通过Java的javaxcrypto包等进行了实现。此外,在通过密码软件PGP保存密钥时,也会使用PBE。
PBE的意义可以按照下面的逻辑来理解。
想确保重要消息的机制性。
↓
将消息直接保存到磁盘上的话,可能被别人看到。
↓
用密钥(CEK)对消息进行加密吧。
↓
但是这次又需要确保密钥(CEK)的机密性了。
↓
将密钥(CEK)直接保存在磁盘上好像很危险。
↓
用另一个密钥(KEK)对密钥进行加密(CEK)吧。
↓
等等!这次又需要确保密钥(KEK)的机密性了。进入死循环了。
↓
既然如此,那就用口令来生成密钥(KEK)吧。
↓
但只用口令容易遭到字典攻击
↓
那么就用口令和盐共同生成密钥(KEK)吧。
↓
盐可以和加密后的密钥(CEK)一切保存在磁盘上,而密钥(KEK)可以直接丢弃。
↓
口令就记在自己的脑子里吧。
PBE加密包括下列3个步骤:
盐是由伪随机数生成器生成的随机数,在生成密钥(KEK)时会和口令一起被输入单向散列函数。
密钥(KEK)是根据秘密的口令生成的,加盐好像没有什么意义,那么盐到底起到什么作用呢?
盐是用来防御字典攻击的 。字典攻击是一种事先进行计算并准备好候选密钥列表的方法。
我们假设在生成KEK的时候没有加盐。那么主动攻击者Mallory就可以根据字典数据事先生成大量的候选KEK。
在这里,事先是很重要的一点。这意味着Mallory可以在窃取到加密会话的密钥之前,就准备好了大量的候选KEK。当Mallory窃取加密的会话密钥后,就需要尝试将它解密,这是准备好了大量事先生成的候选KEK,就能够大幅度缩短尝试的时间,这就是 字典攻击 (dictionary attack)。
如果在生成KEK时加盐,则盐的长度越大,候选KEK的数量也会随之增大,事先生成的的候选KEK就会变得非常困难。只要Mallory还没有得到盐,就无法生成候选KEK。这是因为加盐之后,候选KEK的数量会变得非常巨大。
具有充足长度的密钥是无法用人脑记忆的。口令也是一样,我们也无法记住具有充足比特数的口令。
在PBE中,我们通过口令生成密钥(KEK),在用这个密钥来加密会话密钥(CEK)。由于通过口令生成的密钥(KEK)强度不如由伪随机数生成器生成的会话密钥(CEK),这就好像是将一个牢固的保险柜的钥匙放在了一个不怎么牢固的保险柜保管,因此在使用基于口令的密钥时,需要将盐和加密后的CEK通过物理方法进行保护。例如将盐和加密后的CEK保存到存储卡随身携带。
在生成KEK时,通过多次使用单向散列函数就可以提高安全性。例如,将盐和口令输入单向散列函数,进行1000次的散列函数所得到的散列值作为KEK来使用,是一个不错的方法。
像这样将单向散列函数进行多次迭代的方法称为 拉伸 (stretching)。
该系列的主要内容来自《图解密码技术第三版》
我只是知识的搬运工
文章中的插图来源于原著
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)