由于在之后的算法中会用到HMAC-SHA256函数,这里先简单对其进行一个介绍。

一、HMAC算法

  • 什么是HMAC算法?

HMAC是密钥相关的哈希运算消息认证码(Hash-based Message Authentication Code)的缩写,由H.Krawezyk,M.Bellare,R.Canetti于1996年提出的一种基于Hash函数和密钥进行消息认证的方法,并于1997年作为RFC2104被公布,并在IPSec和其他网络协议(如SSL)中得以广泛应用,现在已经成为事实上的Internet安全标准。它可以与任何迭代散列函数捆绑使用。[3]

简单地说就是:HMAC是一种使用单向散列函数构造消息认证码的算法。

HMAC算法利用哈希运算,以一个密钥一个消息为输入,生成一个消息摘要作为输出。其安全性是建立在Hash加密算法基础上的。它要求通信双方共享密钥、约定算法、对报文进行Hash运算,形成固定长度的认证码。通信双方通过认证码的校验来确定报文的合法性。HMAC算法可以用来作加密、数字签名、报文验证等[2]。HMAC使用的Hahs函数并不仅限于一种,任何高强度的单向散列函数都可以被用于HMAC,如果将来设计出的新的单向散列函数,也同样可以使用。使用SHA-1、SHA-224、SHA-256、SHA-384、SHA-512所构造的HMAC,分别称为HMAC-SHA1、HMAC-SHA-224、HMAC-SHA-256、HMAC-SHA-384、HMAC-SHA-512[1]。其中HMAC-SHA256就是接下来要重点介绍的。

定义1 HMAC算法

HMAC算法的数学公式为:
                HMAC ( k , m ) = H ( k’ ⊕ opad , H ( k’ ⊕ ipad,  m ) )
        其中:
                H 为密码Hash函数(如MD5或SHA-2),能够对明文进行分组循环压缩;
                k 为密钥(secret key);
                m 为要认证的消息;
                k’ 是从原始密钥 k 导出的另一个密钥(如果 k 短于散列函数的输入块大小,则向右填充零;如果比该块大小更长,则对 k 进行散列)
                ipad 内部填充(0x5C5C5C…5C5C,一段十六进制常量);
                opad 外部填充(0x363636…3636,一段十六进制常量)。

1.1 HMAC的计算步骤

HMAC计算步骤如下图所示:

① 密钥处理

如果密钥比单向散列函数分组长度要,就需要在末尾填充0,直到其长度达到单向散列函数的分组长度为止。

如果密钥比分组长度要,则要用单向散列函数求出密钥的散列值,然后将这个散列值用作HMAC的密钥。

② 处理后的密钥与ipad进行XOR

将处理后的密钥与被称为ipad的比特序列进行XOR运算。ipad是将00110110这一比特序列不断循环反复直到达到分组长度所形成的比特序列,其中ipad的i是inner的意思。

XOR运算所得到的值,是一个和单向散列函数的分组长度相同,且和密钥相关的比特序列。这里将这个比特序列称为ipadkey。

③ 与消息组合

随后,将ipadkey与消息组合,也就是将和密钥相关的比特序列(ipadkey)附加在消息的开头。

④ 计算散列值

将步骤③的结果作为单向散列函数的输入,并计算出散列值。

⑤ 处理后的密钥与opad进行XOR

将填充后的密钥与被称为opad的比特序列进行XOR运算,opad是将01011100这一比特序列不断循环反复直到达到分组长度所形成的比特序列,其中opad的o是outer的意思。

XOR运算所得到的结果也是一个和单向散列函数的分组长度相同,且和密钥相关的比特序列。这里将这个比特序列称为opadkey。

⑥ 与散列值组合

将步骤④的结果拼在opadkey的后面。

⑦ 计算散列值

将步骤⑥的结果输入单向散列函数,并计算出散列值,这个散列值就是最终的MAC值。

通过上述流程可以看出,最后得到的MAC值,一定是一个和输入的消息以及密钥都相关的长度固定的比特序列。

