no commit message
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
/**
|
||||
* ARC4
|
||||
*
|
||||
* An ActionScript 3 implementation of RC4
|
||||
* Copyright (c) 2007 Henri Torgemane
|
||||
*
|
||||
* Derived from:
|
||||
* The jsbn library, Copyright (c) 2003-2005 Tom Wu
|
||||
*
|
||||
* See LICENSE.txt for full license information.
|
||||
*/
|
||||
package com.hurlant.crypto.prng
|
||||
{
|
||||
import com.hurlant.crypto.symmetric.ICipher;
|
||||
import com.hurlant.util.Memory;
|
||||
|
||||
import flash.utils.ByteArray;
|
||||
|
||||
public class ARC4 implements IPRNG, ICipher {
|
||||
private var i:int = 0;
|
||||
private var j:int = 0;
|
||||
private var S:ByteArray;
|
||||
private var key:ByteArray;
|
||||
private const psize:uint = 256;
|
||||
public function ARC4(key:ByteArray = null){
|
||||
S = new ByteArray;
|
||||
if (key) {
|
||||
init(key);
|
||||
}
|
||||
}
|
||||
public function getPoolSize():uint {
|
||||
return psize;
|
||||
}
|
||||
public function init(key:ByteArray):void {
|
||||
this.key = key; //keep a copy, as we need to reset our state for every encrypt/decrypt call.
|
||||
var i:int;
|
||||
var j:int;
|
||||
var t:int;
|
||||
for (i=0; i<256; ++i) {
|
||||
S[i] = i;
|
||||
}
|
||||
j=0;
|
||||
for (i=0; i<256; ++i) {
|
||||
j = (j + S[i] + key[i%key.length]) & 255;
|
||||
t = S[i];
|
||||
S[i] = S[j];
|
||||
S[j] = t;
|
||||
}
|
||||
this.i=0;
|
||||
this.j=0;
|
||||
}
|
||||
public function next():uint {
|
||||
var t:int;
|
||||
i = (i+1)&255;
|
||||
j = (j+S[i])&255;
|
||||
t = S[i];
|
||||
S[i] = S[j];
|
||||
S[j] = t;
|
||||
return S[(t+S[i])&255];
|
||||
}
|
||||
|
||||
public function getBlockSize():uint {
|
||||
return 1;
|
||||
}
|
||||
|
||||
public function encrypt(block:ByteArray):void {
|
||||
init(key);
|
||||
var i:uint = 0;
|
||||
while (i<block.length) {
|
||||
block[i++] ^= next();
|
||||
}
|
||||
}
|
||||
public function decrypt(block:ByteArray):void {
|
||||
encrypt(block); // the beauty of XOR.
|
||||
}
|
||||
public function dispose():void {
|
||||
var i:uint = 0;
|
||||
for (i=0;i<S.length;i++) {
|
||||
S[i] = Math.random()*256;
|
||||
}
|
||||
for (i=0;i<key.length;i++) {
|
||||
key[i] = Math.random()*256;
|
||||
}
|
||||
S.length=0;
|
||||
key.length=0;
|
||||
S = null;
|
||||
key = null;
|
||||
this.i = 0;
|
||||
this.j = 0;
|
||||
Memory.gc();
|
||||
}
|
||||
public function toString():String {
|
||||
return "rc4";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
* IPRNG
|
||||
*
|
||||
* An interface for classes that can be used a pseudo-random number generators
|
||||
* Copyright (c) 2007 Henri Torgemane
|
||||
*
|
||||
* See LICENSE.txt for full license information.
|
||||
*/
|
||||
package com.hurlant.crypto.prng
|
||||
{
|
||||
import flash.utils.ByteArray;
|
||||
|
||||
public interface IPRNG {
|
||||
function getPoolSize():uint;
|
||||
function init(key:ByteArray):void;
|
||||
function next():uint;
|
||||
function dispose():void;
|
||||
function toString():String;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
/**
|
||||
* Random
|
||||
*
|
||||
* An ActionScript 3 implementation of a Random Number Generator
|
||||
* Copyright (c) 2007 Henri Torgemane
|
||||
*
|
||||
* Derived from:
|
||||
* The jsbn library, Copyright (c) 2003-2005 Tom Wu
|
||||
*
|
||||
* See LICENSE.txt for full license information.
|
||||
*/
|
||||
package com.hurlant.crypto.prng
|
||||
{
|
||||
import flash.utils.ByteArray;
|
||||
import com.hurlant.util.Memory;
|
||||
import flash.system.System;
|
||||
import flash.system.Capabilities;
|
||||
import flash.accessibility.AccessibilityProperties;
|
||||
import flash.display.SWFVersion;
|
||||
import flash.display.Stage;
|
||||
import flash.utils.getTimer;
|
||||
import flash.text.Font;
|
||||
|
||||
public class Random
|
||||
{
|
||||
private var state:IPRNG;
|
||||
private var ready:Boolean = false;
|
||||
private var pool:ByteArray;
|
||||
private var psize:int;
|
||||
private var pptr:int;
|
||||
private var seeded:Boolean = false;
|
||||
|
||||
public function Random(prng:Class = null) {
|
||||
if (prng==null) prng = ARC4;
|
||||
state = new prng as IPRNG;
|
||||
psize= state.getPoolSize();
|
||||
pool = new ByteArray;
|
||||
pptr = 0;
|
||||
while (pptr <psize) {
|
||||
var t:uint = 65536*Math.random();
|
||||
pool[pptr++] = t >>> 8;
|
||||
pool[pptr++] = t&255;
|
||||
}
|
||||
pptr=0;
|
||||
seed();
|
||||
}
|
||||
|
||||
public function seed(x:int = 0):void {
|
||||
if (x==0) {
|
||||
x = new Date().getTime();
|
||||
}
|
||||
pool[pptr++] ^= x & 255;
|
||||
pool[pptr++] ^= (x>>8)&255;
|
||||
pool[pptr++] ^= (x>>16)&255;
|
||||
pool[pptr++] ^= (x>>24)&255;
|
||||
pptr %= psize;
|
||||
seeded = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gather anything we have that isn't entirely predictable:
|
||||
* - memory used
|
||||
* - system capabilities
|
||||
* - timing stuff
|
||||
* - installed fonts
|
||||
*/
|
||||
public function autoSeed():void {
|
||||
var b:ByteArray = new ByteArray;
|
||||
b.writeUnsignedInt(System.totalMemory);
|
||||
b.writeUTF(Capabilities.serverString);
|
||||
b.writeUnsignedInt(getTimer());
|
||||
b.writeUnsignedInt((new Date).getTime());
|
||||
var a:Array = Font.enumerateFonts(true);
|
||||
for each (var f:Font in a) {
|
||||
b.writeUTF(f.fontName);
|
||||
b.writeUTF(f.fontStyle);
|
||||
b.writeUTF(f.fontType);
|
||||
}
|
||||
b.position=0;
|
||||
while (b.bytesAvailable>=4) {
|
||||
seed(b.readUnsignedInt());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function nextBytes(buffer:ByteArray, length:int):void {
|
||||
while (length--) {
|
||||
buffer.writeByte(nextByte());
|
||||
}
|
||||
}
|
||||
public function nextByte():int {
|
||||
if (!ready) {
|
||||
if (!seeded) {
|
||||
autoSeed();
|
||||
}
|
||||
state.init(pool);
|
||||
pool.length = 0;
|
||||
pptr = 0;
|
||||
ready = true;
|
||||
}
|
||||
return state.next();
|
||||
}
|
||||
public function dispose():void {
|
||||
for (var i:uint=0;i<pool.length;i++) {
|
||||
pool[i] = Math.random()*256;
|
||||
}
|
||||
pool.length=0;
|
||||
pool = null;
|
||||
state.dispose();
|
||||
state = null;
|
||||
psize = 0;
|
||||
pptr = 0;
|
||||
Memory.gc();
|
||||
}
|
||||
public function toString():String {
|
||||
return "random-"+state.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
package com.hurlant.crypto.prng
|
||||
{
|
||||
import flash.utils.ByteArray;
|
||||
import com.hurlant.crypto.hash.HMAC;
|
||||
import com.hurlant.crypto.hash.MD5;
|
||||
import com.hurlant.crypto.hash.SHA1;
|
||||
import com.hurlant.util.Memory;
|
||||
import com.hurlant.util.Hex;
|
||||
|
||||
/**
|
||||
* There's "Random", and then there's TLS Random.
|
||||
* .
|
||||
* Still Pseudo-random, though.
|
||||
*/
|
||||
public class TLSPRF
|
||||
{
|
||||
// XXX WAY TOO MANY STRUCTURES HERE
|
||||
|
||||
// seed
|
||||
private var seed:ByteArray;
|
||||
// P_MD5's secret
|
||||
private var s1:ByteArray;
|
||||
// P_SHA-1's secret
|
||||
private var s2:ByteArray;
|
||||
// HMAC_MD5's A
|
||||
private var a1:ByteArray;
|
||||
// HMAC_SHA1's A
|
||||
private var a2:ByteArray;
|
||||
// Pool for P_MD5
|
||||
private var p1:ByteArray;
|
||||
// Pool for P_SHA1
|
||||
private var p2:ByteArray;
|
||||
// Data for HMAC_MD5
|
||||
private var d1:ByteArray;
|
||||
// Data for HMAC_SHA1
|
||||
private var d2:ByteArray;
|
||||
|
||||
|
||||
private var hmac_md5:HMAC;
|
||||
private var hmac_sha1:HMAC;
|
||||
|
||||
public function TLSPRF(secret:ByteArray, label:String, seed:ByteArray) {
|
||||
var l:int = Math.ceil(secret.length/2);
|
||||
var s1:ByteArray = new ByteArray;
|
||||
var s2:ByteArray = new ByteArray;
|
||||
s1.writeBytes(secret, 0, l);
|
||||
s2.writeBytes(secret, secret.length-l, l);
|
||||
var s:ByteArray = new ByteArray;
|
||||
s.writeUTFBytes(label);
|
||||
s.writeBytes(seed);
|
||||
this.seed = s;
|
||||
this.s1 = s1;
|
||||
this.s2 = s2;
|
||||
|
||||
hmac_md5 = new HMAC(new MD5);
|
||||
hmac_sha1 = new HMAC(new SHA1);
|
||||
|
||||
this.a1 = hmac_md5.compute(s1, this.seed);
|
||||
this.a2 = hmac_sha1.compute(s2, this.seed);
|
||||
|
||||
p1 = new ByteArray;
|
||||
p2 = new ByteArray;
|
||||
|
||||
d1 = new ByteArray;
|
||||
d2 = new ByteArray;
|
||||
d1.position = MD5.HASH_SIZE;
|
||||
d1.writeBytes(this.seed);
|
||||
d2.position = SHA1.HASH_SIZE;
|
||||
d2.writeBytes(this.seed);
|
||||
}
|
||||
// XXX HORRIBLY SLOW. REWRITE.
|
||||
public function nextBytes(buffer:ByteArray, length:int):void {
|
||||
while (length--) {
|
||||
buffer.writeByte(nextByte());
|
||||
}
|
||||
}
|
||||
public function nextByte():int {
|
||||
if (p1.bytesAvailable==0) {
|
||||
more_md5();
|
||||
}
|
||||
if (p2.bytesAvailable==0) {
|
||||
more_sha1();
|
||||
}
|
||||
return p1.readUnsignedByte()^p2.readUnsignedByte();
|
||||
}
|
||||
public function dispose():void {
|
||||
seed = dba(seed);
|
||||
s1 = dba(s1);
|
||||
s2 = dba(s2);
|
||||
a1 = dba(a1);
|
||||
a2 = dba(a2);
|
||||
p1 = dba(p1);
|
||||
p2 = dba(p2);
|
||||
d1 = dba(d1);
|
||||
d2 = dba(d2);
|
||||
hmac_md5.dispose();
|
||||
hmac_md5 = null;
|
||||
hmac_sha1.dispose();
|
||||
hmac_sha1 = null;
|
||||
Memory.gc();
|
||||
}
|
||||
public function toString():String {
|
||||
return "tls-prf";
|
||||
}
|
||||
private function dba(ba:ByteArray):ByteArray {
|
||||
for (var i:uint=0;i<ba.length;i++) {
|
||||
ba[i]=0;
|
||||
}
|
||||
ba.length=0;
|
||||
return null;
|
||||
}
|
||||
private function more_md5():void {
|
||||
d1.position=0;
|
||||
d1.writeBytes(a1);
|
||||
var p:int = p1.position;
|
||||
var more:ByteArray = hmac_md5.compute(s1, d1);
|
||||
a1 = hmac_md5.compute(s1, a1);
|
||||
p1.writeBytes(more);
|
||||
p1.position=p;
|
||||
}
|
||||
private function more_sha1():void {
|
||||
d2.position=0;
|
||||
d2.writeBytes(a2);
|
||||
var p:int = p2.position;
|
||||
var more:ByteArray = hmac_sha1.compute(s2, d2);
|
||||
a2 = hmac_sha1.compute(s2, a2);
|
||||
p2.writeBytes(more);
|
||||
p2.position=p;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user