当前位置: 首页 > 图文教程 > 开发语言 > VC++ > 基于SHA-256的HMAC文件校验器

VC++
如何在运行时确定对象类型(RTTI)
FMD开发文集 -- CArchive原理
FMD开发文集 -- MFC调试模式下new操作符的特殊处理
FMD开发文集 -- MFC CObject浅析
生死疆界(下)--- 在new与delete之间
生死疆界(上)--- 在new与delete之间
Pointers 与 References(四)
Pointers 与 References(三)
Pointers 与 References(二)
Pointers 与 References(一)
介绍一个专门处理C++异常的类和例子
关于构造单实例类的一个问题
模板友元化
C++中类的数据成员的安全隐患
关于对象生命历程的会话
接触VC之二:MFC类基础,C++程序编写规范介绍
内联汇编基础知识
命名空间的概念
捕获数学函数异常
MMX指令集在C++中的使用

VC++ 中的 基于SHA-256的HMAC文件校验器


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-10-30   浏览: 86 ::
收藏到网摘: n/a

基于SHA-256的HMAC文件校验器

作者:Gamsn

下载源代码

  HMAC即带密钥的HASH函数,用它产生的报文鉴别码(MAC)可以实现报文鉴别。这里我将其做成一个软件,用于对文件的合法性进行校验。以下我先简单介绍软件相关背景知识再介绍其代码实现。

一、背景知识简介
  有时候进行通信的双方基于安全的考虑需要对对方发过来的消息进行校验,以确定消息是未经第三方修改过的。这种校验可以这样进行:
  • 双方共同约定一个密钥(即一个密码),这个密钥是对第三方保密的;
  • 消息的发方使用该密钥对将发送的消息产生一个校验码,并把该校验码附在消息后一起发出;
  • 消息的接收方在接收到附有校验码的消息后,将消息和校验码分开,用密钥对该消息生成一个校验码;
  • 然后将两个校验码相比较,如果相同的话则说明消息是未经第三方修改的,如果不同的话说明消息很可能被非法修改过(当然也有可能是别的原因使消息改变了)则该消息不可信,需要对方重发 ;
  •  *其中,生成校验码的算法一般采用HMAC,它保证了第三方在不知密钥的情况下,不可能在修改消息后可以同时修改校验码使之与修改后的消息匹配。
     *在整个过程中消息是公开的(未经加密的),算法只提供消息的完整性校验而不提供保密性,保密性可由公钥加密算法现实,这里不作讨论。

    二、软件的实现
      我做的该软件是可以对电脑磁盘上的任意一文件生成一校验文件.vri(密钥由用户自己输入),根据该校验文件可以在需要之时对相应的文件进行校验。具体做法将在后面的例子中给出。
      程序中的HMAC算法的HASH函数我采用的是SHA-256算法,它比起MD5和SHA-1来要安全。(其实因为不是正式的安全产品,所以在本程序中采用MD5或SHA-1也未尝不可)。

    *HMAC的结构如下图所示:
     

    图一 HMAC的结构

    图中各符号定义如下:

    IV =作为HASH函数输入的初始值 M =HMAC的消息输入 Yi =M的第i个分组,0<=i<=(L-1) b =每一分组所含的位数 n =嵌入的HASH函数所产生的HASH码长 K =密钥 K+ =为使K为b位长而在K左边填充0后所得的结果 ipad =0x36重复b/8次的结果 opad =0x5c重复b/8次的结果 

      对于特定的HASH函数,b、n都是固定的,所以在程序的HMAC类中,n被定义为宏Mn,b被定义为Mb,值分别为32和64。由于该结构的效率较低,不利于实用化。于是有人提出了一个HMAC的高效实现方案。

    *HMAC的有效实现方案如下:


    图二 HMAC的有效实现方案

    其中的HASH即为SHA-256。

    图中左边所示为预计算,右边为对每条消息的计算。在密钥不变的情况下只需进行一次预计算,以后在产生校验码时就只用到右边的计算了。这样就可以提高效率。
      需要说明的是,大家在阅读我写的HMAC的类可能会发现,在每次计算时都进行了左右两边的计算(不论密钥怎样)。这是因为我考虑到个人用户可能会不时地对密钥进行更换,并且应用场合也不对效率有特别的要求。当然这样做并没有体现出HMAC有效实现方案的优点。
      另外还有一点就是我对密钥的填充是填充的低位,即密钥右边,这和上述方案有不同(方案上说是要填充在高位,即左边),在此说明,以使大家在看源代码的时候不至于疑惑。
      以上有效实现方案在HMac类中现实,HASH函数sha-256在Sha256类中实现。由于这里主要说的是HMAC,sha-256只是作为一个黑盒子,所以不多解释。
      程序中的Mac类与HAMC和HASH函数都无关,只是一个存放结果的介质,它甚至都没有成员函数,我也在考虑是不是可以不把它做成一个类。

    为了便于读者阅读HMac类中的各变量基本上采用图二中的各标识符标识。

    对于下面一段代码读者可能会有疑惑,明明是该得到第一个预计算的结果,m_dwA1—m_dwH1是什么呢?

    for(i=0;i<Mb;i++) S[i]=sKeyplus[i]^ipad[i];m_sha256.Init(Mb);m_sha256.GenW(S,Mb);m_sha256.Steps();m_dwA1=m_sha256.OA;m_dwB1=m_sha256.OB;m_dwC1=m_sha256.OC;m_dwD1=m_sha256.OD;m_dwE1=m_sha256.OE;m_dwF1=m_sha256.OF;m_dwG1=m_sha256.OG;m_dwH1=m_sha256.OH; 
      其实m_dwA1—m_dwH1就是第一个预计算的输出。这里因为这个输出有256位,于是我把它拆成了8个32位。同理,第二个预计算的输出为m_dwA2—m_dwH2。
      此外,程序中关于文件拖