二、SHA-256算法

  • 什么是SHA-256算法?

散列函数它被认为是一种单向函数——根据函数输出的结果,极难回推输入的数据。散列函数把消息数据打乱混合,压缩成散列值(摘要),使得数据量变小。

SHA-256由美国国家安全局研发,是SHA-2下细分出的一种算法,属于SHA算法之一,是SHA-1的后继者。SHA-256(Secure Hash Algorithm 256,安全散列算法256)是散列函数(或哈希函数)的一种,对于任意长度的消息,SHA256都会产生一个256-bit(32-byte数组)的哈希值,称作消息摘要。。摘要通常用一个长度为64位的十六进制字符串来表示。当接收到消息的时候,这个消息摘要可以用来验证数据是否发生改变,即验证其完整性。[2]

2.1 SHA-256的算法描述

首先进行信息预处理,如下图所示,将原始消息分成若干个512-bit大小的消息块。最后一个消息块需要进行信息补全,并附上原消息的长度信息。消息被分成n块后,需要进行n次迭代,最后一次的结果就是最终的哈希值,即256bit的数字摘要。

SHA256算法的最小运算单元为“字”(word, 32-bit)。下图的256-bit的中间状态Hi被描述为8个字。512-bit的消息块Mi将由16个字扩展为64个字,并与Hi混合,压缩成新的散列值Hi+1。第i块数据经Map函数映射的结果,将作为第i+1块的输入,即Map(H_(i-1))=H_i。H0是预设好的hash初值(自然数中前8个质数的平方根的小数部分,取前32-bit),依次对数据进行Hash映射,得到的最后一个状态Hn便是最终的数字摘要。

而其中最关键的操作为映射函数Map,其内部相当于是一个循环加密的过程,不断将原始信息进行打乱。

2.2 SHA-256的算法步骤

下面两个表列出了SHA256散列函数中涉及到的所有逻辑运算,运算均是按位进行的。

设原始消息为M,原始消息长度LM,消息块Mi,哈希初值H0,SHA-256常量K[0]~K[63](自然数中前64个质数的立方根的小数部分,取前32-bit)。则SHA-256算法的加密步骤具体如下:
  ① 消息(M)预处理

在消息末尾进行添加一位“1”和t位“0”,使得:
                                           (L_M+t+1) mod 512=448,0≤t<512
   将LM表示为64位大端存储格式,并添加到M末尾,组成新的消息M^’;
  ② 分解

将M^'按照每块512-bit大小分解为Mi;
  ③ 拓展Mi到64字:W[0]~W[63]

将Mi分解为16个32-bit的大端存储的字(word),存为W[0], …, W[15],其余字由以下公式得到:
                                      W_t=σ_1 (W_(t-2))+W_(t-7)+σ_0 (W_(t-15))+W_(t-16)
  ④ 迭代

进行64次加密循环即可完成一次迭代。加密过程如图4所示:ABCDEFGH这8个字最开始分别是8个哈希初值,之后按照图示规则进行更新;深蓝色方块是事先定义好的非线性逻辑函数;红色方块代表加法(若结果大于232,则进行一次mod 232运算);Kt为SHA-256常量,Wt为本区块产生第t个word,0≤t<64;最后一次循环所产生的八段字符串合起来即是此区块对应到的散列字符串;
  ⑤ 若原消息包含数个区块,则最后还要将这些区块产生的散列字符串加入迭代才能产生最后的散列字符串。

三、HMAC-SHA256算法

3.1 HMAC-SHA256的算法描述

HMAC-SHA256算法,即使用SHA-256生成哈希值的HMAC算法。依据HMAC算法和SHA-256算法内容,可知HMAC-SHA256算法的明文分组长度B为512-bit,可通过任意长度密钥K(最小推荐长度为256-bit,一般应大于B),得出长度为256-bit散列值(摘要)。定义为:

