精华内容
下载资源
问答
  • 哈希函数的三个特征
    千次阅读
    2020-07-06 22:57:28

    哈希函数的特征

    Prerequisite: Hashing data structure

    先决条件: 哈希数据结构

    The hash function is the component of hashing that maps the keys to some location in the hash table. As part of the hashing technique, we need a hash function to map the available keys to the set of indexes in the hash table. Say we have a set of keys ranging from [-1000, 1000] and have a hash table of size 10, index ranging from [0, 10].

    哈希函数是哈希的组件,它将密钥映射到哈希表中的某个位置。 作为哈希技术的一部分,我们需要一个哈希函数将可用键映射到哈希表中的索引集。 假设我们有一组范围从[-1000,1000]的键,并且有一个大小为10的哈希表,索引范围是[0,10]。

    That's why to map the keys we need hash functions. A hash function is termed as the perfect hash function is what is able to map the keys to unique locations. But unfortunately, there is no systematic way to generate hash function as the size of the key list is very large considered to hash table size.

    这就是为什么要映射我们需要哈希函数的键的原因。 哈希函数被称为完美哈希函数,它是能够将密钥映射到唯一位置的函数。 但是遗憾的是,由于键列表的大小对于哈希表的大小而言非常大,因此没有系统的方法来生成哈希函数。

    A popular hash function is a folding method where we fold the integers and sum the partitions and then take mod 10 finally.

    流行的哈希函数是一种折叠方法 ,其中我们折叠整数并将分区求和,然后最终取mod 10。

    For example,

    例如,

    The hash function for the folding method is = 
        sum of the fold of size two %10
    Say we have integer 60784567
    So sum will be 60 + 78 + 45 + 67 = 250
    So final location is 250 % 10 = 0
    
    

    The below program computes the above folding method which is an example of the hash function.

    下面的程序将计算上述折叠方法 ,该方法哈希函数的一个示例。

    #include <bits/stdc++.h>
    using namespace std;
    
    //folding method
    
    int main()
    {
        string s;
      
        cout << "enter number\n";
        cin >> s;
    
        //folding and summing
        int sum = 0;
        for (int i = 0; i < s.length(); i += 2) {
            if (i + 1 < s.length())
                sum += stoi(s.substr(i, 2));
            else
                //when only one digit is left for folding
                sum += stoi(s.substr(i, 1));
        }
    
        cout << s << "->" << sum % 10;
    
        return 0;
    }
    
    

    Output:

    输出:

    enter number
    60784567
    60784567->0
    
    

    Now if some other number also finds location 0, then it's called collision.

    现在,如果其他一些数字也找到位置0,则称为碰撞

    Characteristics of good hash function

    哈希函数良好的特征

    1. Minimum collision

      最小碰撞

    2. High gain factor (distributes keys evenly). Like say we have 10 locations in the hash table, then almost 9 locations should have keys. It should not be the case that 4-5 locations have keys only where the keys collided.

      高增益因子(均匀分布密钥)。 像说在哈希表中有10个位置,那么几乎9个位置应该有键。 并非4-5个位置仅在按键碰撞的地方具有按键。

    3. Have a high load factor. Load factor means the number of keys stored/hash table size

      负载系数高。 负载因子是指存储的密钥数/哈希表大小

    4. Easy to compute

      易于计算

    Exercises on hash function

    哈希函数练习

    Use the below hash function to compute the hashing and comment on the goodness of the hash function.

    使用下面的哈希函数来计算哈希并评论哈希函数的优缺点。

    1) F(key) = number of digits of key

    1)F(key)=密钥位数

    #include <bits/stdc++.h>
    using namespace std;
    
    //hash function 1
    int main()
    {
        string s;
        cout << "enter number\n";
        cin >> s;
    
        //f(s)=no of digit in s=length of s
        cout << s << "->" << s.length();
    
        return 0;
    }
    
    

    Output:

    输出:

    enter number
    123452
    123452->6
    
    

    The above hash function is not good at all. Say we have set of keys all having the same digits, then all the keys will collide and the rest of the locations will remain empty.

    上面的哈希函数根本不好。 假设我们有一组键都具有相同的数字,那么所有键将发生冲突,其余位置将保持为空。

    2) F(key) = (rand()*key) % 10

    2)F(键)=(rand()*键)%10

    #include <bits/stdc++.h>
    using namespace std;
    
    //hash function 2
    int main()
    {
        int n;
        cout << "enter number\n";
        cin >> n;
    
        //f(n)=rand()*n
        cout << n << "->" << (rand() * n) % 10;
    
        return 0;
    }
    
    

    Output:

    输出:

    enter number
    103456
    103456->2
    
    

    The above hash function is good as we are multiplying random integers and bringing randomness, the collision rate will be less.

    上面的哈希函数很好,因为我们要乘以随机整数并带来随机性,则冲突率会更低。

    Comparison of the above hash functions:

    上面的哈希函数比较:

    #include <bits/stdc++.h>
    using namespace std;
    
    //comparing goodness of hash function 1 &  2
    int main()
    {
    
        //set of input numbers
        vector<int> arr{ 12345, 234245, 1223123, 765845, 345234, 234534, 98675, 34523, 123, 3245 };
    
        //using hash function 1
        cout << "using hash function 1\n";
        for (int a : arr) {
            cout << a << "->" << to_string(a).length() % 10 << endl;
        }
    
        //using hash function 2
        cout << "\n\nusing hashh function 2\n";
        for (int a : arr) {
            cout << a << "->" << (rand() * a) % 10 << endl;
        }
    
        return 0;
    }
    
    

    Output:

    输出:

    using hash function 1
    12345->5
    234245->6
    1223123->7
    765845->6
    345234->6
    234534->6
    98675->5
    34523->5
    123->3
    3245->4
    
    
    using hashh function 2
    12345->9
    234245->4
    1223123->3
    765845->-1
    345234->-4
    234534->4
    98675->6
    34523->0
    123->5
    3245->-9
    
    
    

    翻译自: https://www.includehelp.com/data-structure-tutorial/hash-functions-and-its-characteristics.aspx

    哈希函数的特征

    更多相关内容
  • 正在学习区块链,如果我哪里有错误希望大家指出,如果有任何想法也欢迎留言。这些笔记本身是在typora上写的,如果有显示不正确的敬请谅解...比特币用的哈希函数是SHA-256。  一共有三点,其中前两点都很简单,于算法而
  • 认识哈希函数

    千次阅读 2019-06-20 12:35:54
    哈希函数的输入域可以是非常大的范围,比如,一字符串,但是它的输出域是固定的范围。并具有以下性质: 典型的哈希函数都有无限的输入值域。 当给哈希函数传入相同的输入值时,返回值一样。 当给哈希函数传入...

    首先,先来介绍一下哈希函数的概念。哈希函数的输入域可以是非常大的范围,比如,一个字符串,但是它的输出域是固定的范围。并具有以下性质:

    1. 典型的哈希函数都有无限的输入值域。
    2. 当给哈希函数传入相同的输入值时,返回值一样。
    3. 当给哈希函数传入不同的输入值时,返回值可能一样,也可能不一样,这是当然的,因为输出域是固定的范围,所以会有不同的输入值对应在输出域的一个元素上,这就涉及到了哈希碰撞的问题。
    4. 最重要的性质是很多不同的输入值所得到的返回值会均匀的分布在输出域上。

    第1~3点性质是哈希函数的基础,第4点性质是评价一个哈希函数优劣的关键,不同输入值所得到的所有返回值越均匀分布与输入值出现的规律无关。

    哈希函数的构造方法

    1)直接定址法:

    取关键字或关键字的某个线性函数值为哈希地址:H(key) = key 或 H(key) = a·key + b
    其中a和b为常数,这种哈希函数叫做自身函数。

    注意:由于直接定址所得地址集合和关键字集合的大小相同。因此,对于不同的关键字不会发生冲突。但实际中能使用这种哈希函数的情况很少。

    2)相乘取整法:

    首先用关键字key乘上某个常数A(0 < A < 1),并抽取出key.A的小数部分;然后用m乘以该小数后取整。

    注意:该方法最大的优点是m的选取比除余法要求更低。比如,完全可选择它是2的整数次幂。虽然该方法对任何A的值都适用,但对某些值效果会更好。Knuth建议选取 0.61803……。

    3)平方取中法:

    取关键字平方后的中间几位为哈希地址。

    通过平方扩大差别,另外中间几位与乘数的每一位相关,由此产生的散列地址较为均匀。这是一种较常用的构造哈希函数的方法。

    将一组关键字(0100,0110,1010,1001,0111) 
    平方后得(0010000,0012100,1020100,1002001,0012321) 
    若取表长为1000,则可取中间的三位数作为散列地址集:(100,121,201,020,123)。
    

    4)除留余数法:

    取关键字被数p除后所得余数为哈希地址:H(key) = key MOD p (p ≤ m)。

    注意:这是一种最简单,也最常用的构造哈希函数的方法。它不仅可以对关键字直接取模(MOD),也可在折迭、平方取中等运算之后取模。值得注意的是,在使用除留余数法时,对p的选择很重要。一般情况下可以选p为质数或不包含小于20的质因素的合数。

    5)随机数法:

    选择一个随机函数,取关键字的随机函数值为它的哈希地址,即 H(key) = random (key),其中random为随机函数。通常,当关键字长度不等时采用此法构造哈希函数较恰当。

    哈希冲突解决方法

    1)开放定址法:

    就是在发生冲突后,通过某种探测技术,去依次探查其他单元,直到探查到不冲突为止,将元素添加进去。

    假如是在index的位置发生哈希冲突,那么通常有一下几种探测方式:

    • 线性探测法(线性探测再散列)
      向后依次探测index+1,index+2…位置,看是否冲突,直到不冲突为止,将元素添加进去。

    • 平方探测法
      不探测index的后一个位置,而是探测2^i 位置 ,比如探测2^0 位置上时发生冲突,接着探测2^1位置,依此类推,直至冲突解决。

    注意:

    (1)用开放定址法建立散列表时,建表前须将表中所有单元(更严格地说,是指单元中存储的关键字)
    置空。
    (2)两种探测方法的优缺点。
         线性探测法虽然在哈希表未满的情况下,总能保证找到不冲突的地址,但是容易发生二次哈希冲
         突的现象。比如在处理若干次次哈希冲突后k,k+1,k+2位置上的都存储了数据,那下一次存储地
         址在k,k+1,k+2,k+3位置的数据都将存在k+3位置上,这就产生了二次冲突。
         这里引入一个新的概念,堆积现象是指用线性探测法处理哈希冲突时,k,k+1,k+2位置已存有数
         据,下一个数据请求地址如果是k,k+1,k+2,k+3的话,那么这四个数据都会要求填入k+3的位置。
         
         平方探测法可以减少堆积现象的发生,但是前提是哈希表的总容量要是素数4n+3才可以。
    

    2)链地址法(开散列法)

    基本思想:

    链表法就是在发生冲突的地址处,挂一个单向链表,然后所有在该位置冲突的数据,都插入这个链表中。插入数据的方式有多种,可以从链表的尾部向头部依次插入数据,也可以从头部向尾部依次插入数据,也可以依据某种规则在链表的中间插入数据,总之保证链表中的数据的有序性。Java的HashMap类就是采取链表法的处理方案。

    例:已知一组关键字为(19,14,23,01,68,20,84,27,55,11,10,79),则按哈希函数 H(key) = key MOD13 和链地址法处理冲突构造所得的哈希表为:
    在这里插入图片描述

    3)再哈希法:(双散列法)

    在发生哈希冲突后,使用另外一个哈希算法产生一个新的地址,直到不发生冲突为止。这个应该很好理解。

    再哈希法可以有效的避免堆积现象,但是缺点是不能增加了计算时间和哈希算法的数量,而且不能保证在哈希表未满的情况下,总能找到不冲突的地址。

    4)建立一个公共溢出区:

    建立一个基本表,基本表的大小等于哈希表的大小。建立一个溢出表,所有哈希地址的第一个记录都存在基本表中,所有发生冲突的数据,不管哈希算法得到的地址是什么,都放入溢出表中。

    但是有一个缺点就是,必须事先知道哈希表的可能大小,而且溢出表里的数据不能太多,否则影响溢出表的查询效率。实际上就是要尽量减少冲突。

    参考链接:https://blog.csdn.net/m0_37925202/article/details/82015731

    展开全文
  • 只是一自行车棚。 安装 npm install hash.js 用法 var hash = require ( 'hash.js' ) hash . sha256 ( ) . update ( 'abc' ) . digest ( 'hex' ) 选择性哈希用法 var sha512 = require ( 'hash.js/lib/hash/sha/...
  • 1. 哈希表就是数组+哈希函数,其核心思想是利用数组可以按照下标索引随机访问数据的特性。 2. 哈希冲突的原因:数组的有界,哈希函数的计算,哈希值的映射。 3. 解决哈希冲突的方法:数组扩容,设计优秀的哈希函数,...

    一、什么是哈希表

    哈希表就是数组+哈希函数,其核心思想是利用数组可以按照下标索引随机访问数据的特性。

    举个栗子:一个班级有50个人,每个人都有学号,按自然数顺序编号,学号1是小明,学号2是小红,学号3是小强,以此类推。在这个栗子中一个班级就是一个数组容器,学号就是数组的下标,学生就是数组中的元素,通过学号找人就是利用数组下标随机访问元素的特性。而如何给学生编号就是哈希函数的事情了。

    在这里插入图片描述

    二、哈希函数

    哈希函数,顾名思义,是一个函数,表达式:hash(key),key就是与数组下标不相干的关键词,而哈希函数计算的值就是与数组下标建立联系,可以直接作为数组下标,也可以将哈希值做取模等运算得到数组下标。

    刚才学号的栗子就是hash(自然数)=自然数,计算得到的哈希值可以直接用作数组下标,而深入到哈希表的实际应用,往往计算出的哈希值会很大,将其直接作为数组下标的话会使数组的长度很长,浪费内存。所以在有限的数组中通过哈希函数映射下标,势必会造成哈希冲突。

    三、哈希冲突的原因与解决方法

    产生哈希冲突的原因不仅仅是因为数组的有界,还包括哈希函数的计算以及对哈希值的映射都会产生哈希冲突。

    解决哈希冲突的方式也是根据这三个原因对症下药:

    1. 数组有界就适当扩容。
    2. 设计优秀的哈希算法。
    3. 开放寻址法和链表法为哈希值找到合适的映射。

    1、数组扩容

    数组中空闲的位置越多,一定程度上哈希冲突也会越小。但是不能因为这个原因就把数组的长度设置的很长,而是设置一个合理的初始长度,后面再慢慢扩容。

    什么时候扩容?扩容多少?都是有考究的。扩容太少导致频繁扩容影响性能,扩容太多浪费内存。一般经验所得,当元素个数占数组长度的3/4时扩容,扩容后的长度是原来的两倍。这也是java中HashMap的扩容思想,但是还是需要根据实际情况做调整。

    什么时候扩容有一个名词,装载因子,代表元素个数占数组长度的比例:装载因子=元素个数/数组长度。装载因子的设置要权衡时间和空间复杂度,装载因子太大,哈希冲突越严重,装载因子太小,内存浪费严重。

    如果内存空间不紧张,对执行效率要求很高,可以降低装载因子的阈值;相反,如果内存空间紧张,对执行效率要求又不高,可以增加装载因子的大小,甚至可以大于 1(对于链表法冲突解决)。

    对于单纯的数组扩容,数据的迁移很简单,对应位置复制过去即可,但是哈希表的扩容迁移就比较复杂,哈希表的长度变了,元素的位置也变了,需要一个个重新计算哈希映射新位置。扩容的时间复杂度是O(n),简单的插入一个数据的时间复杂度是O(1),如果刚好碰上扩容,时间复杂度就是O(n)。
    在这里插入图片描述

    扩容在一定程度上影响插入数据的性能,所以要避免无效的扩容,除了设计合理的装载因子和扩容比例,还可以从扩容的过程中优化:

    (1)扩容动作摊分到每个插入操作中,新数据插入新数组中,插入数据的同时复制一个旧数组中的一个元素到新数组,这样每次插入操作的时间复杂度都是O(1),但是需要兼容维护新旧数组,查找和删除操作先到旧数组查找,没有再到新数组查找。(jdk1.8 ConcurrentHashMap多线程扩容思想)

    (2)对于链表法解决冲突构成的哈希表,迁移时可以链表为单位复制,无需所有元素重新计算哈希值。(ConcurrentHashMap扩容以链表为单位整体迁移复制)

    2、一个优秀的哈希函数

    一个不合理的哈希函数,会使得数组扩容功亏一篑。若计算的哈希值本身很容易冲突,或者映射到数组下标不均匀分布,再多的空闲位置也没用。这就要求一个优秀的哈希函数必须具有以下2个要素:

    • 哈希值尽量随机且均匀分布,这样不仅可以最小化哈希冲突,而且即使出现了冲突,也会平均在各个位置,有利于冲突的解决改善(开放寻址法和链表法)。
    • 哈希算法的计算性能要高,不能影响哈希表的正常操作。

    数组扩容和优秀的哈希函数仍然无法避免哈希冲突,还可以从哈希值映射上下手,常用的方法有开放寻址法和链表法。

    3、开放寻址法

    开放寻址法,就是当发生哈希冲突时,重新找到空闲的位置,然后插入元素。寻址方式有多种,常用的有线性寻址、二次方寻址、双重哈希寻址:

    • 线性寻址,当需要插入元素的位置被占用时,顺序向后寻址,如果到数组最后也没找到一个空闲位置,则从数组开头寻址,直到找到一个空闲位置插入数据。线性寻址的每次寻址步长是1,寻址公式hash(key)+n(n是寻址的次数)。
    • 二次方寻址,就是线性寻址的总步长的二次方,即hash(key)+n^2
    • 双重哈希寻址,顾名思义就是多次哈希直到找到一个不冲突的哈希值。
      在这里插入图片描述

    采用开放寻址法解决哈希冲突,又该如何查找元素和删除元素呢?

    查找元素的过程和插入元素类似,用相同的寻址方式,寻址的同时比对key或者value是否相等,相等则认为元素存在,不相等则继续寻址,如果探测到空闲位置依然没有找到则认为该元素不存在

    删除有些特别,不能单纯的把要删除的元素设置为空,因为在查找元素的过程中探测到的空闲位置是删除元素的位置,就会使得查找元素的寻址算法失效,本来存在的元素误判定为不存在。该如何解决这个问题呢?

    只需要删除元素不是物理删除而是逻辑删除。给删除的元素做上delete标记,当查询元素寻址时遇到delete标记的位置时不会停下来而是继续向后探测,但是在插入元素寻址遇到delete标记的位置就会把应该删除的元素替换掉。

    三种寻址方式都有着明显的不足:

    • 线性寻址,寻址的性能虽然元素个数的增多逐步下降,最坏时间复杂度是O(n)。
    • 二次方寻址,寻址的次数比线性寻址较低了,但是会因为步长是二次方,所以需要较长的数组长度,内存利用率可能较低。
    • 双重哈希寻址,多次哈希可能会浪费时间,需要优质的哈希函数做支撑。

    而整个开放寻址法的不足也很明显:

    • 插入、查找、删除都需要寻址。
    • 数组中元素越多,空闲位置越少,哈希冲突越剧烈。所以装载因子不能太大,要及时扩容减小冲突,但是数组内存利用率较低。

    看似开放寻址法有挺多问题,但是也有一些优点:

    • 数据都存储在数组中,可以有效地利用 CPU 缓存加快查询速度。
    • 而且,这种方法实现的哈希表,序列化也简单,不像链表还要考虑指针。

    总结而得,当数据量比较小、装载因子小的时候,适合采用开放寻址法。这也是 Java 中ThreadLocal内部类ThreadLocalMap使用开放寻址法解决散列冲突的原因。

    4、链表法

    链表法相对于开放寻址法实现起来简单一些,在数组内存利用率上比开放寻址法高,同时对装载因子的忍耐度也相对较高。开放寻址法的装载因子只能小于1,越趋近于1,冲突越剧烈,寻址过程越耗时,而链表法的装载因子可以大于1(但是内存不紧张,在意性能的一般不会装载因子不会大于1)。

    链表法就是将产生哈希冲突的元素链接成一个链表,每个链表可以设想成一个桶(bucket)或者槽(slot):

    • 插入元素就是通过哈希找到对应的桶,然后插入到链表中,时间复杂度为O(1);
    • 查找元素也是通过哈希找到对应的桶,然后遍历链表;
    • 删除元素同样通过哈希找到对应的桶,遍历链表找到需要删除的元素删除。

    当哈希比较均匀时,理论上查询和删除的时间复杂度为O(n/m),n是数组中元素的个数,m是数组中桶的个数。但是当哈希冲突非常严重时,数据都集中在一个桶里,数组退化成链表,查找和删除的时间复杂度为趋近与O(n)。
    在这里插入图片描述

    针对数组退化成链表或者链表过长导致的性能下降,可以在合适的时机将链表转换为红黑树,极端情况下数组退化成一个红黑树,时间复杂度也是O(logn),比O(n)强多了。(jdk8中ConcurrentHashMap对于jdk7有所优化,当链表节点的个数大于8个且数组的长度大于64时,链表转换为红黑树;当红黑树的节点小于8个时又退化为链表。)

    可以容忍的缺点:

    • 因为链表节点需要存放指针,所以内存占用上比开放寻址法高。
    • 链表中的节点在内存中是不连续分布的,所以对CPU缓存的利用率也不高,序列化也比开放寻址法复杂。

    优点:

    • 内存利用率较高。
    • 优化策略灵活,红黑树和链表可以互相转换。

    四、总结

    哈希表的两个核心哈希函数的设计与哈希冲突的解决。

    1. 哈希表就是数组+哈希函数,其核心思想是利用数组可以按照下标索引随机访问数据的特性。
    2. 哈希冲突的原因:数组的有界,哈希函数的计算,哈希值的映射。
    3. 解决哈希冲突的方法:数组扩容,设计优秀的哈希函数,开放寻址法和链表法为哈希值找到合适的映射。
    4. 开放寻址法,插入、查找、删除都需要相同的寻址逻辑,所以时间复杂度一样。数组中元素越多,空闲位置越少,哈希冲突越剧烈。
    5. 链表法需要注意,当哈希冲突非常严重时,数组会退化成链表,查找和删除的时间复杂度趋近于O(n),可以采用红黑树进行优化。

    参考:极客时间专栏《数据结构与算法之美》。

    PS: 如若文章中有错误理解,欢迎批评指正,同时非常期待你的评论、点赞和收藏。我是徐同学,愿与你共同进步!

    展开全文
  • 区块链与哈希函数

    2022-07-19 22:03:48
    (另外一工作是RSA算法) 这种结构在几乎所有的哈希函数中使用,具体做法为: 把所有消息M分成一些固定长度的 块Yi; 最后一块padding并使其包含消息 M的长度; 设定初始值CV0; 循环执行压缩函数f,CVi=f(CVi - 1||...

    目录

    哈希函数

    定义

    性质

    发展

    常见攻击方法

    1.穷举攻击

    2.生日攻击

    3.其他攻击

    构造方法

    1.利用对称密码体制来设计哈希函数

    2.直接设计哈希函数

    ​编辑

    常用哈希函数简介

    1.SHA-256算法

    ​编辑

    2.Keccak算法

    3.SM3算法

    哈希函数在区块链中的应用

    1.以太坊用户地址的生成

    2.默克尔哈希树

    3. 挖矿难度的设置

    4. 数字签名

    5. 软件发布


    哈希函数

    定义

    哈希函数:是一公开函数。用于将任意长的消息M映射为较短的、固定长度的值H(M),又称为散列函数、杂凑函数。我们称函数值H(M)为哈希值、杂凑值、杂凑码、信息摘要。

    杂凑值是信息中所有比特的函数,因此提供了一种错误检测能力,即改变信息中任何一个比特或几个比特都会使杂凑值改变

    性质

    前三条实用性要求,后三条安全性要求

    • H 可以作用于任意一个长度的数据块(实际上不是任意的,比如SHA-1要求不超过2^64)
    • H 产生一个固定长度的输出(比如SHA-1的输出是160比特,SHA-256的输出是256比特)
    • 对任意给定的x,H(x)计算相对容易,无论是软件还是硬件实现
    • 单向性(抗原像)(one-way):对于任意给定的消息,计算其哈希值容易。但是,对于给定的哈希值H,要找到M使得H(M)=H在计算上是不可行的。即给定消息可以产生一个哈希值,而给定哈希值不可能产生对应的消息;否则, 设传送数据 C =< M,H(M||K)>,K是密钥。攻击者可以截获C,求出哈希函数的逆,从而得出H^-1(C),然后从M 和M‖K即可得出K
    • 弱抗碰撞(抗二次原像)(Weakly Collision-Free):对于给定的消息x,要发现另一个消息y,满足H(x)=H(y)在计算上是不可行的。是保证一个给定的消息的哈希值不能找到与之相同的另外的消息,即防止伪造。否则,攻击者可以劫获报文M及其哈希值H(M),并找出另一报文M',使得H(M)=H(M')。这样攻击者可以用M'去冒充M。
    • 强抗碰撞(Strongly Collision-Free):找任意一对不同的消息x、y,使H(x)=H(y)在计算上是不可行的。是对已知的生日攻击方法的防御能力,强抗碰撞自然包含弱抗碰撞。(?)

     图:哈希函数强碰撞性示意图

    发展

     

     图:哈希函数结构示意图

    • 1978年,Merkle和Damagad设计MD迭代结构
    • 1993年,来学嘉和Messay改进加强MD结构;
    • 在90年代初 MIT Laboratory for Computer Science和RSA数据安全公司的Rivest设计了散列算法MD族,MD代表消息摘要.
    • MD族中的MD2、MD4和MD5都产生一个 128位的信息摘要
    • MD2(1989年)
    • MD4(1990年)
    • MD5(1991年):由美国密码学家罗纳德ꞏ李维斯特(Ronald Linn Rivest)设计,经MD2、MD3和 MD4发展而来,输出的是128位固定长度的字符串.
    • RIPEMD-128/160/320:国际著名密码学家Hans Dobbertin的在1996年攻破了MD4算法的同时, 也对MD5的安全性产生了质疑,从而促使他设计了一个类MD5的RIPEMD-160. 在结构上, RIPEMD-160可以视为两个并行的类MD5算法,这使得RIPEMD-160的安全性大大提高.
    • 值得注意得是,MD4, MD5已经在2004年8月Crypto2004 上,被我国密码学者王小云等破 译,即在有效的时间内找到了它们的大量碰撞

    • SHA-0:正式称作为SHA,这个版本在发行后不久被指出存在弱点
    • SHA-1:是NIS于1994年发布的,它于MD4与MD5算法非常相似,被认为是MD4和MD5的后继者
    • SHA-2:实际上分为SHA-224、SHA-256、SHA384、SHA-512算法

     图:SHA系列哈希函数相关参数比较

    图:哈希函数碰撞攻击复杂度示意图(单位:年)

    常见攻击方法

    1.穷举攻击

    (a)原像攻击和第二原像攻击(Preimage or Second Preimage attack)

    • 对于给定的哈希值h,试图找到满足H(x)=h的x
    • 对于m位的哈希值,穷举规模大约是2^m

    (b)碰撞攻击(Collision Resistance)

    • 找到两个信息x不等于y,满足H(x) = H(y)
    • 对于m位的哈希值,平均预计在2^m/2次尝试后就找到两个具有相同哈希值的数据

    (c)因此对于m位的哈希值,抗穷举攻击的强度为2^m/2:

    • 目前128比特已经不够,需要160比特甚至更多

    2.生日攻击

    情景:考虑教室有30位同学,定义函数 H: {张三,李四,ꞏꞏꞏꞏꞏꞏ|在教室里的同学}→{1,2, ꞏꞏꞏꞏꞏꞏ,365}, 如果有两个同学的生日相同,则称为一个“碰撞”. 直观看来,产生碰撞的可能性较小. 但是, 对于30个人的人群,这个事情发生的可能性大约为1/2.当人数增加时,这个可能性就增大. 这 个事实与我们的直观相悖, 称为”生日悖论”.

    生日悖论是指在不少于 23 个人中至少有两人生日相同的概率大于 50%。例如在一个 30 人的小学班级中,存在两人生日相同的概率为 70%。对于 60 人的大班,这种概率要大于 99%。从引起逻辑矛盾的角度来说,生日悖论是一种 “佯谬”。但这个数学事实十分反直觉,故称之为一个悖论。生日悖论的数学理论被应用于设计密码学攻击方法——生日攻击

    生日悖论普遍的应用于检测哈希函数:N 位长度的哈希表可能发生碰撞测试次数不是 2N 次而是只有 2N/2 次。这一结论被应用到破解密码哈希函数 (cryptographic hash function) 的 “生日攻击” 中。 

    总结:对于n位的哈希值,只要尝试2^n/2次,就至少存在一对x和x',使得H(x)和H(x')相同

    3.其他攻击

    • 利用算法的某种特性进行攻击
    • 哈希函数的迭代结构:将消息分组后分别进行处理
    • 密码分析的攻击集中于压缩函数 f 的碰撞

    构造方法

    1.利用对称密码体制来设计哈希函数

    分组密码的工作模式是:根据不同的数据格式和安全性要求, 以一个具体的分组密码算 法为基础构造一个分组密码系统的方法.基于分组的对称密码算法比如DES/AES算法只是描述 如何根据秘钥对一段固定长度(分组块)的数据进行加密,对于比较长的数据,分组密码工作模 式描述了如何重复应用某种算法安全地转换大于块的数据量.

    简单的说就是,DES/AES算法描述怎么加密一个数据块,分组密码工作模式描述了如果 重复加密比较长的多个数据块. 常见的分组密码工作模式有五种:电码本( Electronic Code Book, ECB)模式、密文分组链接(Cipher Block Chaining,CBC)模式、密文反馈(Cipher Feed Back , CFB)模式、输出反馈(Output Feed Back ,OFB)模式和计数器(Counter, CTR)模式

    (1)ECB工作模式

    加密:输入的是当前明文分组

    解密:每一个密文分组分别解密

    公式:C_n = E_k[P_n]P_n = D_k[C_n]

     (2)CBC工作模式

    加密:输入是当前铭文分组和前一次密文分组的异或

    解密:每一个密文分组被解密后,再与前一个密文分组异或得明文

    公式:

     

     (3)CFB工作模式

    •  加密算法的输入是64比特移位寄存器,其 初值为某个初始向量IV.
    • 加密算法输出的最左(最高有效位)j比特与 明文的第一个单元P1进行异或,产生出密 文的第1个单元C1,并传送该单元.
    • 然后将移位寄存器的内容左移j位并将C1送 入移位寄存器最右边(最低有效位)j位.
    • 这一过程继续到明文的所有单元都被加密 为止.

     

     (4)OFB工作模式

    • 工作模式类似CFB
    • 不同:OFB模式是将加密算法的输出反馈到移位寄存器;CFB模式中是将密文单元反馈到移位寄存器

     (5)CTR工作模式

    加密:输入是当前明文分组和计数器密文分组的异或

    解密:每一个密文分组被解密后,再与计数器密文分组异或得到明文

    公式:

     

    5种工作模式的比较 

    • ECB模式,简单、高速,但最弱、易受重发攻击,一般不推荐.
    • CBC模式适用于文件加密,比ECB模式慢.安全性加强. 当有少量错误时,不会造成同步错误.
    • OFB模式和CFB模式较CBC模式慢许多. 每次迭代只有少数比特完成加密. 若可以容忍少量错 误扩展,则可换来恢复同步能力,此时用CFB或OFB模式. 在字符为单元的流密码中多选 CFB模式.
    • CTR模式用于高速同步系统,不容忍差错传播.

    下面利用对称密码来构造哈希函数,我们规定:

    1.1基于分组密码的CBC工作模式杂凑函数

    1.2基于分组密码的CFB工作模式杂凑函数

     

     总结:上述两种基于分组密码的杂凑函数中,K可以公开,称为不带密钥的哈希函数;k也可以不公开,称为带密钥的哈希函数(MAC)。在K公开的情况下,上述两种构造杂凑函数的方法是不安全的,容易找到碰撞。这是为什么呢?

    2.直接设计哈希函数

    • Merkle在1989年提出迭代型哈希函数的一般结构;(另外一个工作是默克尔哈希树)
    • Ron Rivest在1990年利用这种结构提出MD4;(另外一个工作是RSA算法)
    • 这种结构在几乎所有的哈希函数中使用,具体做法为:
      • 把所有消息M分成一些固定长度的 块Yi;
      • 最后一块padding并使其包含消息 M的长度;
      • 设定初始值CV0;
      • 循环执行压缩函数f,CVi=f(CVi - 1||Yi -1);
      • 最后一个CVi为哈希值

    •  算法中重复使用一个压缩函数f ;
    • f 的输入有两项,一项是上一轮输出的n比特值CVi-1,称为链接变量,另一项是算法在本轮 的b比特输入分组Yi-1 ;
    • f 的输出为n比特值CVi,CVi又作为下一轮的输入;
    • 算法开始时还需对链接变量指定一个初值IV,最后一轮输出的链接变量CVL即为最终产生的 杂凑值;
    • 通常有b>n,因此称函数f为压缩函数.
    • 算法可表达如下:CV0=IV= n比特长的初值;
    • CVi=f(CVi-1,Yi-1);1≤i≤L;
    • H(M)=CVL
    • 算法的核心技术是设计难以找到碰撞的压缩函数f,而敌手对算法的攻击重点是f 的内部结构;
    • f 和分组密码一样是由若干轮处理过程组成;
    • 对f 的分析需要找出f 的碰撞.由于f 是压缩函数,其碰撞是不可避免的,因此在设计f 时就应 保证找出其碰撞在计算上是困难的

    常用哈希函数简介

    1.SHA-256算法

    概况

    • SHA系列标准哈希函数是由美国标准与技术研究所(National Institute of Standards and Technology,NIST)组织制定的.
    • 1993年公布了SHA-0 (FIPS PUB 180),后发现不安全.
    • 1995年又公布了SHA-1(FIPS PUB 180--1).
    • 2002年又公布了SHA-2( FIPS PUB 180--2),包括 3种算法:SHA-256, SHA-384, SHA-512.
    • 2005年王小云院士给出一种攻击SHA-1的方法,用 2^69操作找到一个强碰撞,以前认为是 2^80.
    • 2017 年 2 月23日,谷歌宣布找到SHA-1碰撞的算法,需要耗费110 块GPU一年的运算量

    图:SHA系列哈希函数的参数比较

    注意:所有的长度以比特为单位;安全性是指对输出长度为n比特哈希函数的生日攻击产生碰撞的工作量大约为2^n/2

     算法描述

    • 输入数据长度为k比特,1 <= k <= (2^64) -1
    • 输出哈希值的长度为256比特

    (1)常量与函数:SHA-256算法使用以下常数与函数:

    ①常量 初始值IV = 0x6a09e667 bb67ae85 3c6ef372 a54ff53a 510e527f 9b05688c 1f83d9ab 5be0cd19,这 些初值是对自然数中前 8个质数(2,3,5,7,11,13,17,19)的平方根的小数部分取前32比特而来.

    举个例子来说, 2小数部分约为0.414213562373095048,而0.414213562373095048 ≈ 6 ∗16−1 +a ∗16−2+0 ∗16−3 +9 ∗16−4 +...于是,质数 2 的平方根的小数部分取前32比特就对应出0x6a09e667. 另外,SHA-256还用到了64个常数: K0, K1, …, K63 =

    和 8个初始值类似,这些常量是对自然数中前64个质数(2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97…) 的立方根的小数部分取前32比特而来

     ②函数 SHA-256用到了以下函数:

     其中: ∧表示按位“与”; ¬ 表示按位“补”;⊕表示按位“异或”; ROTR i (x )表示循环右移 i比特; SHR i (x )表示右移 i比特;

    (2) 算法描述 ①填充

    • 对数据填充的目的是使填充后的数据长度为512的整数倍.因为迭代压缩是对512位数据块进 行的,如果数据的长度不是512的整数倍,最后一块数据将是短块,这将无法处理.
    • 设消息 m长度为 l比特.首先将比特“1”添加到 m的末尾,再添加 k个“0”,其中, k是满足下式 的最小非负整数 l +1+ k = 448 mod 512
    • 然后再添加一个64位比特串,该比特串是长度 l的二进制表示.填充后的消息 m 的比特长度一 定为512的倍数.

    以信息“abc”为例显示补位的过程.a, b, c对应的ASCII码分别是97, 98, 99;于是原始信息 的二进制编码为:01100001 01100010 01100011.

    ① 补一个“1” : 0110000101100010 01100011 1

    ② 补423个“0”:01100001 01100010 01100011 10000000 00000000 … 00000000

    ③ 补比特长度24 (64位表示 ),得到512比特的数据:

     

     ②消息分块 将填充后的消息 m′按512比特分成 n组: m′= M(0)||M(1)|| ꞏ ꞏ ꞏ || M(n-1),其中: n = ( l+ k+65)/512.

     ③消息扩展

    • 对一个消息分组M(t) 迭代压缩之前,首先进行消息扩展
      •  将16个字的消息分组 M t 扩展生成如下的64个字,供压缩函数使用 W0,W1,…,W63;
      •  消息扩展把原消息位打乱,隐蔽原消息位之间的关联,增强了安全性;
    • 消息扩展的步骤如下:

     ④压缩函数

    • 压缩函数是SHA-256的核心
    • 令 a, b, c, d, e, f, g, h为字寄存器, T1, T2为中间变量.
    • 压缩函数: V(t+1)= CF( V(t) ,M(t)), 0 ≤ t ≤ n -1.
    • 压缩函数CF的压缩处理:内层迭代
      • ① FOR t = 0 TO 63
      • ② CF= F( T1 , T2 , a, b, c, d, e, f, g, h,M(t) )
      • ③ END FOR

     图:SHA-256算法的压缩函数工作流程示意图

    ⑤基本压缩函数

    基本压缩函数的流程如右边公式所述.

    说明:

    • a, b, c, d, e, f, g, h为字寄存器, T1, T2为中间 变量;
    • +运算为mod 232 算术加运算;
    • 字的存储为大端(big-endian)格式.即,左边为 高有效位,右边为低有效位

     下图是SHA-256算法的基本压缩函数示意图

     ⑥SHA-256工作全过程

     安全性

    • 专业机构设计,经过充分测试和论证;
    • 安全性可满足应用的安全需求;
    • 学者已开展对SHA-256的安全分析 (如缩减轮的分析 ),尚未发现本质的缺陷

    程序设计

    • typedef.h:定义数据类型;
    • sha256.h:定义SHA-256算法相 关功能函数、数据接口声明;
    • sha256.c:实现SHA-256算法相 关功能函数;
    • sha256_test.h:定义测试函数、 数据接口声明;
    • Sha256_test.c:实现测试功能函 数;
    • main.c:实现main函数,测试程 序的正确性、性能等.

    2.Keccak算法

    概况

    • 能够直接替代SHA-2.这要求SHA--3必须也能够产生224,256,384,512比特的哈希值.
    • 保持SHA-2的在线处理能力. 这要求SHA-33必须能处理小的数据块 ( 如512 或1024比特).
    • 安全性:能够抵抗原像和碰撞攻击的能力,能够抵抗已有的或潜在的对于SHA-2的攻击.
    • 效率:可在各种硬件平台上的实现,且是高效的和存储节省的.
    • 灵活性:可设置可选参数以提供安全性与效率折中的选择,便于并行计算等
    • 2008 年10 月有64 个算法正式向NIST提交了方案,经过初步评价,共有51个算法进入第 一轮评估,主要对算法的安全性、消耗、和实现特点等进行分析;
    • 2009 年 7 月24日宣布,其中14个算法通过第一轮评审进入第二轮;
    • 2010 年12 月 9日宣布,其中 5个算法(JH、Grstl、Blake、Keccak 和Skein)通过第二轮评审进 入第三轮.
    • 2012 年10 月 2 日NIST公布了最终的优胜者.它就是由意法半导体公司 的Guido Bertoai Bertoai、 Jean Daemen Daemen、Gilles Van Assche Assche 与恩智半导体公司 的Micha Michaëël Peeters 联合设计的Keccak算法.
    • SHA-3成为NIST的新哈希函数标准算法(FIPS PUB 180--5).
    • Keccak算法的分析与实现详见:https://keccak.team/index.html
    • SHA-3的结构仍属于Merkle提出的迭代型哈希函数结构.
    • 最大的创新点是采用了一种被称为海绵结构的新的迭代结构. 海绵结构又称为海绵函数.
    • 在海绵函数中,输入数据被分为固定长度的数据分组.每个分组逐次作为迭代的输入,同时 上轮迭代的输出也反馈至下轮的迭代中,最终产生输出哈希值.
    • 海绵函数允许输入长度和输出长度都可变,具有灵活的性.
    • 海绵函数能够用于设计哈希函数 (固定输出长度 )、伪随机数发生器,以及其他密码函数.

    Keccak算法描述

    • 输入数据没有长度限制;
    • 输出哈希值的比特长度分为:224,256,384,512.

    (1) 符号与函数 Keccak算法使用以下符号与函数:

    ①符号

    • r:比特率 (比特 rate),其值为每个输入块的长度.
    • c:容量(capacity),其长度为输出长度的两倍.
    • b:向量的长度, b = r + c,而 b的值依赖于指数 I,即 b=25 * 2^l

    图:Keccak算法的参数定义 

    ②函数 Keccak算法用到了以下 5个函数: θ(theta)、ρ(rho)、π(pi)、χ(chi)、ι(iota)

     (2) 算法描述

    Keccak算法 对数据进行填充,然后迭代压缩生成哈希值.

    ①填充

    对数据填充的目的是使填充后的数据长度为 r的整数倍.因为迭代压缩是对 r位数据块进行 的,如果数据的长度不是 r的整数倍,最后一块数据将是短块,这将无法处理.

    • 设消息 m长度为 l比特.首先将比特“1”添加到 m的末尾,再添加 k个“0”,其中, k是满足下式 的最小非负整数: l +1+ k = r-1 mod r ;
    • 然后再添加比特“1”添加到末尾. 填充后的消息 m 的比特长度一定为 r的倍数

    以算法Keccak-256,信息“abc”为例显示补位的过程. a, b, c对应的ASCII码分别是97, 98, 99;于是原始信息的二进制编码为:01100001 01100010 01100011.此时 r = 1088.

    • 补一个“1” : 0110000101100010 01100011 1
    • 补1062个“0”:01100001 01100010 01100011 10000000 00000000 … 00000000
    • 补一个“1” ,得到1088比特的数据

    ②整体描述

    Keccak算法采用海绵结构(Sponge Construction),在预处理(padding并分成大小相同的块 ) 后,海绵结构主要分成两部分:

    • 吸入阶段(Absorbing Phase):将块 xi传入算法并处理.
    • 挤出阶段(Squeezing Phase):产生一个固定长度的输出.

    Keccak算法的整体运算结构如下图

     ③吸入与挤出阶段

    给定输入串 x ,首先对 x 做padding,使其长度能被 r整除,将padding后分割成长度为 r的块, 即 x =x 0|| x1|| x 2||...|| xt-1 .然后执行以下吸入阶段和挤出阶段:

    1. 初始化一个长度为 r + c 比特的全零向量.
    2. 输入块 xi,将 xi和向量的前 r个比特做异或运算,然后输入到 f 函数中处理.
    3. 重复上一步,直至处理完 x中的每个块.
    4. 输出长为 r的块作为y 0,并将向量输入到 f 函数中处理,输出 y1,以此类推.得到的哈希序列 即为y = y 0 || y1|| y 2 ||...|| y u .在Keccak-224/256/384/512中,只需要在y 0中取出 前224/ 256/ 384/ 512位即可

    图:Kecca算法的吸入阶段和挤出阶段示意图

     ④压缩函数

    • 压缩函数 f 是Keccak算法的核心,它包含 nr轮.
    • nr的取值与我们之前计算 b时用到的指数 I ( b=25 * 25^l)有关, 具体地, nr =12+2* I.Keccak-224/256/384/512中,取 I=6, 因此 nr =24.
    • 在每一轮中,要以此执行五步,即 θ(theta)、ρ(rho)、π(pi)、 χ(chi)、ι(iota).
    • 在处理过程中,我们把 b=1600个比特排列成一个5*5* w 的三维数组,其中 w=2^I=64比特,如图所示:

    图:Kecca算法的三维数组示意图 

    图:Kecca算法的压缩函数结构示意图

    (3) 安全性与性能

    • 安全性
      • 可以抵御对哈希函数的所有现有攻击.
      • 到目前为止,没有发现它有严重的安全弱点.
    • 灵活性:可选参数配置,能够适应哈希函数的各种应用.
    • 高效性:设计简单,软硬件实现方便.在效率方面,它是高效的.
    • 尚未广泛应用,需要经过实践检验

    3.SM3算法

    概况

    • SM3是我国商用密码管理局颁布的商用密码哈希函数
    • 用途广泛:
      • 商用密码应用中的辅助数字签名和验证
      • 消息认证码的生成与验证
      • 随机数的生成
    • SM3在结构上属于基本压缩函数迭代型的哈希函数.

    SM3算法描述

    • 输入数据长度为 l比特,1≤ l ≤264-1;
    • 输出哈希值的长度为256比特.

    (1) 常量与函数:SHA-256算法使用以下常数与函数:

    ①常量 初始值IV=7380166f 4914b2b9 172442d7 da8a0600 a96f30bc 163138aa e38dee4d b0fb0e4e.

     ②函数

    布尔函数

    置换函数

    其中: ∧表示按位“与”; ∨表示按位“或” ; ¬ 表示按位“补”;⊕表示按位“异或”; <<<表示循环左移

     (2) 算法描述

    ①填充

    • 对数据填充的目的是使填充后的数据长度为512的整数倍.因为迭代压缩是对512位数据块进 行的,如果数据的长度不是512的整数倍,最后一块数据将是短块,这将无法处理.
    • 设消息 m长度为 l比特.首先将比特“1”添加到 m的末尾,再添加 k个“0”,其中, k是满足下式 的最小非负整数.l +1+ k = 448 mod 512
    • 然后再添加一个64位比特串,该比特串是长度 l的二进制表示.填充后的消息 m 的比特长度一 定为512的倍数

    以信息“abc”为例显示补位的过程.a, b, c对应的ASCII码分别是97, 98, 99;于是原始信息 的二进制编码为:01100001 01100010 01100011.

    • 补一个“1” : 0110000101100010 01100011 1
    • 补423个“0”:01100001 01100010 01100011 10000000 00000000 … 00000000
    • 补比特长度24 (64位表示 ),得到512比特的数据

     ②消息扩展

    • 对一个消息分组 B(i)迭代压缩之前,首先进行消息扩展
      • 将16个字的消息分组 B(i)扩展生成如下的132个字,供压缩函数CF使用 W0,W1,…,W67,W′ 0, W′ 1,…,W′63
      • 消息扩展把原消息位打乱,隐蔽原消息位之间的关联,增强了安全性
    • 消息扩展的步骤如下:

     ③迭代压缩处理

    • 将填充后的消息 m′按512比特分组: m′= B^(0) B^(1) … B^(n−1),其中: n = ( l+ k+65)/512.
    • 对 m′按下列方式迭代压缩://外层迭代
      •  FOR i = 0 TO n-1
      • V ^(i+1)= CF^( V(i) ,B^(i) )
      • ENDFOR
      • 其中CF是压缩函数, V ^(0) 为256比特初始值IV,B^(i)为填充后的消息分组,
    • 迭代压缩的结果为 V^(n),它为消息 m的哈希值

    ④压缩函数

    • 压缩函数是SM3的核心
    • 令A, B, C, D, E, F, G, H为字寄存器,SS1, SS2, TT1, TT2为中间变量.
    • 压缩函数: V^( i+1) = CF( V^(i) ,B^(i)), 0 ≤i ≤ n -1. 压缩函数CF的压缩处理://内层迭代
      • FOR j=0 TO 63
      • CF= F(SS1, SS2, TT1, TT2 , A, B, C, D, E, F, G, H ,Wj ,W′ j ) //基本压缩函数
      • ENDFOR

     图:SM3算法的迭代压缩流程示意图

    ⑤基本压缩函数 F

    1.  SS1 ←((A <<< 12) + E + ( Tj<<< j)) <<< 7
    2. SS2 ←SS1 ⊕(A <<< 12)
    3. TT1 ←FFj (A,B,C) + D + SS2 + Wj ’
    4. TT2 ←GGj (E,F,G ) + H + SS1 + Wj 5. D ← C
    5. C ← B <<< 9
    6. B ←A
    7. A ←TT1
    8. H ← G
    9. G ← F <<<19
    10. F ← E
    11. E ←P0( TT2

     注意:

    • A, B, C, D, E, F, G, H为字寄存器,SS1, SS2, TT1, TT2为中间变量;
    • +运算为mod 232 算术加运算;
    • 字的存储为大端(big-endian)格式.即, 左边为高有效位,右边为低有效位

     图:SM3算法的基本压缩函数示意图

    ⑥SM3工作全过程

     ⑦压缩函数的作用

    • 压缩函数是SM3安全的关键
    • 第一个作用是数据压缩.SM3的压缩函数CF把每一个512位的消息分组 B(i)压缩成256 位.经过各 数据分组之间的迭代处理后把l位的消息压缩成256位的哈希值.
    • 第二个作用是提供安全性.在SM3的压缩函数CF中,布尔函数FFj (X,Y,Z) 和GGj (X,Y,Z)是非线 性函数,经过循环迭代后提供混淆作 用.置换函数P0(X) 和P1(X)是线性函数,经过循环迭代 后提供扩散作用.加上压缩函数CF中的其它运算的共同作用,压缩函数CF具有很高的安全性, 从而确保SM3具有很高的安全性

    ⑶安全性

    • 专业机构设计,经过充分测试和论证;
    • 安全性可满足上述应用的安全需求;
    • 学者已开展对SM3的安全分析 (如缩减轮的分析 ),尚未发现本质的缺陷

    哈希函数在区块链中的应用

    1.以太坊用户地址的生成

    第一步:生成私钥 (private key)

    产生的 256比特随机数做为私钥(256比特 16进制 32字节 ): 18e14a7b 6a307f42 6a94f811 4701e7c8 e774e7f9 a47e2c20 35db29a2 06321725

    第二步:生成公钥 (public key)

    1. 利用将私钥(32字节)和椭圆曲线ECDSA-secp256k1计算公钥(65字节)(前缀04||X公钥||Y公钥): 04 ||50863ad6 4a87ae8a 2fe83c1a f1a8403c b53f53e4 86d8511d ad8a0488 7e5b2352 || 2cd47024 3453a299 fa9e7723 7716103a bc11a1df 38855ed6 f2ee187e 9c582ba6
    2. 利用Keccak-256算法计算公钥的 哈希值(32bytes): fc12ad81 4631ba68 9f7abe67 1016f75c 54c607f0 82ae6b08 81fac0ab eda21781
    3. 取上一步结果取后20bytes即以太坊地址: 1016f75c54c607f082ae6b0881fac0abeda21781

    第三步:输地址 (address):0x1016f75c54c607f082ae6b0881fac0abeda21781

    2.默克尔哈希树

    Merkle树_LEVI_104的博客-CSDN博客

    3. 挖矿难度的设置

    比特币难度是对挖矿困难程度的度量,即指:计算符合给定目标的一个哈希值的困难程度.

    difficulty = difficulty_1_target / current_target difficulty_1_target

    的长度为256比特, 前32位为0, 后面全部为1 ,一般显示为哈希值,

    0x00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF difficulty_1_target表示btc网络最初的目标哈希. current_target是当前块的目标哈希,先经 过压缩然后存储在区块中,区块的哈希值必须小于给定的目标哈希值, 表示挖矿成功

    4. 数字签名

    比特币需要利用公钥进行加锁,利用私钥签名进行解锁,从而实现数字货币的交易. 解锁过程实 际上是利用ECDSA算法的产生数字签名. 给定交易信息 m,签名过程如下:

    1. 选择一个随机数 k;
    2. 计算点 R = k*G= (xR, yR ) ,计算 r = xR mod n;
    3. 利用私钥 d计算 s = k-1 * (( H( m) - d * r)) mod n;
    4. 输入签名 ( r, s)

    5. 软件发布

     图:挖矿软件发布信息示意图

    展开全文
  • 哈希函数

    万次阅读 多人点赞 2018-03-01 08:12:14
    在某种程度上,散列是与排序相反的一种操作,排序是将集合中的元素按照某种方式比如字典顺序排列在一起,而散列通过计算哈希值,打破元素之间原有的关系,使集合中的元素按照散列函数的分类进行排列。在介绍一些集合...
  • 密码学哈希函数

    千次阅读 2017-08-22 21:52:24
    哈希函数是一个数学函数,其具有以下三个特性: 输入可以为任意大小的字符串;其产生固定大小的输出;对于特定的输入字符串,能在合理时间计算出结果。对应n位的字符串,其哈希值计算的复杂度为O(n)。 要使...
  • 常用哈希函数介绍

    千次阅读 2021-03-31 16:21:32
    哈希函数介绍 什么是哈希?在记录的关键字与记录的存储地址之间建立的一种对应关系叫哈希函数哈希函数就是一种映射,是从关键字到存储地址的映射。 通常,包含哈希函数的算法的算法复杂度都假设为O(1),这就是为...
  • 哈希原理与常见哈希函数

    千次阅读 多人点赞 2020-01-09 18:11:06
    (1)一致性:同一值每次经过同一个哈希函数计算后得到的哈希值是一致的。 F(x)=rand() :每次返回一随机值,是不好的哈希 (2)散列性:不同的值的哈希值尽量不同,理想情况下每值对应于不同的数字。 F(x)...
  • 在云存储服务中,为使第方可以验证存储服务提供者持有(保存)用户数据的正确性,且用户的数据不会泄露给第方,提出一种基于同态哈希函数的隐私保护性公钥审计算法。通过在文件的线性组合中插入一随机向量的方法,...
  • 哈希函数和哈希表

    2019-07-12 20:24:41
    说白了,哈希函数就是用来将key-value结构中关键字值转换为数组的下标的函数(一般都是通过取模,而且这样子在数据量很大的情况下一般是均匀分布的),然后将该结构存放到数组中去,然后这数组就叫做哈希表. 这固定...
  • 本章简单讲讲哈希函数的实现,和大数据问题的处理方法 认识哈希函数 1.输入域是无穷的,输出域是有限的. 2.相同的输入会返回相同的输出 3.不同的输入可能会返回相同的输出(哈希碰撞,因为输入域是无穷的,输出是有限...
  • 区块链中的哈希函数

    千次阅读 2021-08-22 16:06:20
    哈希函数是一公开函数,可以将任意长度的消息M映射成为一长度较短且长度固定的值H(M),称H(M)为哈希值、散列值(Hash Value)、杂凑值或者消息摘要(Message Digest)。 (2)它是一种单向密码体制,即一...
  • 现代密码学5.1--哈希函数 博主正在学习INTRODUCTION TO MODERN CRYPTOGRAPHY (Second Edition) --Jonathan Katz, Yehuda Lindell,做一些笔记供自己回忆,如有错误请指正。整理成一系列现代密码学,方便检索。 第...
  • 哈希算法(哈希函数)基本

    千次阅读 2021-09-19 16:33:42
    一、什么是哈希(Hash) 哈希也称“散列”函数或“杂凑”函数。它是一不可逆的单向映射,将任意长度的输入消息M...这是哈希函数安全性的基础。 灵敏性:对输入数据敏感,哪怕只改了一Bit,得到的哈希值也大不相同
  • 什么是哈希函数

    千次阅读 2020-09-25 11:45:24
    Hash函数译为哈希函数,又称散列函数。是把任意长度的输入,通过散列算法,变换成固定...出于安全性考虑,对哈希函数三个安全性假设: 对任意给定的散列值h,找到满足H(x)=h的x在计算上是不可行的,称之为单向性...
  • 哈希函数就是映射关系 、哈希表应用举例: Leetcode上第387题: 思路:通过s.charAt(i)-'a’将字符串中的字符映射成hash表,出现一次,在相应位置加一,左后找到第一值为1的下标 其他思路:当然此题解决方案很...
  • 本文出自 AC.HASH 团队,AC<=>Adaptive Creator,适应性...Table of Contents什么是哈希函数?什么是birthday attack?哈希值的长度如何影响安全性?什么是压缩函数?什么是冲突(pseudo-collisions)?什么是MD2、M.
  • 密码学哈希函数A Hash Function is a mathematical function that converts a numerical value into another compressed numeric value. The input value for the hash functions can be of arbitrary length, but ...
  • 哈希函数和消息认证

    千次阅读 2020-12-29 21:39:24
    文章目录一、哈希(Hash)函数1、...Hash函数也称散列函数、哈希函数、杂凑函数等。,是一从消息空间到像空间的不可逆映射。hash函数能将“任意长度”的消息经过hash变换为固定长度的像。所以Hash函数是一种具有压缩性
  • 哈希函数的一些知识

    2020-12-10 06:44:46
    哈希函数是一个数学函数,其具有以下三个特性: 输入可以为任意大小的字符串; 其产生固定大小的输出; 对于特定的输入字符串,能在合理时间计算出结果。对应n位的字符串,其哈希值计算的复杂度为O(n)。 要使...
  • 几种常见的哈希函数(散列函数)构造方法 直接定址法 取关键字或关键字的某个线性函数值为散列地址。 即 H(key) = key 或 H(key) = a*key + b,其中a和b为常数。 比如 除留余数法 取关键字被某个不大于散...
  • 哈希函数和数字签名

    千次阅读 2021-09-13 18:54:27
    目录1 哈希函数 Hash1.1 构造方法1.2 哈希函数在密码学的应用2 数字签名2.1 签名--认证流程2.2 一生动形象的例子 在讲数字前面以前,我们先要了解一下哈希函数 1 哈希函数 Hash Hash,一般翻译做散列、杂凑,或...
  • 所有哈希表都使用一个哈希函数,该函数将放入容器的元素的值映射到特定的存储桶。目标两是相等的值始终生成相同的存储桶索引,而对于不同的值,理想情况下应处理不同的存储桶条目。对于任何传递值的范围,哈希函数...
  • 目录概念哈希函数哈希冲突哈希冲突的解决闭散列概念哈希表闭散列的实现(采用线性探测)哈希表整体框架插入元素查找元素删除元素开散列概念哈希表开散列实现(哈希桶)整体框架插入元素查找元素删除元素字符串哈希...
  • 散列函数(也叫哈希函数) 将任意长度的消息映射陈一较短的定长输出报文的函数 作用:完整性校验 主要算法:MD5、SHA-1 数学性质 单向性 弱抗碰撞性 强抗碰撞性 基于hash的模型 散列函数(哈希...
  • 这里有一点需要强调,不要把哈希函数想成具体的实现,要想成理想化的一黑盒,就是我指定一范围(1到N),经过HASH(X)的值等于从范围1到N中的任意值的概率是1/N。 设想有一阵列位(例如一字节有8阵列位),...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 168,108
精华内容 67,243
热门标签
关键字:

哈希函数的三个特征

友情链接: DevExpress.Utils.v11.2.zip