HMAC算法(AS3)

软件编程牛人

还记得上学期信息系统安全工程课上杨老师说到04年山大的教授破译了MD5、HAVAL-128、MD4和RIPEMD算法时得意的神情,似乎那玩意是他自己破的一样,哈哈。不过MD5、SHA算法虽然被中国人破解了,但并不代表基于MD5等算法的网上交易认证、数字签名什么的失效了——就比如基于MD5或者SHA算法的HMAC算法。
  MD5和SHA-1是一种HASH函数,又称杂凑函数,类似于指纹的应用。在网络安全协议中,杂凑函数用来处理电子签名,将冗长的签名文件压缩为一段独特的数字信息,像指纹鉴别身份一样保证原来数字签名文件的合法性和安全性。经过这些算法的处理,原始信息即使只更动一个字母,对应的压缩信息也会变为截然不同的“指纹”,这就保证了经过处理信息的唯一性。为电子商务等提供了数字认证的可能性。
  而HMAC算法需要一个加密用散列函数(表示为H,可以是MD5或者SHA-1)和一个密钥K。我们用B来表示数据块的字节数。(以上所提到的散列函数的分割数据块字长B=64),用L来表示散列函数的输出数据字节数(MD5中L=16,SHA-1中L=20)。鉴别密钥的长度可以是小于等于数据块字长的任何正整数值。应用程序中使用的密钥长度若是比B大,则首先用使用散列函数H作用于它,然后用H输出的L长度字符串作为在HMAC中实际使用的密钥。一般情况下,推荐的最小密钥K长度是L个字节。

  我们将定义两个固定且不同的字符串ipad,opad:(‘i','o'标志内部与外部)
  ipad = the byte 0x36 重复 B 次
  opad = the byte 0x5C 重复 B 次.
  计算‘text'的HMAC:
  HMAC =  H( K XOR opad, H(K XOR ipad, text))

  即为以下步骤:
  (1) 在密钥K后面添加0来创建一个字长为B的字符串。(例如,如果K的字长是20
  字节,B=64字节,则K后会加入44个零字节0x00)
  (2) 将上一步生成的B字长的字符串与ipad做异或运算。
  (3) 将数据流text填充至第二步的结果字符串中。
  (4) 用H作用于第三步生成的数据流。
  (5) 将第一步生成的B字长字符串与opad做异或运算。
  (6) 再将第四步的结果填充进第五步的结果中。
  (7) 用H作用于第六步生成的数据流,输出最终结果

  HMAC的典型应用

  HMAC的一个典型应用是用在“挑战/响应”(Challenge/Response)身份认证中,认证流程如下[3]:
   (1) 先由客户端向服务器发出一个验证请求。
   (2) 服务器接到此请求后生成一个随机数并通过网络传输给客户端(此为挑战)。
   (3) 客户端将收到的随机数提供给ePass,由ePass使用该随机数与存储在ePass中的密钥进行HMAC-MD5运算并得到一个结果作为认证证据传给服务器(此为响应)。
   (4) 与此同时,服务器也使用该随机数与存储在服务器数据库中的该客户密钥进行HMAC-MD5运算,如果服务器的运算结果与客户端传回的响应结果相同,则认为客户端是一个合法用户

  HMAC算法AS3版(作者hurlant):

/**
* HMAC
*
* An ActionScript. 3 implementation of HMAC, Keyed-Hashing for Message
* Authentication, as defined by RFC-2104
* Copyright (c) 2007 Henri Torgemane
*
*/
package com.hurlant.crypto.hash
{
  import flash.utils.ByteArray;
  import com.hurlant.util.Hex;
 
  public class HMAC
  {
    private var hash:IHash;
    private var bits:uint;
   
    /**
    * Create a HMAC object, using a Hash function, and
    * optionally a number of bits to return.
    * The HMAC will be truncated to that size if needed.
    */
    public function HMAC(hash:IHash, bits:uint=0) {
      this.hash = hash;
      this.bits = bits;
    }
   
    /**
    * Compute a HMAC using a key and some data.
    * It doesn't modify either, and returns a new ByteArray with the HMAC value.
    */
    public function compute(key:ByteArray, data:ByteArray):ByteArray {
      var hashKey:ByteArray;
      if (key.length>hash.getInputSize()) {
        hashKey = hash.hash(key);
      } else {
        hashKey = new ByteArray;
        hashKey.writeBytes(key);
      }
      while (hashKey.length<hash.getInputSize()) {
        hashKey[hashKey.length]=0;
      }
      var innerKey:ByteArray = new ByteArray;
      var outerKey:ByteArray = new ByteArray;
      for (var i:uint=0;i<hashKey.length;i++) {
        innerKey[i] = hashKey[i] ^ 0x36;
        outerKey[i] = hashKey[i] ^ 0x5c;
      }
      // inner + data
      innerKey.position = hashKey.length;
      innerKey.writeBytes(data);
      var innerHash:ByteArray = hash.hash(innerKey);
      // outer + innerHash
      outerKey.position = hashKey.length;
      outerKey.writeBytes(innerHash);
      var outerHash:ByteArray = hash.hash(outerKey);
      if (bits>0 && bits<8*outerHash.length) {
        outerHash.length = bits/8;
      }
      return outerHash;
    }
    public function dispose():void {
      hash = null;
      bits = 0;
    }
    public function toString():String {
      return "hmac-"+(bits>0?bits+"-":"")+hash.toString();
    }
   
  }
}

 

算法的使用:
  这个HMAC算法加密和解密均使用ByteArray,使用时需要使用hurlant的Hex类中对应的方法转换数据类型。
引用

If you want a HMAC of SHA-224 with 128 significant bits, you can use
var hmac:HMAC = Crypto.getHMAC("hmac-128-sha224");
You can then use it as:
var value:ByteArray = hmac.compute(key, data);

 


<?xml version="1.0" encoding="utf-8"?>
<!--
/**
* HmacTab
*
* A UI Component that allows one to quickly test the HMAC algorithm
* made available in the AS3 Crypto library.
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
-->
<mx:Canvas xmlns:mx="http://www.**/2006/mxml" label="HMAC" width="100%" height="100%">
  <mx:Label text="Hash Function:" left="10" top="10"/>
  <mx:ComboBox id="hashType" labelField="@label" left="106" top="8">
  <mx:dataProvider>
    <mx:XMLList>
      <item label="SHA-256" value="sha256"/>
      <item label="SHA-224" value="sha224"/>
      <item label="SHA-1" value="sha1"/>
      <item label="MD5" value="md5"/>
      <item label="MD2" value="md2"/>
    </mx:XMLList>
  </mx:dataProvider>
  </mx:ComboBox>
  <mx:Label x="10" y="36" text="Key Format:"/>
  <mx:ComboBox id="keyFormat" labelField="@label" left="91" top="34">
  <mx:dataProvider>
    <mx:XMLList>
      <item label="Text" value="text"/>
      <item label="Hex" value="hex"/>
      <item label="Base64" value="b64"/>
    </mx:XMLList>
  </mx:dataProvider>
  </mx:ComboBox>
  <mx:TextArea id="key" left="10" right="10" top="62" height="50"/>
  <mx:Label text="Input Format:" left="10" top="120"/>
  <mx:ComboBox id="inputFormat" labelField="@label" left="91" top="118">
  <mx:dataProvider>
    <mx:XMLList>
      <item label="Text" value="text"/>
      <item label="Hex" value="hex"/>
      <item label="Base64" value="b64"/>
    </mx:XMLList>
  </mx:dataProvider>
  </mx:ComboBox>
  <mx:TextArea id="input" left="10" right="10" top="146" bottom="148"/>
  <mx:Label text="Output Format:" left="10" bottom="120"/>
  <mx:ComboBox id="outputFormat" labelField="@label" bottom="118" left="109" change="displayOutput()">
  <mx:dataProvider>
    <mx:XMLList>
      <item label="Text" value="text"/>
      <item label="Hex" value="hex"/>
      <item label="Base64" value="b64"/>
    </mx:XMLList>
  </mx:dataProvider>
  </mx:ComboBox>
  <mx:TextArea id="output" height="100" right="10" left="10" bottom="10" editable="false"/>
  <mx:Button label="Compute HMAC" right="10" click="computeHMAC()" bottom="118"/>
 
  <mx:Script>
    <![CDATA[
      import com.hurlant.crypto.hash.HMAC;
      import com.hurlant.util.Base64;
      import com.hurlant.util.Hex;
      import com.hurlant.crypto.Crypto;
      import com.hurlant.crypto.hash.IHash;
     
      private var currentResult:ByteArray;
     
      private function computeHMAC():void {
        // 1: get a IHash.
        var hmac:HMAC = Crypto.getHMAC(hashType.selectedItem.@value);
        // 2: get a key
        var k:String = key.text;
        var kdata:ByteArray;
        var kformat:String = String(keyFormat.selectedItem.@value);
        switch (kformat) {
          case "hex": kdata = Hex.toArray(k); break;
          case "b64": kdata = Base64.decodeToByteArray(k); break;
          default:
            kdata = Hex.toArray(Hex.fromString(k));
        }
        // 3: get an input
        var txt:String = input.text;
        var data:ByteArray;
        var format:String = String(inputFormat.selectedItem.@value);
        switch (format) {
          case "hex": data = Hex.toArray(txt); break;
          case "b64": data = Base64.decodeToByteArray(txt); break;
          default:
            data = Hex.toArray(Hex.fromString(txt));
        }
        currentResult = hmac.compute(kdata, data);
        displayOutput();
      }
      private function displayOutput():void {
        if (currentResult==null) return;
        var txt:String;
        var format:String = String(outputFormat.selectedItem.@value);
        switch (format) {
          case "hex": txt = Hex.fromArray(currentResult); break;
          case "b64": txt = Base64.encodeByteArray(currentResult); break;
          default:
            txt = Hex.toString(Hex.fromArray(currentResult)); break;
        }
        trace("txt="+txt);
        output.text = txt;
      }
    ]]>
  </mx:Script>
</mx:Canvas>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值