〖HMAC〗_SHA256 (k,m)= SHA256(k’⊕opad∥SHA256(k’⊕ipad∥m))
  其中:
  SHA256 为SHA-256加密算法,其输出散列值长度256-bit;
  || 拼接操作,将两个字符串拼接在一起;
  B Hash函数明文分组长度,SHA-256算法中为512-bit;
  k 为密钥(secret key);
  m 为要认证的消息;
  k’ 是从原始密钥 k 导出的另一个密钥(若 k 短于B,则向右填充零,直到与B相同;若k长于B,则对 k 进行一次SHA256散列计算)
  ipad 内部填充(0x5C5C5C…5C5C,512-bit常量);
  opad 外部填充(0x363636…3636,512-bit常量)。

3.2 HMAC-SHA256的算法步骤

HMAC-SHA256计算步骤如下图所示:

① 密钥处理

如果密钥比SHA-256分组长度(512-bit)要,就需要在末尾填充0,直到其长度达到单向散列函数的分组长度为止。

如果密钥比SHA-256分组长度(512-bit)要,则要用SHA-256算法求出密钥的散列值,然后将这个散列值用作HMAC的密钥。

② 处理后的密钥与ipad进行XOR

将处理后的密钥与被称为ipad的比特序列进行XOR运算。ipad是将00110110这一比特序列不断循环反复直到达到SHA-256分组长度(512-bit)所形成的比特序列,其中ipad的i是inner的意思。

XOR运算所得到的值,是一个和SHA-256分组长度(512-bit)相同,且和密钥相关的比特序列。这里将这个比特序列称为ipadkey。

③ 与消息组合

随后,将ipadkey与消息组合,也就是将和密钥相关的比特序列(ipadkey)附加在消息的开头。

④ 计算散列值

将步骤③的结果作为SHA-256函数的输入,并计算出散列值。

⑤ 处理后的密钥与opad进行XOR

将填充后的密钥与被称为opad的比特序列进行XOR运算,opad是将01011100这一比特序列不断循环反复直到达到SHA-256分组长度(512-bit)所形成的比特序列,其中opad的o是outer的意思。

XOR运算所得到的结果也是一个和SHA-256分组长度(512-bit)相同,且和密钥相关的比特序列。这里将这个比特序列称为opadkey。

⑥ 与散列值组合

将步骤④的结果拼在opadkey的后面。

⑦ 计算散列值

将步骤⑥的结果输入SHA-256函数,并计算出散列值,这个散列值就是最终的摘要内容。

通过上述流程可以看出,最后得到的摘要内容,一定是一个和输入的消息以及密钥都相关的长度固定的比特序列。

参考:

[1] HMAC简介及HMAC-SHA256实现Demo

[2] 从零入门HMAC-SHA256

[3] HMAC百度百科

