/**
* 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.adobe.com/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"/>
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>