4 * An ActionScript 3 implementation of a pseudo-random generator
\r
5 * that follows the TLS specification
\r
6 * Copyright (c) 2007 Henri Torgemane
\r
8 * See LICENSE.txt for full license information.
\r
10 package com.hurlant.crypto.prng
\r
12 import flash.utils.ByteArray;
\r
13 import com.hurlant.crypto.hash.HMAC;
\r
14 import com.hurlant.crypto.hash.MD5;
\r
15 import com.hurlant.crypto.hash.SHA1;
\r
16 import com.hurlant.util.Memory;
\r
17 import com.hurlant.util.Hex;
\r
18 import flash.utils.IDataOutput;
\r
21 * There's "Random", and then there's TLS Random.
\r
23 * Still Pseudo-random, though.
\r
27 // XXX WAY TOO MANY STRUCTURES HERE
\r
30 private var seed:ByteArray;
\r
32 private var s1:ByteArray;
\r
34 private var s2:ByteArray;
\r
36 private var a1:ByteArray;
\r
38 private var a2:ByteArray;
\r
40 private var p1:ByteArray;
\r
42 private var p2:ByteArray;
\r
43 // Data for HMAC_MD5
\r
44 private var d1:ByteArray;
\r
45 // Data for HMAC_SHA1
\r
46 private var d2:ByteArray;
\r
49 private var hmac_md5:HMAC;
\r
50 private var hmac_sha1:HMAC;
\r
52 public function TLSPRF(secret:ByteArray, label:String, seed:ByteArray) {
\r
53 var l:int = Math.ceil(secret.length/2);
\r
54 var s1:ByteArray = new ByteArray;
\r
55 var s2:ByteArray = new ByteArray;
\r
56 s1.writeBytes(secret, 0, l);
\r
57 s2.writeBytes(secret, secret.length-l, l);
\r
58 var s:ByteArray = new ByteArray;
\r
59 s.writeUTFBytes(label);
\r
64 hmac_md5 = new HMAC(new MD5);
\r
65 hmac_sha1 = new HMAC(new SHA1);
\r
67 this.a1 = hmac_md5.compute(s1, this.seed);
\r
68 this.a2 = hmac_sha1.compute(s2, this.seed);
\r
75 d1.position = MD5.HASH_SIZE;
\r
76 d1.writeBytes(this.seed);
\r
77 d2.position = SHA1.HASH_SIZE;
\r
78 d2.writeBytes(this.seed);
\r
81 // XXX HORRIBLY SLOW. REWRITE.
\r
82 public function nextBytes(buffer:IDataOutput, length:int):void {
\r
84 buffer.writeByte(nextByte());
\r
87 public function nextByte():int {
\r
88 if (p1.bytesAvailable==0) {
\r
91 if (p2.bytesAvailable==0) {
\r
94 return p1.readUnsignedByte()^p2.readUnsignedByte();
\r
96 public function dispose():void {
\r
106 hmac_md5.dispose();
\r
108 hmac_sha1.dispose();
\r
112 public function toString():String {
\r
115 private function dba(ba:ByteArray):ByteArray {
\r
116 for (var i:uint=0;i<ba.length;i++) {
\r
122 private function more_md5():void {
\r
125 var p:int = p1.position;
\r
126 var more:ByteArray = hmac_md5.compute(s1, d1);
\r
127 a1 = hmac_md5.compute(s1, a1);
\r
128 p1.writeBytes(more);
\r
131 private function more_sha1():void {
\r
134 var p:int = p2.position;
\r
135 var more:ByteArray = hmac_sha1.compute(s2, d2);
\r
136 a2 = hmac_sha1.compute(s2, a2);
\r
137 p2.writeBytes(more);
\r