可搜索加密技术 - 学习笔记(二)- 预备知识:HMAC-SHA256函数的更多相关文章

  1. Java多线程技术学习笔记(二)

    目录: 线程间的通信示例 等待唤醒机制 等待唤醒机制的优化 线程间通信经典问题:多生产者多消费者问题 多生产多消费问题的解决 JDK1.5之后的新加锁方式 多生产多消费问题的新解决办法 sleep和w ...

  2. WPF的Binding学习笔记(二)

    原文: http://www.cnblogs.com/pasoraku/archive/2012/10/25/2738428.htmlWPF的Binding学习笔记(二) 上次学了点点Binding的 ...

  3. AJax 学习笔记二(onreadystatechange的作用)

    AJax 学习笔记二(onreadystatechange的作用) 当发送一个请求后,客户端无法确定什么时候会完成这个请求,所以需要用事件机制来捕获请求的状态XMLHttpRequest对象提供了on ...

  4. [Firefly引擎][学习笔记二][已完结]卡牌游戏开发模型的设计

    源地址:http://bbs.9miao.com/thread-44603-1-1.html 在此补充一下Socket的验证机制:socket登陆验证.会采用session会话超时的机制做心跳接口验证 ...

  5. NumPy学习笔记 二

    NumPy学习笔记 二 <NumPy学习笔记>系列将记录学习NumPy过程中的动手笔记,前期的参考书是<Python数据分析基础教程 NumPy学习指南>第二版.<数学分 ...

  6. python3.4学习笔记(二十四) Python pycharm window安装redis MySQL-python相关方法

    python3.4学习笔记(二十四) Python pycharm window安装redis MySQL-python相关方法window安装redis,下载Redis的压缩包https://git ...

  7. amazeui学习笔记二(进阶开发2)--Web组件简介Web Component

    amazeui学习笔记二(进阶开发2)--Web组件简介Web Component 一.总结 1.amaze ui:amaze ui是一个web 组件, 由模板(hbs).样式(LESS).交互(JS ...

  8. Docker学习笔记二(linux下安装Docker)

    Docker学习笔记二(linux下安装Docker) 1.在线安装linux Docker 这种方式首先要保证linux 环境下可以上网,当然,小编是在自己的电脑上安装了虚拟机,在虚拟机上安装了,l ...

  9. JMX学习笔记(二)-Notification

    Notification通知,也可理解为消息,有通知,必然有发送通知的广播,JMX这里采用了一种订阅的方式,类似于观察者模式,注册一个观察者到广播里,当有通知时,广播通过调用观察者,逐一通知. 这里写 ...

随机推荐

  1. grasshopper之python电池执行逻辑

    在grasshopper中,需要导入的包虽然不多,但是相当绕人,所要实现的操作往往找不到,暂时做个分类. 双击输入 python 电池: # 导入rhino 包 import Rhino #Rhino ...

  2. C++中头文件和实现文件的关系

    头文件相当于是声明的集合,包括头文件的语句#Include实质为程序代码的宏替换. 编译阶段将函数和变量登记在符号表,链接时将各种函数的入口地址在其中查找到来调用,解引用.

  3. 孟老板 ListAdapter封装, 告别Adapter代码 (上)

    BaseAdapter封装(一) 简单封装 BaseAdapter封装(二) Header,footer BaseAdapter封装(三) 空数据占位图 BaseAdapter封装(四) PageHe ...

  4. JUC 并发编程--09, 阻塞队列: DelayQueue, PriorityBlockingQueue ,SynchronousQueue, 定时任务线程池: ScheduledThreadPoolExecutor

    先看DelayQueue 这个是用优先级队列实现的无界限的延迟队列,直接上代码: /** * 这个是 {@link DelayQueue} 延时队列 的验证使用类 */ class MyDelayed ...

  5. Appium UI自动化测试

    #coding:utf-8 from appium import webdriver import time,traceback ''' desired_capabilities:这些键告诉appiu ...

  6. 八、配置Tomcat日志

    [root@svr5 ~]# vim /usr/local/tomcat/conf/server.xml .. .. <Host name="www.a.com" appBa ...

  7. 性能分析之CPU分析-从CPU调用高到具体代码行(JAVA)

      通常情况下,性能报告中只说CPU使用率高的时候,并不能帮助定位问题.因为CPU高会有多种不同的情况.CPU有五种状态(us sy id wa st), 在vmstat中能显示出来,这个想必很多人都 ...

  8. mysqldump 使用规范

    数据库很重要,没有备份,数据丢失只能跑路.所以还是做好备份吧! 目录 一.工具介绍 二.工具特点 三.备份权限 四.工具使用限制 五.已知BUG 六.备份前注意事项 6.1 需要长时间备份或导入时,请 ...

  9. 【NX二次开发】Block UI 切换开关

    属性说明 常规         类型 描述     BlockID     String 控件ID     Enable     Logical 是否可操作     Group     Logical ...

  10. 【NX二次开发】NX内部函数,libufunx.dll文件中的内部函数

    本文分为两部分:"带参数的函数"和 "带修饰的函数". 浏览这篇博客前请先阅读: [NX二次开发]NX内部函数,查找内部函数的方法 带参数的函数: void e ...