4 * An ActionScript 3 implementation of MAC, Message Authentication Code
\r
5 * for use with SSL 3.0.
\r
6 * Loosely copyrighted by Bobby Parker.
\r
7 * As3crypto copyrighted by Henri Torgemane.
\r
9 * See LICENSE.txt for full license information.
\r
11 package com.hurlant.crypto.hash
\r
13 import flash.utils.ByteArray;
\r
14 import com.hurlant.util.Hex;
\r
16 public class MAC implements IHMAC
\r
18 private var hash:IHash;
\r
19 private var bits:uint;
\r
20 private var pad_1:ByteArray;
\r
21 private var pad_2:ByteArray;
\r
22 private var innerHash:ByteArray;
\r
23 private var outerHash:ByteArray;
\r
24 private var outerKey:ByteArray;
\r
25 private var innerKey:ByteArray;
\r
27 * Create a MAC object (for SSL 3.0 ) and
\r
28 * optionally a number of bits to return.
\r
29 * The MAC will be truncated to that size if needed.
\r
31 public function MAC(hash:IHash, bits:uint=0) {
\r
34 innerHash = new ByteArray();
\r
35 outerHash = new ByteArray();
\r
36 innerKey = new ByteArray();
\r
37 outerKey = new ByteArray();
\r
40 if (hash != null) {
\r
41 var pad_size:int = hash.getPadSize();
\r
42 pad_1 = new ByteArray();
\r
43 pad_2 = new ByteArray();
\r
45 for (var x:int = 0; x < pad_size; x++) {
\r
46 pad_1.writeByte(0x36);
\r
47 pad_2.writeByte(0x5c);
\r
52 public function setPadSize(pad_size:int) : void { }
\r
54 public function getHashSize():uint {
\r
58 return hash.getHashSize();
\r
64 * Compute a MAC using a key and some data.
\r
67 public function compute(key:ByteArray, data:ByteArray):ByteArray {
\r
68 // take that incoming key and do hash(key + pad_2 + hash(key + pad_1 + sequence + length + record)
\r
69 // note that data = (sequence + type + length + record)
\r
71 if (pad_1 == null) {
\r
72 var pad_size:int = hash.getPadSize();
\r
73 pad_1 = new ByteArray();
\r
74 pad_2 = new ByteArray();
\r
76 for (var x:int = 0; x < pad_size; x++) {
\r
77 pad_1.writeByte(0x36);
\r
78 pad_2.writeByte(0x5c);
\r
82 // Do some preliminary checking on stuff
\r
84 if (key.length > hash.getInputSize()) {
\r
85 hashKey = hash.hash(key);
\r
87 hashKey = new ByteArray;
\r
88 hashKey.writeBytes(key);
\r
91 while (hashKey.length < hash.getInputSize() ) {
\r
92 hashKey[hashKey.length] = 0;
\r
94 // Henri's conventions work just fine here..
\r
96 innerKey.length = 0;
\r
97 outerKey.length = 0;
\r
98 // trace("MAC Key: " + Hex.fromArray(key));
\r
99 // trace("Key Length: " + key.length);
\r
100 // trace("Pad_1 : " + Hex.fromArray(pad_1));
\r
102 innerKey.writeBytes(key);
\r
103 innerKey.writeBytes(pad_1);
\r
104 innerKey.writeBytes(data);
\r
105 // trace("MAC Inner Key: " + Hex.fromArray(innerKey));
\r
107 innerHash = hash.hash(innerKey);
\r
108 // trace("MAC Inner Hash: " + Hex.fromArray(innerHash));
\r
110 // outer hash calc
\r
111 outerKey.writeBytes(key);
\r
112 outerKey.writeBytes(pad_2);
\r
113 outerKey.writeBytes(innerHash);
\r
115 // trace("MAC Outer Key: " + Hex.fromArray(outerKey));
\r
116 outerHash = hash.hash(outerKey);
\r
119 if (bits > 0 && bits < 8*outerHash.length) {
\r
120 outerHash.length = bits/8;
\r
123 // trace("MAC for record: " + Hex.fromArray(outerHash));
\r
128 public function dispose():void {
\r
132 public function toString():String {
\r
133 return "mac-"+(bits>0?bits+"-":"")+hash.toString();
\r