什么是哈希函数?

作者: 链闻ChainNews | 来源:发表于2018-05-14 14:15 被阅读47次

    哈希函数 Hash Function,也叫做「散列」、「杂凑」函数或者算法。理论上讲,哈希函数就是一种数学流程,将任意大小的输入数据放入该流程,然后返回固定大小的输出数据。把输入数据压缩成摘要,使得数据量变小,将数据的格式固定下来。

    更具体地讲,提取任意长度的字母序列作为输入(通常称为 string)进行杂糅、打乱混合,然后返回一个固定长度、格式的字母序列。无论这个输入 string 是单一字母、单词、句子还是整部小说,而输出的长度(叫做摘要 digest)永远相同。

    举个例子,给定一个输入 x,哈希函数会算出相应的输出 H(x)。其主要特征是:

    输入 x 可以是任意长度的字符串

    输出结果即 H(x) 的长度是固定的

    计算 H(x) 的过程是高效的(对于长度为 n 的字符串 x,计算出 H(x) 的时间复杂度应为 O(n)

    这种类型的哈希函数,常见用例就是存储密码。

    当你使用任何一种网络服务创建需要密码的帐号时,此类密码都是通过哈希函数运行的,所存储的就是该密码信息的哈希摘要。当你输入密码以登陆帐号时,相同的哈希函数会去运行你输入的密码,然后服务器就会检查其结果是否与存储的摘要相匹配。这意味着黑客即使能够访问用于存储哈希的数据库,因无法轻易找到生成某一特定哈希的密码,所以不可能立即破解。

    通过该函数创建的,叫做散列值(hash values、hash codes、hash sums 或 hashes)的指纹,通常用一个短的随机字母和数字组成的字符串表示。好的散列函数在输入域中很少出现散列冲突。在散列表和数据处理中,不抑制冲突来区别数据,会使得数据库记录更难找到。

    所说的固定长度,比如 128 位,依次进行 hash 运算,然后用不同的方法迭代即可(如前一块 hash 值与后一块 hash 值进行异或)。如 128 位不够,用 0 或者 1 补全随意,算法中约定即可。

    由于用途的不同,hash 在数据结构中的含义和密码学中的含义并不相同,所以在这两种不同的领域里,算法的设计侧重点也不同。

    预备小知识:

    1.抗碰撞能力:对于任意两个不同的数据块,其 hash 值相同的可能性极小;对于一个给定的数据块,找到和它 hash 值相同的数据块极为困难。

    2.抗篡改能力:对于一个数据块,哪怕只改动其一个比特位,其 hash 值的改动也会非常大。在用到 hash 进行管理的数据结构中,比如 hashmap,hash 值(key)存在的目的是加速键值对的查找,key 的作用是为了将元素适当地放在各个桶里,对于抗碰撞的要求没有那么高。换句话说,hash 出来的 key,只要保证 value 大致均匀的放在不同的桶里就可以了。但整个算法的 set 性能,直接与 hash 值产生的速度有关,所以这时候的 hash 值的产生速度就尤为重要,以 JDK 中的 String.hashCode() 方法为例:

    public int hashCode() {

            int h = hash;

        //hash default value : 0

            if (h == 0 && value.length > 0) {

        //value : char storage

                char val[] = value;

                for (int i = 0; i < value.length; i++) {

                    h = 31 * h + val[i];

                }

                hash = h;

            }

            return h;

        }

    很简洁的一个乘加迭代运算,在不少的 hash 算法中,使用的是异或 + 加法进行迭代,速度和前者差不多。在密码学中,hash 算法的作用主要是用于消息摘要和签名,换句话说,它主要用于对整个消息的完整性进行校验。在应用场景里,对于抗碰撞和抗篡改能力要求极高,对速度的要求在其次。一个设计良好的 hash 算法,其抗碰撞能力是很高的。以 MD5 为例,其输出长度为 128 位,而对于两个相似的字符串,MD5 加密结果如下:

    MD5("version1") = "966634ebf2fc135707d6753692bf4b1e";

    MD5("version2") = "2e0e95285f08a07dea17e7ee111b21c8";

    可以看到仅仅一个比特位的改变,二者的 MD5 值截然不同。

    到这里,你估计会问,有没有这样一个算法,使得对于任何一个给定的输入,此算法都会输出一个固定的均匀随机的输出?答案是密码学家们也至今没有构造出着这样一个算法,但倾向于这个算法存在,而且有不少的密码学算法构造和这个假设有关。这个假设叫做 Random Oracle 随机预言机。

    Python 简单哈希函数

    你可以使用 Python 编程语言,实验哈希值。

    首先,打开终端,输入 Python 并点击 Enter 键,进入 Python REPL,直接试用 Python 命令,而不是在单独的文件中编写程序。输入以下数值,在每行之后敲击 Enter 键,并在标记处输入 TAB 键:

    import  hashlib 

    def  hash(mystring):[TAB]hash_object=hashlib.md5(mystring.encode())[TAB]print(hash_object.hexdigest())

    [ENTER]

    这样你就创建了一个函数 hash(),该函数将计算出某一特定的使用 MD5 哈希算法的字符串的哈希值。将字符串插入上述的括号()中便可运行该函数。例如:

    hash(“ChainScoop rocks”)

    按下 Enter 并查看该字符串的哈希摘要。

    你将看到在同一字符串上调用该哈希函数将会总是生成相同的哈希,但添加或改变其中的某一个字符将会生成一种完全不同的哈希值:

    hash("ChainScoop rocks") => 7ae26e64679abd1e66cfe1e9b93a9e85

    hash("ChainScoop rocks!") => 6b1f6fde5ae60b2fe1bfe50677434c88


    文章来源:链闻ChainNews

    作者:liao

    相关文章

      网友评论

        本文标题:什么是哈希函数?

        本文链接:https://www.haomeiwen.com/subject/iyaddftx.html