zoukankan      html  css  js  c++  java
  • hash是什么?

      最近读关于php内核的资料,发现php中 在实现变量以及数据类型的实现中大量使用哈希算法,并且非常细致做出了很多优秀的细节设计。比如:在 zend.hash.h 中

    static inline ulong zend_inline_hash_func(char *arKey, uint nKeyLength)
    {
        register ulong hash = 5381;
     
        /* variant with the hash unrolled eight times */
        for (; nKeyLength >= 8; nKeyLength -= 8) {
            hash = ((hash << 5) + hash) + *arKey++;
            hash = ((hash << 5) + hash) + *arKey++;
            hash = ((hash << 5) + hash) + *arKey++;
            hash = ((hash << 5) + hash) + *arKey++;
            hash = ((hash << 5) + hash) + *arKey++;
            hash = ((hash << 5) + hash) + *arKey++;
            hash = ((hash << 5) + hash) + *arKey++;
            hash = ((hash << 5) + hash) + *arKey++;
        }
        switch (nKeyLength) {
            case 7: hash = ((hash << 5) + hash) + *arKey++; /* fallthrough... */
            case 6: hash = ((hash << 5) + hash) + *arKey++; /* fallthrough... */
            case 5: hash = ((hash << 5) + hash) + *arKey++; /* fallthrough... */
            case 4: hash = ((hash << 5) + hash) + *arKey++; /* fallthrough... */
            case 3: hash = ((hash << 5) + hash) + *arKey++; /* fallthrough... */
            case 2: hash = ((hash << 5) + hash) + *arKey++; /* fallthrough... */
            case 1: hash = ((hash << 5) + hash) + *arKey++; break;
            case 0: break;
    EMPTY_SWITCH_DEFAULT_CASE()
        }
        return hash;
    }

    相比较常用的 times 33 算法,会快一些了;

    (相对web开发角度而言,我用自己的话来概括下 哈希)哈希是一种做法的总称,这种做法指的就是 将一个字串(也可以说是数据)进行杂糅,得出一个定长的另一个字串(也可以说另一个数据),然后我们就可以用省的字串来 代替原来的字串了,就有指纹验证的特征了。

        目前已经有算法去实现这种做法了,比如:md5,sha1等等,使用算法去达到 不可逆,不重复的目的,当然这不是绝对的,只是很小很小概率上不重复不可逆,换句话说,就是目前你穷尽你所有的计算资源以及时间去也很难去逆转。

       我认为hash算法是 很美妙的工具,他让数据在传输过程中真正有了保密性,而且好多web开发的校验过程都有使用它,下面来一段比较专业术语来描述吧,


    抗碰撞能力:对于任意两个不同的数据块,其hash值相同的可能性极小;对于一个给定的数据块,找到和它hash值相同的数据块极为困难。
    抗篡改能力:对于一个数据块,哪怕只改动其一个比特位,其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算法生成一个密码的签名,知乎后台只保存这个签名值。由于hash算法是不可逆的,那么黑客即便得到这个签名,也丝毫没有用处;而如果你在网站登陆界面上输入你的密码,那么知乎后台就会重新计算一下这个hash值,与网站中储存的原hash值进行比对,如果相同,证明你拥有这个账户的密码,那么就会允许你登陆。银行也是如此,银行是万万不敢保存用户密码的原文的,只会保存密码的hash值而而已。

    哈希算法并不是一个特定的算法而是一类算法的统称。哈希算法也叫散列算法,一般来说满足这样的关系:f(data)=key,输入任意长度的data数据,经过哈希算法处理后输出一个定长的数据key。同时这个过程是不可逆的,无法由key逆推出data。

    如果是一个data数据集,经过哈希算法处理后得到key的数据集,然后将keys与原始数据进行一一映射就得到了一个哈希表。一般来说哈希表M符合M[key]=data这种形式。
    哈希表的好处是当原始数据较大时,我们可以用哈希算法处理得到定长的哈希值key,那么这个key相对原始数据要小得多。我们就可以用这个较小的数据集来做索引,达到快速查找的目的。

    稍微想一下就可以发现,既然输入数据不定长,而输出的哈希值却是固定长度的,这意味着哈希值是一个有限集合,而输入数据则可以是无穷多个。那么建立一对一关系明显是不现实的。所以"碰撞"(不同的输入数据对应了相同的哈希值)是必然会发生的,所以一个成熟的哈希算法会有较好的抗冲突性。同时在实现哈希表的结构时也要考虑到哈希冲突的问题。

    密码上常用的MD5,SHA都是哈希算法,因为key的长度(相对大家的密码来说)较大所以碰撞空间较大,有比较好的抗碰撞性,所以常常用作密码校验。

  • 相关阅读:
    11.6八校联考T1,T2题解
    NOIP2014解方程
    luogu P2107 小Z的AK计划
    差分及树上差分学习笔记
    Noip2015提高组解题报告
    日常个人训练计划
    dij 费用流
    哈尔滨站总结
    SOSdp
    2018-2019 ACM-ICPC Southeastern European Regional Programming Contest (SEERC 2018)
  • 原文地址:https://www.cnblogs.com/guixiaoming/p/7805025.html
Copyright © 2011-2022 走看看