/flash-src/third-party/com/hurlant/crypto/prng/TLSPRF.as

http://github.com/gimite/web-socket-js · ActionScript · 142 lines · 107 code · 10 blank · 25 comment · 4 complexity · 3cfc54c6c87288574d5d2c545d45435a MD5 · raw file

  1. /**
  2. * TLSPRF
  3. *
  4. * An ActionScript 3 implementation of a pseudo-random generator
  5. * that follows the TLS specification
  6. * Copyright (c) 2007 Henri Torgemane
  7. *
  8. * See LICENSE.txt for full license information.
  9. */
  10. package com.hurlant.crypto.prng
  11. {
  12. import flash.utils.ByteArray;
  13. import com.hurlant.crypto.hash.HMAC;
  14. import com.hurlant.crypto.hash.MD5;
  15. import com.hurlant.crypto.hash.SHA1;
  16. import com.hurlant.util.Memory;
  17. import com.hurlant.util.Hex;
  18. import flash.utils.IDataOutput;
  19. /**
  20. * There's "Random", and then there's TLS Random.
  21. * .
  22. * Still Pseudo-random, though.
  23. */
  24. public class TLSPRF
  25. {
  26. // XXX WAY TOO MANY STRUCTURES HERE
  27. // seed
  28. private var seed:ByteArray;
  29. // P_MD5's secret
  30. private var s1:ByteArray;
  31. // P_SHA-1's secret
  32. private var s2:ByteArray;
  33. // HMAC_MD5's A
  34. private var a1:ByteArray;
  35. // HMAC_SHA1's A
  36. private var a2:ByteArray;
  37. // Pool for P_MD5
  38. private var p1:ByteArray;
  39. // Pool for P_SHA1
  40. private var p2:ByteArray;
  41. // Data for HMAC_MD5
  42. private var d1:ByteArray;
  43. // Data for HMAC_SHA1
  44. private var d2:ByteArray;
  45. private var hmac_md5:HMAC;
  46. private var hmac_sha1:HMAC;
  47. public function TLSPRF(secret:ByteArray, label:String, seed:ByteArray) {
  48. var l:int = Math.ceil(secret.length/2);
  49. var s1:ByteArray = new ByteArray;
  50. var s2:ByteArray = new ByteArray;
  51. s1.writeBytes(secret, 0, l);
  52. s2.writeBytes(secret, secret.length-l, l);
  53. var s:ByteArray = new ByteArray;
  54. s.writeUTFBytes(label);
  55. s.writeBytes(seed);
  56. this.seed = s;
  57. this.s1 = s1;
  58. this.s2 = s2;
  59. hmac_md5 = new HMAC(new MD5);
  60. hmac_sha1 = new HMAC(new SHA1);
  61. this.a1 = hmac_md5.compute(s1, this.seed);
  62. this.a2 = hmac_sha1.compute(s2, this.seed);
  63. p1 = new ByteArray;
  64. p2 = new ByteArray;
  65. d1 = new ByteArray;
  66. d2 = new ByteArray;
  67. d1.position = MD5.HASH_SIZE;
  68. d1.writeBytes(this.seed);
  69. d2.position = SHA1.HASH_SIZE;
  70. d2.writeBytes(this.seed);
  71. }
  72. // XXX HORRIBLY SLOW. REWRITE.
  73. public function nextBytes(buffer:IDataOutput, length:int):void {
  74. while (length--) {
  75. buffer.writeByte(nextByte());
  76. }
  77. }
  78. public function nextByte():int {
  79. if (p1.bytesAvailable==0) {
  80. more_md5();
  81. }
  82. if (p2.bytesAvailable==0) {
  83. more_sha1();
  84. }
  85. return p1.readUnsignedByte()^p2.readUnsignedByte();
  86. }
  87. public function dispose():void {
  88. seed = dba(seed);
  89. s1 = dba(s1);
  90. s2 = dba(s2);
  91. a1 = dba(a1);
  92. a2 = dba(a2);
  93. p1 = dba(p1);
  94. p2 = dba(p2);
  95. d1 = dba(d1);
  96. d2 = dba(d2);
  97. hmac_md5.dispose();
  98. hmac_md5 = null;
  99. hmac_sha1.dispose();
  100. hmac_sha1 = null;
  101. Memory.gc();
  102. }
  103. public function toString():String {
  104. return "tls-prf";
  105. }
  106. private function dba(ba:ByteArray):ByteArray {
  107. for (var i:uint=0;i<ba.length;i++) {
  108. ba[i]=0;
  109. }
  110. ba.length=0;
  111. return null;
  112. }
  113. private function more_md5():void {
  114. d1.position=0;
  115. d1.writeBytes(a1);
  116. var p:int = p1.position;
  117. var more:ByteArray = hmac_md5.compute(s1, d1);
  118. a1 = hmac_md5.compute(s1, a1);
  119. p1.writeBytes(more);
  120. p1.position=p;
  121. }
  122. private function more_sha1():void {
  123. d2.position=0;
  124. d2.writeBytes(a2);
  125. var p:int = p2.position;
  126. var more:ByteArray = hmac_sha1.compute(s2, d2);
  127. a2 = hmac_sha1.compute(s2, a2);
  128. p2.writeBytes(more);
  129. p2.position=p;
  130. }
  131. }
  132. }