aboutsummaryrefslogtreecommitdiffstats
path: root/signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls
diff options
context:
space:
mode:
Diffstat (limited to 'signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls')
-rw-r--r--signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/BulkCiphers.as102
-rw-r--r--signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/CipherSuites.as117
-rw-r--r--signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/IConnectionState.as14
-rwxr-xr-xsignaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/ISecurityParameters.as29
-rw-r--r--signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/KeyExchanges.as24
-rw-r--r--signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/MACs.as38
-rw-r--r--signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/SSLConnectionState.as171
-rwxr-xr-xsignaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/SSLEvent.as26
-rwxr-xr-xsignaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/SSLSecurityParameters.as340
-rw-r--r--signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/TLSConfig.as70
-rw-r--r--signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/TLSConnectionState.as151
-rw-r--r--signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/TLSEngine.as895
-rw-r--r--signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/TLSError.as39
-rw-r--r--signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/TLSEvent.as27
-rw-r--r--signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/TLSSecurityParameters.as197
-rw-r--r--signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/TLSSocket.as370
-rw-r--r--signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/TLSSocketEvent.as26
-rw-r--r--signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/TLSTest.as180
18 files changed, 2816 insertions, 0 deletions
diff --git a/signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/BulkCiphers.as b/signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/BulkCiphers.as
new file mode 100644
index 0000000..2b1e717
--- /dev/null
+++ b/signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/BulkCiphers.as
@@ -0,0 +1,102 @@
+/**
+ * BulkCiphers
+ *
+ * An enumeration of bulk ciphers available for TLS, along with their properties,
+ * with a few convenience methods to go with it.
+ * Copyright (c) 2007 Henri Torgemane
+ *
+ * See LICENSE.txt for full license information.
+ */
+package com.hurlant.crypto.tls {
+ import com.hurlant.crypto.Crypto;
+ import flash.utils.ByteArray;
+ import com.hurlant.crypto.symmetric.ICipher;
+ import com.hurlant.crypto.symmetric.TLSPad;
+ import com.hurlant.crypto.symmetric.SSLPad;
+
+ public class BulkCiphers {
+ public static const STREAM_CIPHER:uint = 0;
+ public static const BLOCK_CIPHER:uint = 1;
+
+ public static const NULL:uint = 0;
+ public static const RC4_40:uint = 1;
+ public static const RC4_128:uint = 2
+ public static const RC2_CBC_40:uint = 3; // XXX I don't have that one.
+ public static const DES_CBC:uint = 4;
+ public static const DES3_EDE_CBC:uint = 5;
+ public static const DES40_CBC:uint = 6;
+ public static const IDEA_CBC:uint = 7; // XXX I don't have that one.
+ public static const AES_128:uint = 8;
+ public static const AES_256:uint = 9;
+
+ private static const algos:Array =
+ ['', 'rc4', 'rc4', '', 'des-cbc', '3des-cbc', 'des-cbc', '', 'aes', 'aes'];
+
+ private static var _props:Array;
+
+ init();
+ private static function init():void {
+ _props = [];
+ _props[NULL] = new BulkCiphers(STREAM_CIPHER, 0, 0, 0, 0, 0);
+ _props[RC4_40] = new BulkCiphers(STREAM_CIPHER, 5, 16, 40, 0, 0);
+ _props[RC4_128] = new BulkCiphers(STREAM_CIPHER, 16, 16, 128, 0, 0);
+ _props[RC2_CBC_40] = new BulkCiphers( BLOCK_CIPHER, 5, 16, 40, 8, 8);
+ _props[DES_CBC] = new BulkCiphers( BLOCK_CIPHER, 8, 8, 56, 8, 8);
+ _props[DES3_EDE_CBC] = new BulkCiphers( BLOCK_CIPHER, 24, 24, 168, 8, 8);
+ _props[DES40_CBC] = new BulkCiphers( BLOCK_CIPHER, 5, 8, 40, 8, 8);
+ _props[IDEA_CBC] = new BulkCiphers( BLOCK_CIPHER, 16, 16, 128, 8, 8);
+ _props[AES_128] = new BulkCiphers( BLOCK_CIPHER, 16, 16, 128, 16, 16);
+ _props[AES_256] = new BulkCiphers( BLOCK_CIPHER, 32, 32, 256, 16, 16);
+ }
+
+ private static function getProp(cipher:uint):BulkCiphers {
+ var p:BulkCiphers = _props[cipher];
+ if (p==null) {
+ throw new Error("Unknown bulk cipher "+cipher.toString(16));
+ }
+ return p;
+ }
+ public static function getType(cipher:uint):uint {
+ return getProp(cipher).type;
+ }
+ public static function getKeyBytes(cipher:uint):uint {
+ return getProp(cipher).keyBytes;
+ }
+ public static function getExpandedKeyBytes(cipher:uint):uint {
+ return getProp(cipher).expandedKeyBytes;
+ }
+ public static function getEffectiveKeyBits(cipher:uint):uint {
+ return getProp(cipher).effectiveKeyBits;
+ }
+ public static function getIVSize(cipher:uint):uint {
+ return getProp(cipher).IVSize;
+ }
+ public static function getBlockSize(cipher:uint):uint {
+ return getProp(cipher).blockSize;
+ }
+ public static function getCipher(cipher:uint, key:ByteArray, proto:uint):ICipher {
+ if (proto == TLSSecurityParameters.PROTOCOL_VERSION) {
+ return Crypto.getCipher(algos[cipher], key, new TLSPad);
+ } else {
+ return Crypto.getCipher(algos[cipher], key, new SSLPad);
+ }
+ }
+
+
+ private var type:uint;
+ private var keyBytes:uint;
+ private var expandedKeyBytes:uint;
+ private var effectiveKeyBits:uint;
+ private var IVSize:uint;
+ private var blockSize:uint;
+
+ public function BulkCiphers(t:uint, kb:uint, ekb:uint, fkb:uint, ivs:uint, bs:uint) {
+ type = t;
+ keyBytes = kb;
+ expandedKeyBytes = ekb;
+ effectiveKeyBits = fkb;
+ IVSize = ivs;
+ blockSize = bs;
+ }
+ }
+}
diff --git a/signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/CipherSuites.as b/signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/CipherSuites.as
new file mode 100644
index 0000000..e9beb0a
--- /dev/null
+++ b/signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/CipherSuites.as
@@ -0,0 +1,117 @@
+/**
+ * CipherSuites
+ *
+ * An enumeration of cipher-suites available for TLS to use, along with
+ * their properties, and some convenience methods
+ * Copyright (c) 2007 Henri Torgemane
+ *
+ * See LICENSE.txt for full license information.
+ */
+package com.hurlant.crypto.tls {
+ import com.hurlant.crypto.hash.MD5;
+ import com.hurlant.crypto.hash.SHA1;
+
+ public class CipherSuites {
+
+
+ // only the lines marked "ok" are currently implemented.
+
+ // rfc 2246
+
+ public static const TLS_NULL_WITH_NULL_NULL:uint = 0x0000; // ok
+ public static const TLS_RSA_WITH_NULL_MD5:uint = 0x0001; // ok
+ public static const TLS_RSA_WITH_NULL_SHA:uint = 0x0002; // ok
+ public static const TLS_RSA_WITH_RC4_128_MD5:uint = 0x0004; // ok
+ public static const TLS_RSA_WITH_RC4_128_SHA:uint = 0x0005; // ok
+ public static const TLS_RSA_WITH_IDEA_CBC_SHA:uint = 0x0007;
+ public static const TLS_RSA_WITH_DES_CBC_SHA:uint = 0x0009; // ok
+ public static const TLS_RSA_WITH_3DES_EDE_CBC_SHA:uint = 0x000A; // ok
+
+ public static const TLS_DH_DSS_WITH_DES_CBC_SHA:uint = 0x000C;
+ public static const TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA:uint = 0x000D;
+ public static const TLS_DH_RSA_WITH_DES_CBC_SHA:uint = 0x000F;
+ public static const TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA:uint = 0x0010;
+ public static const TLS_DHE_DSS_WITH_DES_CBC_SHA:uint = 0x0012;
+ public static const TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA:uint = 0x0013;
+ public static const TLS_DHE_RSA_WITH_DES_CBC_SHA:uint = 0x0015;
+ public static const TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA:uint = 0x0016;
+
+ public static const TLS_DH_anon_WITH_RC4_128_MD5:uint = 0x0018;
+ public static const TLS_DH_anon_WITH_DES_CBC_SHA:uint = 0x001A;
+ public static const TLS_DH_anon_WITH_3DES_EDE_CBC_SHA:uint = 0x001B;
+
+ // rfc3268
+
+ public static const TLS_RSA_WITH_AES_128_CBC_SHA:uint = 0x002F; // ok
+ public static const TLS_DH_DSS_WITH_AES_128_CBC_SHA:uint = 0x0030;
+ public static const TLS_DH_RSA_WITH_AES_128_CBC_SHA:uint = 0x0031;
+ public static const TLS_DHE_DSS_WITH_AES_128_CBC_SHA:uint = 0x0032;
+ public static const TLS_DHE_RSA_WITH_AES_128_CBC_SHA:uint = 0x0033;
+ public static const TLS_DH_anon_WITH_AES_128_CBC_SHA:uint = 0x0034;
+
+ public static const TLS_RSA_WITH_AES_256_CBC_SHA:uint = 0x0035; // ok
+ public static const TLS_DH_DSS_WITH_AES_256_CBC_SHA:uint = 0x0036;
+ public static const TLS_DH_RSA_WITH_AES_256_CBC_SHA:uint = 0x0037;
+ public static const TLS_DHE_DSS_WITH_AES_256_CBC_SHA:uint = 0x0038;
+ public static const TLS_DHE_RSA_WITH_AES_256_CBC_SHA:uint = 0x0039;
+ public static const TLS_DH_anon_WITH_AES_256_CBC_SHA:uint = 0x003A;
+
+ private static var _props:Array;
+
+ init();
+ private static function init():void {
+ _props = [];
+ _props[TLS_NULL_WITH_NULL_NULL] = new CipherSuites(BulkCiphers.NULL, MACs.NULL, KeyExchanges.NULL);
+ _props[TLS_RSA_WITH_NULL_MD5] = new CipherSuites(BulkCiphers.NULL, MACs.MD5, KeyExchanges.RSA);
+ _props[TLS_RSA_WITH_NULL_SHA] = new CipherSuites(BulkCiphers.NULL, MACs.SHA1, KeyExchanges.RSA);
+ _props[TLS_RSA_WITH_RC4_128_MD5] = new CipherSuites(BulkCiphers.RC4_128, MACs.MD5, KeyExchanges.RSA);
+ _props[TLS_RSA_WITH_RC4_128_SHA] = new CipherSuites(BulkCiphers.RC4_128, MACs.SHA1, KeyExchanges.RSA);
+ _props[TLS_RSA_WITH_DES_CBC_SHA] = new CipherSuites(BulkCiphers.DES_CBC, MACs.SHA1, KeyExchanges.RSA);
+ _props[TLS_RSA_WITH_3DES_EDE_CBC_SHA] = new CipherSuites(BulkCiphers.DES3_EDE_CBC, MACs.SHA1, KeyExchanges.RSA);
+ _props[TLS_RSA_WITH_AES_128_CBC_SHA] = new CipherSuites(BulkCiphers.AES_128, MACs.SHA1, KeyExchanges.RSA);
+ _props[TLS_RSA_WITH_AES_256_CBC_SHA] = new CipherSuites(BulkCiphers.AES_256, MACs.SHA1, KeyExchanges.RSA);
+
+ // ...
+ // more later
+ }
+
+ private static function getProp(cipher:uint):CipherSuites {
+ var p:CipherSuites = _props[cipher];
+ if (p==null) {
+ throw new Error("Unknown cipher "+cipher.toString(16));
+ }
+ return p;
+ }
+ public static function getBulkCipher(cipher:uint):uint {
+ return getProp(cipher).cipher;
+ }
+ public static function getMac(cipher:uint):uint {
+ return getProp(cipher).hash;
+ }
+ public static function getKeyExchange(cipher:uint):uint {
+ return getProp(cipher).key;
+ }
+
+ public static function getDefaultSuites():Array {
+ // a list of acceptable ciphers, sorted by preference.
+ return [
+ TLS_RSA_WITH_AES_256_CBC_SHA,
+ TLS_RSA_WITH_3DES_EDE_CBC_SHA,
+ TLS_RSA_WITH_AES_128_CBC_SHA,
+ TLS_RSA_WITH_RC4_128_SHA,
+ TLS_RSA_WITH_RC4_128_MD5,
+ TLS_RSA_WITH_DES_CBC_SHA
+ ];
+ }
+
+ public var cipher:uint;
+ public var hash:uint;
+ public var key:uint;
+
+ public function CipherSuites(cipher:uint, hash:uint, key:uint) {
+ this.cipher = cipher;
+ this.hash = hash;
+ this.key = key;
+ }
+ }
+}
diff --git a/signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/IConnectionState.as b/signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/IConnectionState.as
new file mode 100644
index 0000000..a5f0e11
--- /dev/null
+++ b/signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/IConnectionState.as
@@ -0,0 +1,14 @@
+/**
+ * IConnectionState
+ *
+ * Interface for TLS/SSL Connection states.
+ *
+ * See LICENSE.txt for full license information.
+ */
+package com.hurlant.crypto.tls {
+ import flash.utils.ByteArray;
+ public interface IConnectionState {
+ function decrypt(type:uint, length:uint, p:ByteArray) : ByteArray;
+ function encrypt(type:uint, p:ByteArray) : ByteArray;
+ }
+} \ No newline at end of file
diff --git a/signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/ISecurityParameters.as b/signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/ISecurityParameters.as
new file mode 100755
index 0000000..3c18aa3
--- /dev/null
+++ b/signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/ISecurityParameters.as
@@ -0,0 +1,29 @@
+/**
+ * ISecurityParameters
+ *
+ * This class encapsulates all the security parameters that get negotiated
+ * during the TLS handshake. It also holds all the key derivation methods.
+ * Copyright (c) 2007 Henri Torgemane
+ *
+ * See LICENSE.txt for full license information.
+ */
+package com.hurlant.crypto.tls {
+ import flash.utils.ByteArray;
+
+ public interface ISecurityParameters {
+ function get version() : uint;
+ function reset():void;
+ function getBulkCipher():uint;
+ function getCipherType():uint;
+ function getMacAlgorithm():uint;
+ function setCipher(cipher:uint):void;
+ function setCompression(algo:uint):void;
+ function setPreMasterSecret(secret:ByteArray):void;
+ function setClientRandom(secret:ByteArray):void;
+ function setServerRandom(secret:ByteArray):void;
+ function get useRSA():Boolean;
+ function computeVerifyData(side:uint, handshakeMessages:ByteArray):ByteArray;
+ function computeCertificateVerify( side:uint, handshakeRecords:ByteArray):ByteArray;
+ function getConnectionStates():Object;
+ }
+} \ No newline at end of file
diff --git a/signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/KeyExchanges.as b/signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/KeyExchanges.as
new file mode 100644
index 0000000..8b9fd0d
--- /dev/null
+++ b/signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/KeyExchanges.as
@@ -0,0 +1,24 @@
+/**
+ * KeyExchanges
+ *
+ * An enumeration of key exchange methods defined by TLS
+ * ( right now, only RSA is actually implemented )
+ * Copyright (c) 2007 Henri Torgemane
+ *
+ * See LICENSE.txt for full license information.
+ */
+package com.hurlant.crypto.tls {
+ public class KeyExchanges {
+ public static const NULL:uint = 0;
+ public static const RSA:uint = 1;
+ public static const DH_DSS:uint = 2;
+ public static const DH_RSA:uint = 3;
+ public static const DHE_DSS:uint = 4;
+ public static const DHE_RSA:uint = 5;
+ public static const DH_anon:uint = 6;
+
+ public static function useRSA(p:uint):Boolean {
+ return (p==RSA);
+ }
+ }
+} \ No newline at end of file
diff --git a/signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/MACs.as b/signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/MACs.as
new file mode 100644
index 0000000..09d79e7
--- /dev/null
+++ b/signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/MACs.as
@@ -0,0 +1,38 @@
+/**
+ * MACs
+ *
+ * An enumeration of MACs implemented for TLS 1.0/SSL 3.0
+ * Copyright (c) 2007 Henri Torgemane
+ *
+ * See LICENSE.txt for full license information.
+ */
+package com.hurlant.crypto.tls {
+ import com.hurlant.crypto.Crypto;
+ import com.hurlant.crypto.hash.HMAC;
+ import com.hurlant.crypto.hash.MAC;
+
+ public class MACs {
+ public static const NULL:uint = 0;
+ public static const MD5:uint = 1;
+ public static const SHA1:uint = 2;
+
+ public static function getHashSize(hash:uint):uint {
+ return [0,16,20][hash];
+ }
+
+ public static function getPadSize(hash:uint):int {
+ return [0, 48, 40][hash];
+ }
+
+ public static function getHMAC(hash:uint):HMAC {
+ if (hash==NULL) return null;
+ return Crypto.getHMAC(['',"md5","sha1"][hash]);
+ }
+
+ public static function getMAC(hash:uint):MAC {
+ return Crypto.getMAC(['', "md5", "sha1"][hash]);
+ }
+
+
+ }
+} \ No newline at end of file
diff --git a/signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/SSLConnectionState.as b/signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/SSLConnectionState.as
new file mode 100644
index 0000000..1ef9c38
--- /dev/null
+++ b/signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/SSLConnectionState.as
@@ -0,0 +1,171 @@
+/**
+ * TLSConnectionState
+ *
+ * This class encapsulates the read or write state of a TLS connection,
+ * and implementes the encrypting and hashing of packets.
+ * Copyright (c) 2007 Henri Torgemane
+ *
+ * See LICENSE.txt for full license information.
+ */
+package com.hurlant.crypto.tls {
+ import flash.utils.IDataInput;
+ import flash.utils.ByteArray;
+ import com.hurlant.crypto.hash.MD5;
+ import com.hurlant.crypto.hash.MAC;
+ import com.hurlant.crypto.hash.IHash;
+ import com.hurlant.crypto.symmetric.ICipher;
+ import com.hurlant.crypto.symmetric.IVMode;
+ import com.hurlant.util.Hex;
+ import com.hurlant.util.ArrayUtil;
+
+ public class SSLConnectionState implements IConnectionState {
+
+ // compression state
+
+ // cipher state
+ private var bulkCipher:uint;
+ private var cipherType:uint;
+ private var CIPHER_key:ByteArray;
+ private var CIPHER_IV:ByteArray;
+ private var cipher:ICipher;
+ private var ivmode:IVMode;
+
+ // mac secret
+ private var macAlgorithm:uint;
+ private var MAC_write_secret:ByteArray;
+ private var mac:MAC;
+
+ // sequence number. uint64
+
+ private var seq_lo:uint = 0x0;
+ private var seq_hi:uint = 0x0;
+
+ public function SSLConnectionState(
+ bulkCipher:uint=0, cipherType:uint=0, macAlgorithm:uint=0,
+ mac_enc:ByteArray=null, key:ByteArray=null, IV:ByteArray=null) {
+ this.bulkCipher = bulkCipher;
+ this.cipherType = cipherType;
+ this.macAlgorithm = macAlgorithm;
+ MAC_write_secret = mac_enc;
+ mac = MACs.getMAC(macAlgorithm);
+
+ CIPHER_key = key;
+ CIPHER_IV = IV;
+ cipher = BulkCiphers.getCipher(bulkCipher, key, 0x0300);
+ if (cipher is IVMode) {
+ ivmode = cipher as IVMode;
+ ivmode.IV = IV;
+ }
+
+ }
+
+ public function decrypt(type:uint, length:uint, p:ByteArray):ByteArray {
+ // decompression is a nop.
+
+ if (cipherType == BulkCiphers.STREAM_CIPHER) {
+ if (bulkCipher == BulkCiphers.NULL) {
+ // no-op
+ } else {
+ cipher.decrypt(p);
+ }
+ } else {
+ p.position = 0;
+ // block cipher
+ if (bulkCipher == BulkCiphers.NULL) {
+
+ } else {
+ var nextIV:ByteArray = new ByteArray;
+ nextIV.writeBytes(p, p.length-CIPHER_IV.length, CIPHER_IV.length);
+ p.position = 0;
+ cipher.decrypt(p);
+
+ CIPHER_IV = nextIV;
+ ivmode.IV = nextIV;
+ }
+ }
+
+ if (macAlgorithm!=MACs.NULL) {
+ // there will be CTX delay here as well,
+ // I should probably optmize the hell out of it
+ var data:ByteArray = new ByteArray;
+ var len:uint = p.length - mac.getHashSize();
+ data.writeUnsignedInt(seq_hi);
+ data.writeUnsignedInt(seq_lo);
+
+ data.writeByte(type);
+ data.writeShort(len);
+ if (len!=0) {
+ data.writeBytes(p, 0, len);
+ }
+ var mac_enc:ByteArray = mac.compute(MAC_write_secret, data);
+ // compare "mac" with the last X bytes of p.
+ var mac_received:ByteArray = new ByteArray;
+ mac_received.writeBytes(p, len, mac.getHashSize());
+ if (ArrayUtil.equals(mac_enc, mac_received)) {
+ // happy happy joy joy
+ } else {
+ throw new TLSError("Bad Mac Data", TLSError.bad_record_mac);
+ }
+ p.length = len;
+ p.position = 0;
+ }
+ // increment seq
+ seq_lo++;
+ if (seq_lo==0) seq_hi++;
+ return p;
+ }
+ public function encrypt(type:uint, p:ByteArray):ByteArray {
+ var mac_enc:ByteArray = null;
+ if (macAlgorithm!=MACs.NULL) {
+ var data:ByteArray = new ByteArray;
+ // data.writeUnsignedInt(seq);
+
+ // Sequence
+ data.writeUnsignedInt(seq_hi);
+ data.writeUnsignedInt(seq_lo);
+
+ // Type
+ data.writeByte(type);
+
+ // Length
+ data.writeShort(p.length);
+
+ // The data
+ if (p.length!=0) {
+ data.writeBytes(p);
+ }
+
+ // trace("data for the MAC: " + Hex.fromArray(data));
+ mac_enc = mac.compute(MAC_write_secret, data);
+ // trace("MAC: " + Hex.fromArray( mac_enc ));
+ p.position = p.length;
+ p.writeBytes(mac_enc);
+ }
+
+ // trace("Record to encrypt: " + Hex.fromArray(p));
+
+ p.position = 0;
+ if (cipherType == BulkCiphers.STREAM_CIPHER) {
+ // stream cipher
+ if (bulkCipher == BulkCiphers.NULL) {
+ // no-op
+ } else {
+ cipher.encrypt(p);
+ }
+ } else {
+ // block cipher
+ cipher.encrypt(p);
+ // adjust IV
+ var nextIV:ByteArray = new ByteArray;
+ nextIV.writeBytes(p, p.length-CIPHER_IV.length, CIPHER_IV.length);
+ CIPHER_IV = nextIV;
+ ivmode.IV = nextIV;
+ }
+ // increment seq
+ seq_lo++;
+ if (seq_lo==0) seq_hi++;
+ return p;
+ }
+
+ }
+} \ No newline at end of file
diff --git a/signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/SSLEvent.as b/signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/SSLEvent.as
new file mode 100755
index 0000000..9a63521
--- /dev/null
+++ b/signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/SSLEvent.as
@@ -0,0 +1,26 @@
+/**
+ * SSLEvent
+ *
+ * This is used by TLSEngine to let the application layer know
+ * when we're ready for sending, or have received application data
+ * This Event was created by Bobby Parker to support SSL 3.0.
+ *
+ * See LICENSE.txt for full license information.
+ */
+package com.hurlant.crypto.tls {
+ import flash.events.Event;
+ import flash.utils.ByteArray;
+
+ public class SSLEvent extends Event {
+
+ static public const DATA:String = "data";
+ static public const READY:String = "ready";
+
+ public var data:ByteArray;
+
+ public function SSLEvent(type:String, data:ByteArray = null) {
+ this.data = data;
+ super(type, false, false);
+ }
+ }
+} \ No newline at end of file
diff --git a/signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/SSLSecurityParameters.as b/signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/SSLSecurityParameters.as
new file mode 100755
index 0000000..3549461
--- /dev/null
+++ b/signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/SSLSecurityParameters.as
@@ -0,0 +1,340 @@
+/**
+ * TLSSecurityParameters
+ *
+ * This class encapsulates all the security parameters that get negotiated
+ * during the TLS handshake. It also holds all the key derivation methods.
+ * Copyright (c) 2007 Henri Torgemane
+ *
+ * See LICENSE.txt for full license information.
+ */
+package com.hurlant.crypto.tls {
+ import com.hurlant.crypto.hash.MD5;
+ import com.hurlant.crypto.hash.SHA1;
+ import com.hurlant.util.Hex;
+
+ import flash.utils.ByteArray;
+
+ public class SSLSecurityParameters implements ISecurityParameters {
+
+ // COMPRESSION
+ public static const COMPRESSION_NULL:uint = 0;
+
+ private var entity:uint; // SERVER | CLIENT
+ private var bulkCipher:uint; // BULK_CIPHER_*
+ private var cipherType:uint; // STREAM_CIPHER | BLOCK_CIPHER
+ private var keySize:uint;
+ private var keyMaterialLength:uint;
+ private var keyBlock:ByteArray;
+ private var IVSize:uint;
+ private var MAC_length:uint;
+ private var macAlgorithm:uint; // MAC_*
+ private var hashSize:uint;
+ private var compression:uint; // COMPRESSION_NULL
+ private var masterSecret:ByteArray; // 48 bytes
+ private var clientRandom:ByteArray; // 32 bytes
+ private var serverRandom:ByteArray; // 32 bytes
+ private var pad_1:ByteArray; // varies
+ private var pad_2:ByteArray; // varies
+ private var ignoreCNMismatch:Boolean = true;
+ private var trustAllCerts:Boolean = false;
+ private var trustSelfSigned:Boolean = false;
+ public static const PROTOCOL_VERSION:uint = 0x0300;
+
+ // not strictly speaking part of this, but yeah.
+ public var keyExchange:uint;
+
+ public function get version() : uint {
+ return PROTOCOL_VERSION;
+ }
+ public function SSLSecurityParameters(entity:uint, localCert:ByteArray = null, localKey:ByteArray = null) {
+ this.entity = entity;
+ reset();
+ }
+
+ public function reset():void {
+ bulkCipher = BulkCiphers.NULL;
+ cipherType = BulkCiphers.BLOCK_CIPHER;
+ macAlgorithm = MACs.NULL;
+ compression = COMPRESSION_NULL;
+ masterSecret = null;
+ }
+
+ public function getBulkCipher():uint {
+ return bulkCipher;
+ }
+ public function getCipherType():uint {
+ return cipherType;
+ }
+ public function getMacAlgorithm():uint {
+ return macAlgorithm;
+ }
+
+ public function setCipher(cipher:uint):void {
+ bulkCipher = CipherSuites.getBulkCipher(cipher);
+ cipherType = BulkCiphers.getType(bulkCipher);
+ keySize = BulkCiphers.getExpandedKeyBytes(bulkCipher); // 8
+ keyMaterialLength = BulkCiphers.getKeyBytes(bulkCipher); // 5
+ IVSize = BulkCiphers.getIVSize(bulkCipher);
+
+
+ keyExchange = CipherSuites.getKeyExchange(cipher);
+
+ macAlgorithm = CipherSuites.getMac(cipher);
+ hashSize = MACs.getHashSize(macAlgorithm);
+ pad_1 = new ByteArray();
+ pad_2 = new ByteArray();
+ for (var x:int = 0; x < 48; x++) {
+ pad_1.writeByte(0x36);
+ pad_2.writeByte(0x5c);
+ }
+ }
+ public function setCompression(algo:uint):void {
+ compression = algo;
+ }
+
+ public function setPreMasterSecret(secret:ByteArray):void {
+ /* Warning! Following code may cause madness
+ Tread not here, unless ye be men of valor.
+
+ ***** Official Prophylactic Comment ******
+ (to protect the unwary...this code actually works, that's all you need to know)
+
+ This does two things, computes the master secret, and generates the keyBlock
+
+
+ To compute the master_secret, the following algorithm is used.
+ for SSL 3, this means
+ master = MD5( premaster + SHA1('A' + premaster + client_random + server_random ) ) +
+ MD5( premaster + SHA1('BB' + premaster + client_random + server_random ) ) +
+ MD5( premaster + SHA1('CCC' + premaster + client_random + server_random ) )
+ */
+ var tempHashA:ByteArray = new ByteArray(); // temporary hash, gets reused a lot
+ var tempHashB:ByteArray = new ByteArray(); // temporary hash, gets reused a lot
+
+ var shaHash:ByteArray;
+ var mdHash:ByteArray;
+
+ var i:int;
+ var j:int;
+
+ var sha:SHA1 = new SHA1();
+ var md:MD5 = new MD5();
+
+ var k:ByteArray = new ByteArray();
+
+ k.writeBytes(secret);
+ k.writeBytes(clientRandom);
+ k.writeBytes(serverRandom);
+
+ masterSecret = new ByteArray();
+ var pad_char:uint = 0x41;
+
+ for ( i = 0; i < 3; i++) {
+ // SHA portion
+ tempHashA.position = 0;
+
+ for ( j = 0; j < i + 1; j++) {
+ tempHashA.writeByte(pad_char);
+ }
+ pad_char++;
+
+ tempHashA.writeBytes(k);
+ shaHash = sha.hash(tempHashA);
+
+ // MD5 portion
+ tempHashB.position = 0;
+ tempHashB.writeBytes(secret);
+ tempHashB.writeBytes(shaHash);
+ mdHash = md.hash(tempHashB);
+
+ // copy into my key
+ masterSecret.writeBytes(mdHash);
+ }
+
+ // *************** END MASTER SECRET **************
+
+ // More prophylactic comments
+ // *************** START KEY BLOCK ****************
+
+ // So here, I'm setting up the keyBlock array that I will derive MACs, keys, and IVs from.
+ // Rebuild k (hash seed)
+
+ k.position = 0;
+ k.writeBytes(masterSecret);
+ k.writeBytes(serverRandom);
+ k.writeBytes(clientRandom);
+
+ keyBlock = new ByteArray();
+
+ tempHashA = new ByteArray();
+ tempHashB = new ByteArray();
+ // now for 16 iterations to get 256 bytes (16 * 16), better to have more than not enough
+ pad_char = 0x41;
+ for ( i = 0; i < 16; i++) {
+ tempHashA.position = 0;
+
+ for ( j = 0; j < i + 1; j++) {
+ tempHashA.writeByte(pad_char);
+ }
+ pad_char++;
+ tempHashA.writeBytes(k);
+ shaHash = sha.hash(tempHashA);
+
+ tempHashB.position = 0;
+ tempHashB.writeBytes(masterSecret);
+ tempHashB.writeBytes(shaHash, 0);
+ mdHash = md.hash(tempHashB);
+
+ keyBlock.writeBytes(mdHash);
+ }
+ }
+
+ public function setClientRandom(secret:ByteArray):void {
+ clientRandom = secret;
+ }
+ public function setServerRandom(secret:ByteArray):void {
+ serverRandom = secret;
+ }
+
+ public function get useRSA():Boolean {
+ return KeyExchanges.useRSA(keyExchange);
+ }
+
+ // This is the Finished message
+ // if you value your sanity, stay away...far away
+ public function computeVerifyData(side:uint, handshakeMessages:ByteArray):ByteArray {
+ // for SSL 3.0, this consists of
+ // finished = md5( masterSecret + pad2 + md5( handshake + sender + masterSecret + pad1 ) ) +
+ // sha1( masterSecret + pad2 + sha1( handshake + sender + masterSecret + pad1 ) )
+
+ // trace("Handshake messages: " + Hex.fromArray(handshakeMessages));
+ var sha:SHA1 = new SHA1();
+ var md:MD5 = new MD5();
+ var k:ByteArray = new ByteArray(); // handshake + sender + masterSecret + pad1
+ var j:ByteArray = new ByteArray(); // masterSecret + pad2 + k
+
+ var innerKey:ByteArray;
+ var outerKey:ByteArray = new ByteArray();
+
+ var hashSha:ByteArray;
+ var hashMD:ByteArray;
+
+ var sideBytes:ByteArray = new ByteArray();
+ if (side == TLSEngine.CLIENT) {
+ sideBytes.writeUnsignedInt(0x434C4E54);
+ } else {
+ sideBytes.writeUnsignedInt(0x53525652);
+ }
+
+ // Do the SHA1 part of the routine first
+ masterSecret.position = 0;
+ k.writeBytes(handshakeMessages);
+ k.writeBytes(sideBytes);
+ k.writeBytes(masterSecret);
+ k.writeBytes(pad_1, 0, 40); // limited to 40 chars for SHA1
+
+ innerKey = sha.hash(k);
+ // trace("Inner SHA Key: " + Hex.fromArray(innerKey));
+
+ j.writeBytes(masterSecret);
+ j.writeBytes(pad_2, 0, 40); // limited to 40 chars for SHA1
+ j.writeBytes(innerKey);
+
+ hashSha = sha.hash(j);
+ // trace("Outer SHA Key: " + Hex.fromArray(hashSha));
+
+ // Rebuild k for MD5
+ k = new ByteArray();
+
+ k.writeBytes(handshakeMessages);
+ k.writeBytes(sideBytes);
+ k.writeBytes(masterSecret);
+ k.writeBytes(pad_1); // Take the whole length of pad_1 & pad_2 for MD5
+
+ innerKey = md.hash(k);
+ // trace("Inner MD5 Key: " + Hex.fromArray(innerKey));
+
+ j = new ByteArray();
+ j.writeBytes(masterSecret);
+ j.writeBytes(pad_2); // see above re: 48 byte pad
+ j.writeBytes(innerKey);
+
+ hashMD = md.hash(j);
+ // trace("Outer MD5 Key: " + Hex.fromArray(hashMD));
+
+ outerKey.writeBytes(hashMD, 0, hashMD.length);
+ outerKey.writeBytes(hashSha, 0, hashSha.length);
+ var out:String = Hex.fromArray(outerKey);
+ // trace("Finished Message: " + out);
+ outerKey.position = 0;
+
+ return outerKey;
+
+ }
+
+ public function computeCertificateVerify( side:uint, handshakeMessages:ByteArray ):ByteArray {
+ // TODO: Implement this, but I don't forsee it being necessary at this point in time, since for purposes
+ // of the override, I'm only going to use TLS
+ return null;
+ }
+
+ public function getConnectionStates():Object {
+
+ if (masterSecret != null) {
+ // so now, I have to derive the actual keys from the keyblock that I generated in setPremasterSecret.
+ // for MY purposes, I need RSA-AES 128/256 + SHA
+ // so I'm gonna have keylen = 32, minlen = 32, mac_length = 20, iv_length = 16
+ // but...I can get this data from the settings returned in the constructor when this object is
+ // It strikes me that TLS does this more elegantly...
+
+ var mac_length:int = hashSize as Number;
+ var key_length:int = keySize as Number;
+ var iv_length:int = IVSize as Number;
+
+ var client_write_MAC:ByteArray = new ByteArray();
+ var server_write_MAC:ByteArray = new ByteArray();
+ var client_write_key:ByteArray = new ByteArray();
+ var server_write_key:ByteArray = new ByteArray();
+ var client_write_IV:ByteArray = new ByteArray();
+ var server_write_IV:ByteArray = new ByteArray();
+
+ // Derive the keys from the keyblock
+ // Get the MACs first
+ keyBlock.position = 0;
+ keyBlock.readBytes(client_write_MAC, 0, mac_length);
+ keyBlock.readBytes(server_write_MAC, 0, mac_length);
+
+ // keyBlock.position is now at MAC_length * 2
+ // then get the keys
+ keyBlock.readBytes(client_write_key, 0, key_length);
+ keyBlock.readBytes(server_write_key, 0, key_length);
+
+ // keyBlock.position is now at (MAC_length * 2) + (keySize * 2)
+ // and then the IVs
+ keyBlock.readBytes(client_write_IV, 0, iv_length);
+ keyBlock.readBytes(server_write_IV, 0, iv_length);
+
+ // reset this in case it's needed, for some reason or another, but I doubt it
+ keyBlock.position = 0;
+
+ var client_write:SSLConnectionState = new SSLConnectionState(
+ bulkCipher, cipherType, macAlgorithm,
+ client_write_MAC, client_write_key, client_write_IV);
+ var server_write:SSLConnectionState = new SSLConnectionState(
+ bulkCipher, cipherType, macAlgorithm,
+ server_write_MAC, server_write_key, server_write_IV);
+
+ if (entity == TLSEngine.CLIENT) {
+ return {read:server_write, write:client_write};
+ } else {
+ return {read:client_write, write:server_write};
+ }
+
+
+ } else {
+ return {read:new SSLConnectionState, write:new SSLConnectionState};
+ }
+ }
+
+ }
+} \ No newline at end of file
diff --git a/signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/TLSConfig.as b/signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/TLSConfig.as
new file mode 100644
index 0000000..2cd1d27
--- /dev/null
+++ b/signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/TLSConfig.as
@@ -0,0 +1,70 @@
+/**
+ * TLSConfig
+ *
+ * A set of configuration parameters for use by a TLSSocket or a TLSEngine.
+ * Most parameters are optional and will be set to appropriate default values for most use.
+ *
+ * Copyright (c) 2007 Henri Torgemane
+ *
+ * See LICENSE.txt for full license information.
+ */
+package com.hurlant.crypto.tls {
+ import flash.utils.ByteArray;
+ import com.hurlant.util.der.PEM;
+ import com.hurlant.crypto.rsa.RSAKey;
+ import com.hurlant.crypto.cert.X509CertificateCollection;
+ import com.hurlant.crypto.cert.MozillaRootCertificates;
+
+ public class TLSConfig {
+ public var entity:uint; // SERVER | CLIENT
+
+ public var certificate:ByteArray;
+ public var privateKey:RSAKey;
+
+ public var cipherSuites:Array;
+
+ public var compressions:Array;
+ public var ignoreCommonNameMismatch:Boolean = false;
+ public var trustAllCertificates:Boolean = false;
+ public var trustSelfSignedCertificates:Boolean = false;
+ public var promptUserForAcceptCert:Boolean = false;
+ public var CAStore:X509CertificateCollection;
+ public var localKeyStore:X509CertificateCollection;
+ public var version:uint;
+
+ public function TLSConfig( entity:uint, cipherSuites:Array = null, compressions:Array = null,
+ certificate:ByteArray = null, privateKey:RSAKey = null, CAStore:X509CertificateCollection = null, ver:uint = 0x00) {
+ this.entity = entity;
+ this.cipherSuites = cipherSuites;
+ this.compressions = compressions;
+ this.certificate = certificate;
+ this.privateKey = privateKey;
+ this.CAStore = CAStore;
+ this.version = ver;
+ // default settings.
+ if (cipherSuites==null) {
+ this.cipherSuites = CipherSuites.getDefaultSuites();
+ }
+ if (compressions==null) {
+ this.compressions = [TLSSecurityParameters.COMPRESSION_NULL];
+ }
+
+ if (CAStore==null) {
+ this.CAStore = new MozillaRootCertificates;
+ }
+
+ if (ver==0x00) {
+ // Default to TLS
+ this.version = TLSSecurityParameters.PROTOCOL_VERSION;
+ }
+ }
+
+ public function setPEMCertificate(cert:String, key:String = null):void {
+ if (key == null) {
+ key = cert; // for folks who like to concat those two in one file.
+ }
+ certificate = PEM.readCertIntoArray(cert);
+ privateKey = PEM.readRSAPrivateKey(key);
+ }
+ }
+}
diff --git a/signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/TLSConnectionState.as b/signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/TLSConnectionState.as
new file mode 100644
index 0000000..0d09a6c
--- /dev/null
+++ b/signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/TLSConnectionState.as
@@ -0,0 +1,151 @@
+/**
+ * TLSConnectionState
+ *
+ * This class encapsulates the read or write state of a TLS connection,
+ * and implementes the encrypting and hashing of packets.
+ * Copyright (c) 2007 Henri Torgemane
+ *
+ * See LICENSE.txt for full license information.
+ */
+package com.hurlant.crypto.tls {
+ import flash.utils.IDataInput;
+ import flash.utils.ByteArray;
+ import com.hurlant.crypto.hash.MD5;
+ import com.hurlant.crypto.hash.HMAC;
+ import com.hurlant.crypto.hash.IHash;
+ import com.hurlant.crypto.symmetric.ICipher;
+ import com.hurlant.crypto.symmetric.IVMode;
+ import com.hurlant.util.Hex;
+ import com.hurlant.util.ArrayUtil;
+
+ public class TLSConnectionState implements IConnectionState {
+
+
+ // compression state
+
+ // cipher state
+ private var bulkCipher:uint;
+ private var cipherType:uint;
+ private var CIPHER_key:ByteArray;
+ private var CIPHER_IV:ByteArray;
+ private var cipher:ICipher;
+ private var ivmode:IVMode;
+
+ // mac secret
+ private var macAlgorithm:uint;
+ private var MAC_write_secret:ByteArray;
+ private var hmac:HMAC;
+
+ // sequence number. uint64
+ private var seq_lo:uint;
+ private var seq_hi:uint;
+
+
+
+ public function TLSConnectionState(
+ bulkCipher:uint=0, cipherType:uint=0, macAlgorithm:uint=0,
+ mac:ByteArray=null, key:ByteArray=null, IV:ByteArray=null) {
+ this.bulkCipher = bulkCipher;
+ this.cipherType = cipherType;
+ this.macAlgorithm = macAlgorithm;
+ MAC_write_secret = mac;
+ hmac = MACs.getHMAC(macAlgorithm);
+ CIPHER_key = key;
+ CIPHER_IV = IV;
+ cipher = BulkCiphers.getCipher(bulkCipher, key, 0x0301);
+ if (cipher is IVMode) {
+ ivmode = cipher as IVMode;
+ ivmode.IV = IV;
+ }
+ }
+
+ public function decrypt(type:uint, length:uint, p:ByteArray):ByteArray {
+ // decompression is a nop.
+
+ if (cipherType == BulkCiphers.STREAM_CIPHER) {
+ if (bulkCipher == BulkCiphers.NULL) {
+ // no-op
+ } else {
+ cipher.decrypt(p);
+ }
+ } else {
+ // block cipher
+ var nextIV:ByteArray = new ByteArray;
+ nextIV.writeBytes(p, p.length-CIPHER_IV.length, CIPHER_IV.length);
+
+ cipher.decrypt(p);
+
+
+ CIPHER_IV = nextIV;
+ ivmode.IV = nextIV;
+ }
+ if (macAlgorithm!=MACs.NULL) {
+ var data:ByteArray = new ByteArray;
+ var len:uint = p.length - hmac.getHashSize();
+ data.writeUnsignedInt(seq_hi);
+ data.writeUnsignedInt(seq_lo);
+ data.writeByte(type);
+ data.writeShort(TLSSecurityParameters.PROTOCOL_VERSION);
+ data.writeShort(len);
+ if (len!=0) {
+ data.writeBytes(p, 0, len);
+ }
+ var mac:ByteArray = hmac.compute(MAC_write_secret, data);
+ // compare "mac" with the last X bytes of p.
+ var mac_received:ByteArray = new ByteArray;
+ mac_received.writeBytes(p, len, hmac.getHashSize());
+ if (ArrayUtil.equals(mac, mac_received)) {
+ // happy happy joy joy
+ } else {
+ throw new TLSError("Bad Mac Data", TLSError.bad_record_mac);
+ }
+ p.length = len;
+ p.position = 0;
+ }
+ // increment seq
+ seq_lo++;
+ if (seq_lo==0) seq_hi++;
+ return p;
+ }
+ public function encrypt(type:uint, p:ByteArray):ByteArray {
+ var mac:ByteArray = null;
+ if (macAlgorithm!=MACs.NULL) {
+ var data:ByteArray = new ByteArray;
+ data.writeUnsignedInt(seq_hi);
+ data.writeUnsignedInt(seq_lo);
+ data.writeByte(type);
+ data.writeShort(TLSSecurityParameters.PROTOCOL_VERSION);
+ data.writeShort(p.length);
+ if (p.length!=0) {
+ data.writeBytes(p, 0, p.length);
+ }
+ mac = hmac.compute(MAC_write_secret, data);
+ p.position = p.length;
+ p.writeBytes(mac);
+ }
+ p.position = 0;
+ if (cipherType == BulkCiphers.STREAM_CIPHER) {
+ // stream cipher
+ if (bulkCipher == BulkCiphers.NULL) {
+ // no-op
+ } else {
+ cipher.encrypt(p);
+ }
+ } else {
+ // block cipher
+ cipher.encrypt(p);
+ // adjust IV
+ var nextIV:ByteArray = new ByteArray;
+ nextIV.writeBytes(p, p.length-CIPHER_IV.length, CIPHER_IV.length);
+ CIPHER_IV = nextIV;
+ ivmode.IV = nextIV;
+ }
+ // increment seq
+ seq_lo++;
+ if (seq_lo==0) seq_hi++;
+ // compression is a nop.
+ return p;
+ }
+
+ }
+} \ No newline at end of file
diff --git a/signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/TLSEngine.as b/signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/TLSEngine.as
new file mode 100644
index 0000000..72f3941
--- /dev/null
+++ b/signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/TLSEngine.as
@@ -0,0 +1,895 @@
+/**
+ * TLSEngine
+ *
+ * A TLS protocol implementation.
+ * See comment below for some details.
+ * Copyright (c) 2007 Henri Torgemane
+ *
+ * Patched(heavily) by Bobby Parker (shortwave@gmail.com)
+ *
+ * See LICENSE.txt for full license information.
+ */
+package com.hurlant.crypto.tls {
+ import com.hurlant.crypto.cert.X509Certificate;
+ import com.hurlant.crypto.cert.X509CertificateCollection;
+ import com.hurlant.crypto.prng.Random;
+ import com.hurlant.util.ArrayUtil;
+ import com.hurlant.util.Hex;
+
+ import flash.events.Event;
+ import flash.events.EventDispatcher;
+ import flash.events.ProgressEvent;
+ import flash.utils.ByteArray;
+ import flash.utils.IDataInput;
+ import flash.utils.IDataOutput;
+ import flash.utils.clearTimeout;
+ import flash.utils.setTimeout;
+ import com.hurlant.crypto.prng.ARC4;
+
+
+ [Event(name="close", type="flash.events.Event")]
+ [Event(name="socketData", type="flash.events.ProgressEvent")]
+ [Event(name="ready", type="com.hurlant.crypto.tls.TLSEvent")]
+ [Event(name="data", type="com.hurlant.crypto.tls.TLSEvent")]
+
+ /**
+ * The heart of the TLS protocol.
+ * This class can work in server or client mode.
+ *
+ * This doesn't fully implement the TLS protocol.
+ *
+ * Things missing that I'd like to add:
+ * - support for client-side certificates
+ * - general code clean-up to make sure we don't have gaping securite holes
+ *
+ * Things that aren't there that I won't add:
+ * - support for "export" cypher suites (deprecated in later TLS versions)
+ * - support for "anon" cypher suites (deprecated in later TLS versions)
+ *
+ * Things that I'm unsure about adding later:
+ * - compression. Compressing encrypted streams is barely worth the CPU cycles.
+ * - diffie-hellman based key exchange mechanisms. Nifty, but would we miss it?
+ *
+ * @author henri
+ *
+ */
+ public class TLSEngine extends EventDispatcher {
+
+ public static const SERVER:uint = 0;
+ public static const CLIENT:uint = 1;
+ public var protocol_version:uint;
+
+
+
+ private static const PROTOCOL_HANDSHAKE:uint = 22;
+ private static const PROTOCOL_ALERT:uint = 21;
+ private static const PROTOCOL_CHANGE_CIPHER_SPEC:uint = 20;
+ private static const PROTOCOL_APPLICATION_DATA:uint = 23;
+
+
+ private static const STATE_NEW:uint = 0; // brand new. nothing happened yet
+ private static const STATE_NEGOTIATING:uint = 1; // we're figuring out what to use
+ private static const STATE_READY:uint = 2; // we're ready for AppData stuff to go over us.
+ private static const STATE_CLOSED:uint = 3; // we're done done.
+
+ private var _entity:uint; // SERVER | CLIENT
+ private var _config:TLSConfig;
+
+ private var _state:uint;
+
+ private var _securityParameters:ISecurityParameters;
+
+ private var _currentReadState:IConnectionState;
+ private var _currentWriteState:IConnectionState;
+ private var _pendingReadState:IConnectionState;
+ private var _pendingWriteState:IConnectionState;
+
+ private var _handshakePayloads:ByteArray;
+ private var _handshakeRecords:ByteArray; // For client-side certificate verify
+
+ private var _iStream:IDataInput;
+ private var _oStream:IDataOutput;
+
+ // temporary store for X509 certs received by this engine.
+ private var _store:X509CertificateCollection;
+ // the main certificate received from the other side.
+ private var _otherCertificate:X509Certificate;
+
+ public function get peerCertificate() : X509Certificate {
+ return _otherCertificate;
+ }
+ // If this isn't null, we expect this identity to be found in the Cert's Subject CN.
+ private var _otherIdentity:String;
+
+ // The client-side cert
+ private var _myCertficate:X509Certificate;
+ // My Identity
+ private var _myIdentity:String;
+
+ /**
+ *
+ * @param config A TLSConfig instance describing how we're supposed to work
+ * @param iStream An input stream to read TLS data from
+ * @param oStream An output stream to write TLS data to
+ * @param otherIdentity An optional identifier. If set, this will be checked against the Subject CN of the other side's certificate.
+ *
+ */
+ function TLSEngine(config:TLSConfig, iStream:IDataInput, oStream:IDataOutput, otherIdentity:String = null) {
+ _entity = config.entity;
+ _config = config;
+ _iStream = iStream;
+ _oStream = oStream;
+ _otherIdentity = otherIdentity;
+
+ _state = STATE_NEW;
+
+ // Pick the right set of callbacks
+ _entityHandshakeHandlers = _entity == CLIENT ? handshakeHandlersClient : handshakeHandlersServer;
+
+ // setting up new security parameters needs to be controlled by...something.
+ if (_config.version == SSLSecurityParameters.PROTOCOL_VERSION) {
+ _securityParameters = new SSLSecurityParameters(_entity);
+ } else {
+ _securityParameters = new TLSSecurityParameters(_entity, _config.certificate, _config.privateKey);
+ }
+ protocol_version = _config.version;
+
+ // So this...why is it here, other than to preclude a possible null pointer situation?
+ var states:Object = _securityParameters.getConnectionStates();
+
+ _currentReadState = states.read;
+ _currentWriteState = states.write;
+
+ _handshakePayloads = new ByteArray;
+
+ _store = new X509CertificateCollection;
+ }
+
+ /**
+ * This starts the TLS negotiation for a TLS Client.
+ *
+ * This is a no-op for a TLS Server.
+ *
+ */
+ public function start():void {
+ if (_entity == CLIENT) {
+ try {
+ startHandshake();
+ } catch (e:TLSError) {
+ handleTLSError(e);
+ }
+ }
+ }
+
+
+ public function dataAvailable(e:* = null):void {
+ if (_state == STATE_CLOSED) return; // ignore
+ try {
+ parseRecord(_iStream);
+ } catch (e:TLSError) {
+ handleTLSError(e);
+ }
+ }
+
+ public function close(e:TLSError = null):void {
+ if (_state == STATE_CLOSED) return; // ignore
+ // ok. send an Alert to let the peer know
+ var rec:ByteArray = new ByteArray;
+ if (e==null && _state != STATE_READY) {
+ // use canceled while handshaking. be nice about it
+ rec[0] = 1;
+ rec[1] = TLSError.user_canceled;
+ sendRecord(PROTOCOL_ALERT, rec);
+ }
+ rec[0] = 2;
+ if (e == null) {
+ rec[1] = TLSError.close_notify;
+ } else {
+ rec[1] = e.errorID;
+ trace("TLSEngine shutdown triggered by "+e);
+ }
+ sendRecord(PROTOCOL_ALERT, rec);
+
+ _state = STATE_CLOSED;
+ dispatchEvent(new Event(Event.CLOSE));
+ }
+
+ private var _packetQueue:Array = [];
+ private function parseRecord(stream:IDataInput):void {
+ var p:ByteArray;
+ while(_state!=STATE_CLOSED && stream.bytesAvailable>4) {
+
+ if (_packetQueue.length>0) {
+ var packet:Object = _packetQueue.shift();
+ p = packet.data;
+ if (stream.bytesAvailable+p.length>=packet.length) {
+ // we have a whole packet. put together.
+ stream.readBytes(p, p.length, packet.length-p.length);
+ parseOneRecord(packet.type, packet.length, p);
+ // do another loop to parse any leftover record
+ continue;
+ } else {
+ // not enough. grab the data and park it.
+ stream.readBytes(p, p.length, stream.bytesAvailable);
+ _packetQueue.push(packet);
+ continue;
+ }
+ }
+
+
+ var type:uint = stream.readByte();
+ var ver:uint = stream.readShort();
+ var length:uint = stream.readShort();
+ if (length>16384+2048) { // support compression and encryption overhead.
+ throw new TLSError("Excessive TLS Record length: "+length, TLSError.record_overflow);
+ }
+ // Can pretty much assume that if I'm here, I've got a default config, so let's use it.
+ if (ver != _securityParameters.version ) {
+ throw new TLSError("Unsupported TLS version: "+ver.toString(16), TLSError.protocol_version);
+ }
+
+ p = new ByteArray;
+ var actualLength:uint = Math.min(stream.bytesAvailable, length);
+ stream.readBytes(p, 0, actualLength);
+ if (actualLength == length) {
+ parseOneRecord(type, length, p);
+ } else {
+ _packetQueue.push({type:type, length:length, data:p});
+ }
+ }
+ }
+
+
+ // Protocol handler map, provides a mapping of protocol types to individual packet handlers
+ private var protocolHandlers:Object = { 23 : parseApplicationData, // PROTOCOL_APPLICATION_DATA
+ 22 : parseHandshake, // PROTOCOL_HANDSHAKE
+ 21 : parseAlert, // PROTOCOL_ALERT
+ 20 : parseChangeCipherSpec }; // PROTOCOL_CHANGE_CIPHER_SPEC
+
+ /**
+ * Modified to support the notion of a handler map(see above ), since it makes for better clarity (IMHO of course).
+ */
+ private function parseOneRecord(type:uint, length:uint, p:ByteArray):void {
+ p = _currentReadState.decrypt(type, length, p);
+ if (p.length>16384) {
+ throw new TLSError("Excessive Decrypted TLS Record length: "+p.length, TLSError.record_overflow);
+ }
+ if (protocolHandlers.hasOwnProperty( type )) {
+ while( p != null)
+ p = protocolHandlers[ type ]( p );
+ } else {
+ throw new TLSError("Unsupported TLS Record Content Type: "+type.toString( 16 ), TLSError.unexpected_message);
+ }
+ }
+
+ ///////// handshake handling
+ // session identifier
+ // peer certificate
+ // compression method
+ // cipher spec
+ // master secret
+ // is resumable
+ private static const HANDSHAKE_HELLO_REQUEST:uint = 0;
+ private static const HANDSHAKE_CLIENT_HELLO:uint = 1;
+ private static const HANDSHAKE_SERVER_HELLO:uint = 2;
+ private static const HANDSHAKE_CERTIFICATE:uint = 11;
+ private static const HANDSHAKE_SERVER_KEY_EXCHANGE:uint = 12;
+ private static const HANDSHAKE_CERTIFICATE_REQUEST:uint = 13;
+ private static const HANDSHAKE_HELLO_DONE:uint = 14;
+ private static const HANDSHAKE_CERTIFICATE_VERIFY:uint = 15;
+ private static const HANDSHAKE_CLIENT_KEY_EXCHANGE:uint = 16;
+ private static const HANDSHAKE_FINISHED:uint = 20;
+
+ // Server handshake handler map
+ private var handshakeHandlersServer:Object = { 0 : notifyStateError, // HANDSHAKE_HELLO_REQUEST
+ 1 : parseHandshakeClientHello, // HANDSHAKE_CLIENT_HELLO
+ 2 : notifyStateError, // HANDSHAKE_SERVER_HELLO
+ 11 : loadCertificates, // HANDSHAKE_CERTIFICATE
+ 12 : notifyStateError, // HANDSHAKE_SERVER_KEY_EXCHANGE
+ 13 : notifyStateError, // HANDSHAKE_CERTIFICATE_REQUEST
+ 14 : notifyStateError, // HANDSHAKE_HELLO_DONE
+ 15 : notifyStateError, // HANDSHAKE_CERTIFICATE_VERIFY
+ 16 : parseHandshakeClientKeyExchange, // HANDSHAKE_CLIENT_KEY_EXCHANGE
+ 20 : verifyHandshake // HANDSHAKE_FINISHED
+ };
+
+ // Client handshake handler map
+ private var handshakeHandlersClient:Object = { 0 : parseHandshakeHello, // HANDSHAKE_HELLO_REQUEST
+ 1 : notifyStateError, // HANDSHAKE_CLIENT_HELLO
+ 2 : parseHandshakeServerHello, // HANDSHAKE_SERVER_HELLO
+ 11 : loadCertificates, // HANDSHAKE_CERTIFICATE
+ 12 : parseServerKeyExchange, // HANDSHAKE_SERVER_KEY_EXCHANGE
+ 13 : setStateRespondWithCertificate, // HANDSHAKE_CERTIFICATE
+ 14 : sendClientAck, // HANDSHAKE_HELLO_DONE
+ 15 : notifyStateError, // HANDSHAKE_CERTIFICATE_VERIFY
+ 16 : notifyStateError, // HANDSHAKE_CLIENT_KEY_EXCHANGE
+ 20 : verifyHandshake // HANDSHAKE_FINISHED
+ };
+ private var _entityHandshakeHandlers:Object;
+ private var _handshakeCanContinue:Boolean = true; // For handling cases where I might need to pause processing during a handshake (cert issues, etc.).
+ private var _handshakeQueue:Array = [];
+ /**
+ * The handshake is always started by the client.
+ */
+ private function startHandshake():void {
+ _state = STATE_NEGOTIATING;
+ // reset some other handshake state. XXX
+ sendClientHello();
+ }
+
+ /**
+ * Handle the incoming handshake packet.
+ *
+ */
+ private function parseHandshake(p:ByteArray):ByteArray {
+
+ if (p.length<4) {
+ trace("Handshake packet is way too short. bailing.");
+ return null;
+ }
+
+ p.position = 0;
+
+ var rec:ByteArray = p;
+ var type:uint = rec.readUnsignedByte();
+ var tmp:uint = rec.readUnsignedByte();
+ var length:uint = (tmp<<16) | rec.readUnsignedShort();
+ if (length+4>p.length) {
+ // partial read.
+ trace("Handshake packet is incomplete. bailing.");
+ return null;
+ }
+
+ // we need to copy the record, to have a valid FINISHED exchange.
+ if (type!=HANDSHAKE_FINISHED) {
+ _handshakePayloads.writeBytes(p, 0, length+4);
+ }
+
+ // Surf the handler map and find the right handler for this handshake packet type.
+ // I modified the individual handlers so they encapsulate all possible knowledge
+ // about the incoming packet type, so no previous handling or massaging of the data
+ // is required, as was the case using the switch statement. BP
+ if (_entityHandshakeHandlers.hasOwnProperty( type )) {
+ if (_entityHandshakeHandlers[ type ] is Function)
+ _entityHandshakeHandlers[ type ]( rec );
+ } else {
+ throw new TLSError( "Unimplemented or unknown handshake type!", TLSError.internal_error );
+ }
+
+ // Get set up for the next packet.
+ if (length+4<p.length) {
+ var n:ByteArray = new ByteArray;
+ n.writeBytes(p,length+4, p.length-(length+4));
+ return n;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Throw an error when the detected handshake state isn't a valid state for the given entity type (client vs. server, etc. ).
+ * This really should abort the handshake, since there's no case in which a server should EVER be confused about the type of entity it is. BP
+ */
+ private function notifyStateError( rec:ByteArray ) : void {
+ throw new TLSError( "Invalid handshake state for a TLS Entity type of " + _entity, TLSError.internal_error );
+ }
+
+ /**
+ * two unimplemented functions
+ */
+ private function parseClientKeyExchange( rec:ByteArray ) : void {
+ throw new TLSError( "ClientKeyExchange is currently unimplemented!", TLSError.internal_error );
+ }
+
+ private function parseServerKeyExchange( rec:ByteArray ) : void {
+ throw new TLSError( "ServerKeyExchange is currently unimplemented!", TLSError.internal_error );
+ }
+
+ /**
+ * Test the server's Finished message for validity against the data we know about. Only slightly rewritten. BP
+ */
+ private function verifyHandshake( rec:ByteArray):void {
+ // Get the Finished message
+ var verifyData:ByteArray = new ByteArray;
+ // This, in the vain hope that noboby is using SSL 2 anymore
+ if (_securityParameters.version == SSLSecurityParameters.PROTOCOL_VERSION) {
+ rec.readBytes(verifyData, 0, 36); // length should be (in fact, better be) 16 + 20 (md5-size + sha1-size)
+ } else { // presuming TLS
+ rec.readBytes(verifyData, 0, 12);
+ }
+
+ var data:ByteArray = _securityParameters.computeVerifyData(1-_entity, _handshakePayloads);
+
+ if (ArrayUtil.equals(verifyData, data)) {
+ _state = STATE_READY;
+ dispatchEvent(new TLSEvent(TLSEvent.READY));
+ } else {
+ throw new TLSError("Invalid Finished mac.", TLSError.bad_record_mac);
+ }
+ }
+
+ // enforceClient/enforceServer removed in favor of state-driven function maps
+
+ /**
+ * Handle a HANDSHAKE_HELLO
+ */
+ private function parseHandshakeHello( rec:ByteArray ) : void {
+ if (_state != STATE_READY) {
+ trace("Received an HELLO_REQUEST before being in state READY. ignoring.");
+ return;
+ }
+ _handshakePayloads = new ByteArray;
+ startHandshake();
+ }
+
+ /**
+ * Handle a HANDSHAKE_CLIENT_KEY_EXCHANGE
+ */
+ private function parseHandshakeClientKeyExchange(rec:ByteArray):void {
+ if (_securityParameters.useRSA) {
+ // skip 2 bytes for length.
+ var len:uint = rec.readShort();
+ var cipher:ByteArray = new ByteArray;
+ rec.readBytes(cipher, 0, len);
+ var preMasterSecret:ByteArray = new ByteArray;
+ _config.privateKey.decrypt(cipher, preMasterSecret, len);
+ _securityParameters.setPreMasterSecret(preMasterSecret);
+
+ // now is a good time to get our pending states
+ var o:Object = _securityParameters.getConnectionStates();
+ _pendingReadState = o.read;
+ _pendingWriteState = o.write;
+
+ } else {
+ throw new TLSError("parseHandshakeClientKeyExchange not implemented for DH modes.", TLSError.internal_error);
+ }
+
+ }
+
+ /**
+ * Handle HANDSHAKE_SERVER_HELLO - client-side
+ */
+ private function parseHandshakeServerHello( rec:IDataInput ) : void {
+
+ var ver:uint = rec.readShort();
+ if (ver != _securityParameters.version) {
+ throw new TLSError("Unsupported TLS version: "+ver.toString(16), TLSError.protocol_version);
+ }
+ var random:ByteArray = new ByteArray;
+ rec.readBytes(random, 0, 32);
+ var session_length:uint = rec.readByte();
+ var session:ByteArray = new ByteArray;
+ if (session_length > 0) {
+ // some implementations don't assign a session ID
+ rec.readBytes(session, 0, session_length);
+ }
+
+ _securityParameters.setCipher(rec.readShort());
+ _securityParameters.setCompression(rec.readByte());
+ _securityParameters.setServerRandom(random);
+ }
+
+ /**
+ * Handle HANDSHAKE_CLIENT_HELLO - server side
+ */
+ private function parseHandshakeClientHello( rec:IDataInput ) : void {
+ var ret:Object;
+ var ver:uint = rec.readShort();
+ if (ver != _securityParameters.version) {
+ throw new TLSError("Unsupported TLS version: "+ver.toString(16), TLSError.protocol_version);
+ }
+
+ var random:ByteArray = new ByteArray;
+ rec.readBytes(random, 0, 32);
+ var session_length:uint = rec.readByte();
+ var session:ByteArray = new ByteArray;
+ if (session_length > 0) {
+ // some implementations don't assign a session ID
+ rec.readBytes(session, 0, session_length);
+ }
+ var suites:Array = [];
+
+ var suites_length:uint = rec.readShort();
+ for (var i:uint=0;i<suites_length/2;i++) {
+ suites.push(rec.readShort());
+ }
+
+ var compressions:Array = [];
+
+ var comp_length:uint = rec.readByte();
+ for (i=0;i<comp_length;i++) {
+ compressions.push(rec.readByte());
+ }
+
+ ret = {random:random, session:session, suites:suites, compressions:compressions};
+
+ var sofar:uint = 2+32+1+session_length+2+suites_length+1+comp_length;
+ var extensions:Array = [];
+ if (sofar<length) {
+ // we have extensions. great.
+ var ext_total_length:uint = rec.readShort();
+ while (ext_total_length>0) {
+ var ext_type:uint = rec.readShort();
+ var ext_length:uint = rec.readShort();
+ var ext_data:ByteArray = new ByteArray;
+ rec.readBytes(ext_data, 0, ext_length);
+ ext_total_length -= 4+ext_length;
+ extensions.push({type:ext_type, length:ext_length, data:ext_data});
+ }
+ }
+ ret.ext = extensions;
+
+ sendServerHello(ret);
+ sendCertificate();
+ // TODO: Modify to handle case of requesting a certificate from the client, for "client authentication",
+ // and testing purposes, will probably never actually need it.
+ sendServerHelloDone();
+ }
+
+ private function sendClientHello():void {
+ var rec:ByteArray = new ByteArray;
+ // version - modified to support version attribute from ISecurityParameters
+ rec.writeShort(_securityParameters.version);
+ // random
+ var prng:Random = new Random;
+ var clientRandom:ByteArray = new ByteArray;
+ prng.nextBytes(clientRandom, 32);
+ _securityParameters.setClientRandom(clientRandom);
+ rec.writeBytes(clientRandom,0,32);
+ // session
+ rec.writeByte(32);
+ prng.nextBytes(rec, 32);
+ // Cipher suites
+ var cs:Array = _config.cipherSuites;
+ rec.writeShort(2* cs.length);
+ for (var i:int=0;i<cs.length;i++) {
+ rec.writeShort(cs[i]);
+ }
+ // Compression
+ cs = _config.compressions;
+ rec.writeByte(cs.length);
+ for (i=0;i<cs.length;i++) {
+ rec.writeByte(cs[i]);
+ }
+ // no extensions, yet.
+ rec.position = 0;
+ sendHandshake(HANDSHAKE_CLIENT_HELLO, rec.length, rec);
+ }
+
+ private function findMatch(a1:Array, a2:Array):int {
+ for (var i:int=0;i<a1.length;i++) {
+ var e:uint = a1[i];
+ if (a2.indexOf(e)>-1) {
+ return e;
+ }
+ }
+ return -1;
+ }
+
+ private function sendServerHello(v:Object):void {
+ var cipher:int = findMatch(_config.cipherSuites, v.suites);
+ if (cipher == -1) {
+ throw new TLSError("No compatible cipher found.", TLSError.handshake_failure);
+ }
+ _securityParameters.setCipher(cipher);
+
+ var comp:int = findMatch(_config.compressions, v.compressions);
+ if (comp == 01) {
+ throw new TLSError("No compatible compression method found.", TLSError.handshake_failure);
+ }
+ _securityParameters.setCompression(comp);
+ _securityParameters.setClientRandom(v.random);
+
+
+ var rec:ByteArray = new ByteArray;
+ rec.writeShort(_securityParameters.version);
+ var prng:Random = new Random;
+ var serverRandom:ByteArray = new ByteArray;
+ prng.nextBytes(serverRandom, 32);
+ _securityParameters.setServerRandom(serverRandom);
+ rec.writeBytes(serverRandom,0,32);
+ // session
+ rec.writeByte(32);
+ prng.nextBytes(rec, 32);
+ // Cipher suite
+ rec.writeShort(v.suites[0]);
+ // Compression
+ rec.writeByte(v.compressions[0]);
+ rec.position = 0;
+ sendHandshake(HANDSHAKE_SERVER_HELLO, rec.length, rec);
+ }
+
+ private var sendClientCert:Boolean = false;
+ private function setStateRespondWithCertificate( r:ByteArray = null) : void {
+ sendClientCert = true;
+ }
+
+ private function sendCertificate( r:ByteArray = null ):void {
+ var cert:ByteArray = _config.certificate;
+ var len:uint;
+ var len2:uint;
+ var rec:ByteArray = new ByteArray;
+ // Look for a certficate chain, if we have one, send it, if we don't, send an empty record.
+ if (cert != null) {
+ len = cert.length;
+ len2 = cert.length + 3;
+ rec.writeByte(len2>>16);
+ rec.writeShort(len2&65535);
+ rec.writeByte(len>>16);
+ rec.writeShort(len&65535);
+ rec.writeBytes(cert);
+ } else {
+ rec.writeShort( 0 );
+ rec.writeByte( 0 );
+ }
+ rec.position = 0;
+ sendHandshake(HANDSHAKE_CERTIFICATE, rec.length, rec);
+ }
+
+ private function sendCertificateVerify():void {
+ var rec:ByteArray = new ByteArray();
+ // Encrypt the handshake payloads here
+ var data:ByteArray = _securityParameters.computeCertificateVerify(_entity, _handshakePayloads);
+ data.position=0;
+ sendHandshake(HANDSHAKE_CERTIFICATE_VERIFY, data.length, data);
+ }
+
+ private function sendServerHelloDone():void {
+ var rec:ByteArray = new ByteArray;
+ sendHandshake(HANDSHAKE_HELLO_DONE, rec.length, rec);
+ }
+
+ private function sendClientKeyExchange():void {
+ if (_securityParameters.useRSA) {
+ var p:ByteArray = new ByteArray;
+ p.writeShort(_securityParameters.version);
+ var prng:Random = new Random;
+ prng.nextBytes(p, 46);
+ p.position = 0;
+
+ var preMasterSecret:ByteArray = new ByteArray;
+ preMasterSecret.writeBytes(p, 0, p.length);
+ preMasterSecret.position = 0;
+ _securityParameters.setPreMasterSecret(preMasterSecret);
+
+ var enc_key:ByteArray = new ByteArray;
+ _otherCertificate.getPublicKey().encrypt(preMasterSecret, enc_key, preMasterSecret.length);
+
+ enc_key.position = 0;
+ var rec:ByteArray = new ByteArray;
+
+ // TLS requires the size of the premaster key be sent BUT
+ // SSL 3.0 does not
+ if (_securityParameters.version > 0x0300) {
+ rec.writeShort(enc_key.length);
+ }
+ rec.writeBytes(enc_key, 0, enc_key.length);
+
+ rec.position=0;
+
+ sendHandshake(HANDSHAKE_CLIENT_KEY_EXCHANGE, rec.length, rec);
+
+ // now is a good time to get our pending states
+ var o:Object = _securityParameters.getConnectionStates();
+ _pendingReadState = o.read;
+ _pendingWriteState = o.write;
+
+ } else {
+ throw new TLSError("Non-RSA Client Key Exchange not implemented.", TLSError.internal_error);
+ }
+ }
+ private function sendFinished():void {
+ var data:ByteArray = _securityParameters.computeVerifyData(_entity, _handshakePayloads);
+ data.position=0;
+ sendHandshake(HANDSHAKE_FINISHED, data.length, data);
+ }
+
+ private function sendHandshake(type:uint, len:uint, payload:IDataInput):void {
+ var rec:ByteArray = new ByteArray;
+ rec.writeByte(type);
+ rec.writeByte(0);
+ rec.writeShort(len);
+ payload.readBytes(rec, rec.position, len);
+ _handshakePayloads.writeBytes(rec, 0, rec.length);
+ sendRecord(PROTOCOL_HANDSHAKE, rec);
+ }
+
+ private function sendChangeCipherSpec():void {
+ var rec:ByteArray = new ByteArray;
+ rec[0] = 1;
+ sendRecord(PROTOCOL_CHANGE_CIPHER_SPEC, rec);
+
+ // right after, switch the cipher for writing.
+ _currentWriteState = _pendingWriteState;
+ _pendingWriteState = null;
+ }
+
+ public function sendApplicationData(data:ByteArray, offset:uint=0, length:uint=0):void {
+ var rec:ByteArray = new ByteArray;
+ var len:uint = length;
+ // BIG FAT WARNING: Patch from Arlen Cuss ALA As3crypto group on Google code.
+ // This addresses data overflow issues when the packet size hits the max length boundary.
+ if (len == 0) len = data.length;
+ while (len>16384) {
+ rec.position = 0;
+ rec.writeBytes(data, offset, 16384);
+ rec.position = 0;
+ sendRecord(PROTOCOL_APPLICATION_DATA, rec);
+ offset += 16384;
+ len -= 16384;
+ }
+ rec.position = 0;
+ rec.writeBytes(data, offset, len);
+ // trace("Data I'm sending..." + Hex.fromArray( data ));
+ rec.position = 0;
+ sendRecord(PROTOCOL_APPLICATION_DATA, rec);
+ }
+ private function sendRecord(type:uint, payload:ByteArray):void {
+ // encrypt
+ payload = _currentWriteState.encrypt(type, payload);
+
+ _oStream.writeByte(type);
+ _oStream.writeShort(_securityParameters.version);
+ _oStream.writeShort(payload.length);
+ _oStream.writeBytes(payload, 0, payload.length);
+
+ scheduleWrite();
+ }
+
+ private var _writeScheduler:uint;
+ private function scheduleWrite():void {
+ if (_writeScheduler!=0) return;
+ _writeScheduler = setTimeout(commitWrite, 0);
+ }
+ private function commitWrite():void {
+ clearTimeout(_writeScheduler);
+ _writeScheduler = 0;
+ if (_state != STATE_CLOSED) {
+ dispatchEvent(new ProgressEvent(ProgressEvent.SOCKET_DATA));
+ }
+ }
+
+ private function sendClientAck( rec:ByteArray ):void {
+ if ( _handshakeCanContinue ) {
+ // If I have a pending cert request, send it
+ if (sendClientCert)
+ sendCertificate();
+ // send a client key exchange
+ sendClientKeyExchange();
+ // Send the certificate verify, if we have one
+ if (_config.certificate != null)
+ sendCertificateVerify();
+ // send a change cipher spec
+ sendChangeCipherSpec();
+ // send a finished
+ sendFinished();
+ }
+ }
+
+ /**
+ * Vaguely gross function that parses a RSA key out of a certificate.
+ *
+ * As long as that certificate looks just the way we expect it to.
+ *
+ */
+ private function loadCertificates( rec:ByteArray ):void {
+ var tmp:uint = rec.readByte();
+ var certs_len:uint = (tmp<<16) | rec.readShort();
+ var certs:Array = [];
+
+ while (certs_len>0) {
+ tmp = rec.readByte();
+ var cert_len:uint = (tmp<<16) | rec.readShort();
+ var cert:ByteArray = new ByteArray;
+ rec.readBytes(cert, 0, cert_len);
+ certs.push(cert);
+ certs_len -= 3 + cert_len;
+ }
+
+ var firstCert:X509Certificate = null;
+ for (var i:int=0;i<certs.length;i++) {
+ var x509:X509Certificate = new X509Certificate(certs[i]);
+ _store.addCertificate(x509);
+ if (firstCert==null) {
+ firstCert = x509;
+ }
+ }
+
+
+ // Test first for trust override parameters
+ // This nice trust override stuff comes from Joey Parrish via As3crypto forums
+ var certTrusted:Boolean;
+ if (_config.trustAllCertificates) {
+ certTrusted = true; // Blatantly trust everything
+ } else if (_config.trustSelfSignedCertificates ) {
+ // Self-signed certs
+ certTrusted = firstCert.isSelfSigned(new Date);
+ } else {
+ // Certs with a signer in the CA store - realistically, I should setup an event chain to handle this
+ certTrusted = firstCert.isSigned(_store, _config.CAStore );
+ }
+
+ // Good so far
+ if (certTrusted) {
+ // ok, that's encouraging. now for the hostname match.
+ if (_otherIdentity==null || _config.ignoreCommonNameMismatch ) {
+ // we don't care who we're talking with. groovy.
+ _otherCertificate = firstCert;
+ } else {
+ // use regex to handle wildcard certs
+ var commonName:String = firstCert.getCommonName();
+ // replace all regex special characters with escaped version, except for asterisk
+ // replace the asterisk with a regex sequence to match one or more non-dot characters
+ var commonNameRegex:RegExp = new RegExp( commonName.replace(/[\^\\\-$.[\]|()?+{}]/g, "\\$&").replace(/\*/g, "[^.]+"), "gi");
+ if (commonNameRegex.exec(_otherIdentity)) {
+ _otherCertificate = firstCert;
+ } else {
+ if (_config.promptUserForAcceptCert ) {
+ _handshakeCanContinue = false;
+ dispatchEvent( new TLSEvent( TLSEvent.PROMPT_ACCEPT_CERT ));
+ } else {
+ throw new TLSError("Invalid common name: "+firstCert.getCommonName()+", expected "+_otherIdentity, TLSError.bad_certificate);
+ }
+ }
+ }
+
+ } else {
+ // Let's ask the user if we can accept this cert. I'm not certain of the behaviour in case of timeouts,
+ // so I probably need to handle the case by killing and restarting the connection rather than continuing if it becomes
+ // an issue. We shall see. BP
+ if (_config.promptUserForAcceptCert) {
+ _handshakeCanContinue = false;
+ dispatchEvent( new TLSEvent( TLSEvent.PROMPT_ACCEPT_CERT ));
+ } else {
+ // Cannot continue, die.
+ throw new TLSError("Cannot verify certificate", TLSError.bad_certificate);
+ }
+ }
+ }
+
+ // Accept the peer cert, and keep going
+ public function acceptPeerCertificate() : void {
+ _handshakeCanContinue = true;
+ sendClientAck( null );
+ }
+
+ // Step off biotch! No trust for you!
+ public function rejectPeerCertificate() : void {
+ throw new TLSError("Peer certificate not accepted!", TLSError.bad_certificate);
+ }
+
+
+ private function parseAlert(p:ByteArray):void {
+ //throw new Error("Alert not implemented.");
+ // 7.2
+ trace("GOT ALERT! type="+p[1]);
+ close();
+ }
+ private function parseChangeCipherSpec(p:ByteArray):void {
+ p.readUnsignedByte();
+ if (_pendingReadState==null) {
+ throw new TLSError("Not ready to Change Cipher Spec, damnit.", TLSError.unexpected_message);
+ }
+ _currentReadState = _pendingReadState;
+ _pendingReadState = null;
+ // 7.1
+ }
+ private function parseApplicationData(p:ByteArray):void {
+ if (_state != STATE_READY) {
+ throw new TLSError("Too soon for data!", TLSError.unexpected_message);
+ return;
+ }
+ dispatchEvent(new TLSEvent(TLSEvent.DATA, p));
+ }
+
+ private function handleTLSError(e:TLSError):void {
+ // basic rules to keep things simple:
+ // - Make a good faith attempt at notifying peers
+ // - TLSErrors are always fatal.
+ // BP: Meh...not always. Common Name mismatches appear to be common on servers. Instead of closing, let's pause, and ask for confirmation
+ // before we tear the connection down.
+
+ close(e);
+ }
+ }
+}
diff --git a/signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/TLSError.as b/signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/TLSError.as
new file mode 100644
index 0000000..16fac6d
--- /dev/null
+++ b/signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/TLSError.as
@@ -0,0 +1,39 @@
+/**
+ * TLSError
+ *
+ * A error that can be thrown when something wrong happens in the TLS protocol.
+ * This is handled in TLSEngine by generating a TLS ALERT as appropriate.
+ * Copyright (c) 2007 Henri Torgemane
+ *
+ * See LICENSE.txt for full license information.
+ */
+package com.hurlant.crypto.tls {
+ public class TLSError extends Error {
+ public static const close_notify:uint = 0;
+ public static const unexpected_message:uint = 10;
+ public static const bad_record_mac:uint = 20;
+ public static const decryption_failed:uint = 21;
+ public static const record_overflow:uint = 22;
+ public static const decompression_failure:uint = 30;
+ public static const handshake_failure:uint = 40;
+ public static const bad_certificate:uint = 42;
+ public static const unsupported_certificate:uint = 43;
+ public static const certificate_revoked:uint = 44;
+ public static const certificate_expired:uint = 45;
+ public static const certificate_unknown:uint = 46;
+ public static const illegal_parameter:uint = 47;
+ public static const unknown_ca:uint = 48;
+ public static const access_denied:uint = 49;
+ public static const decode_error:uint = 50;
+ public static const decrypt_error:uint = 51;
+ public static const protocol_version:uint = 70;
+ public static const insufficient_security:uint = 71;
+ public static const internal_error:uint = 80;
+ public static const user_canceled:uint = 90;
+ public static const no_renegotiation:uint = 100;
+
+ public function TLSError(message:String, id:int) {
+ super(message,id);
+ }
+ }
+} \ No newline at end of file
diff --git a/signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/TLSEvent.as b/signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/TLSEvent.as
new file mode 100644
index 0000000..d988d1e
--- /dev/null
+++ b/signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/TLSEvent.as
@@ -0,0 +1,27 @@
+/**
+ * TLSEvent
+ *
+ * This is used by TLSEngine to let the application layer know
+ * when we're ready for sending, or have received application data
+ * Copyright (c) 2007 Henri Torgemane
+ *
+ * See LICENSE.txt for full license information.
+ */
+package com.hurlant.crypto.tls {
+ import flash.events.Event;
+ import flash.utils.ByteArray;
+
+ public class TLSEvent extends Event {
+
+ static public const DATA:String = "data";
+ static public const READY:String = "ready";
+ static public const PROMPT_ACCEPT_CERT:String = "promptAcceptCert";
+
+ public var data:ByteArray;
+
+ public function TLSEvent(type:String, data:ByteArray = null) {
+ this.data = data;
+ super(type, false, false);
+ }
+ }
+} \ No newline at end of file
diff --git a/signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/TLSSecurityParameters.as b/signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/TLSSecurityParameters.as
new file mode 100644
index 0000000..2637811
--- /dev/null
+++ b/signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/TLSSecurityParameters.as
@@ -0,0 +1,197 @@
+/**
+ * TLSSecurityParameters
+ *
+ * This class encapsulates all the security parameters that get negotiated
+ * during the TLS handshake. It also holds all the key derivation methods.
+ * Copyright (c) 2007 Henri Torgemane
+ *
+ * Patched by Bobby Parker (sh0rtwave@gmail.com)
+ *
+ * See LICENSE.txt for full license information.
+ */
+package com.hurlant.crypto.tls {
+ import com.hurlant.crypto.hash.MD5;
+ import com.hurlant.crypto.hash.SHA1;
+ import com.hurlant.crypto.prng.TLSPRF;
+ import com.hurlant.util.Hex;
+
+ import flash.utils.ByteArray;
+ import com.hurlant.crypto.rsa.RSAKey;
+
+ public class TLSSecurityParameters implements ISecurityParameters {
+
+ // COMPRESSION
+ public static const COMPRESSION_NULL:uint = 0;
+
+ // This is probably not smart. Revise this to use all settings from TLSConfig, since this shouldn't really know about
+ // user settings, those are best handled from the engine at a session level.
+ public static var IGNORE_CN_MISMATCH:Boolean = true;
+ public static var ENABLE_USER_CLIENT_CERTIFICATE:Boolean = false;
+ public static var USER_CERTIFICATE:String;
+
+
+ private var cert:ByteArray; // Local Cert
+ private var key:RSAKey; // local key
+ private var entity:uint; // SERVER | CLIENT
+ private var bulkCipher:uint; // BULK_CIPHER_*
+ private var cipherType:uint; // STREAM_CIPHER | BLOCK_CIPHER
+ private var keySize:uint;
+ private var keyMaterialLength:uint;
+ private var IVSize:uint;
+ private var macAlgorithm:uint; // MAC_*
+ private var hashSize:uint;
+ private var compression:uint; // COMPRESSION_NULL
+ private var masterSecret:ByteArray; // 48 bytes
+ private var clientRandom:ByteArray; // 32 bytes
+ private var serverRandom:ByteArray; // 32 bytes
+ private var ignoreCNMismatch:Boolean = true;
+ private var trustAllCerts:Boolean = false;
+ private var trustSelfSigned:Boolean = false;
+ public static const PROTOCOL_VERSION:uint = 0x0301;
+ private var tlsDebug:Boolean = false;
+
+
+ // not strictly speaking part of this, but yeah.
+ public var keyExchange:uint;
+ public function TLSSecurityParameters(entity:uint, localCert:ByteArray = null, localKey:RSAKey = null) {
+ this.entity = entity;
+ reset();
+ key = localKey;
+ cert = localCert;
+ }
+
+ public function get version() : uint {
+ return PROTOCOL_VERSION;
+ }
+
+ public function reset():void {
+ bulkCipher = BulkCiphers.NULL;
+ cipherType = BulkCiphers.BLOCK_CIPHER;
+ macAlgorithm = MACs.NULL;
+ compression = COMPRESSION_NULL;
+ masterSecret = null;
+ }
+
+ public function getBulkCipher():uint {
+ return bulkCipher;
+ }
+ public function getCipherType():uint {
+ return cipherType;
+ }
+ public function getMacAlgorithm():uint {
+ return macAlgorithm;
+ }
+
+ public function setCipher(cipher:uint):void {
+ bulkCipher = CipherSuites.getBulkCipher(cipher);
+ cipherType = BulkCiphers.getType(bulkCipher);
+ keySize = BulkCiphers.getExpandedKeyBytes(bulkCipher); // 8
+ keyMaterialLength = BulkCiphers.getKeyBytes(bulkCipher); // 5
+ IVSize = BulkCiphers.getIVSize(bulkCipher);
+
+ keyExchange = CipherSuites.getKeyExchange(cipher);
+
+ macAlgorithm = CipherSuites.getMac(cipher);
+ hashSize = MACs.getHashSize(macAlgorithm);
+ }
+ public function setCompression(algo:uint):void {
+ compression = algo;
+ }
+ public function setPreMasterSecret(secret:ByteArray):void {
+ // compute master_secret
+ var seed:ByteArray = new ByteArray;
+ seed.writeBytes(clientRandom, 0, clientRandom.length);
+ seed.writeBytes(serverRandom, 0, serverRandom.length);
+ var prf:TLSPRF = new TLSPRF(secret, "master secret", seed);
+ masterSecret = new ByteArray;
+ prf.nextBytes(masterSecret, 48);
+ if (tlsDebug)
+ trace("Master Secret: " + Hex.fromArray( masterSecret, true ));
+ }
+ public function setClientRandom(secret:ByteArray):void {
+ clientRandom = secret;
+ }
+ public function setServerRandom(secret:ByteArray):void {
+ serverRandom = secret;
+ }
+
+ public function get useRSA():Boolean {
+ return KeyExchanges.useRSA(keyExchange);
+ }
+
+ public function computeVerifyData(side:uint, handshakeMessages:ByteArray):ByteArray {
+ var seed:ByteArray = new ByteArray;
+ var md5:MD5 = new MD5;
+ if (tlsDebug)
+ trace("Handshake value: " + Hex.fromArray(handshakeMessages, true ));
+ seed.writeBytes(md5.hash(handshakeMessages),0,md5.getHashSize());
+ var sha:SHA1 = new SHA1;
+ seed.writeBytes(sha.hash(handshakeMessages),0,sha.getHashSize());
+ if (tlsDebug)
+ trace("Seed in: " + Hex.fromArray(seed, true ));
+ var prf:TLSPRF = new TLSPRF(masterSecret, (side==TLSEngine.CLIENT) ? "client finished" : "server finished", seed);
+ var out:ByteArray = new ByteArray;
+ prf.nextBytes(out, 12);
+ if (tlsDebug)
+ trace("Finished out: " + Hex.fromArray(out, true ));
+ out.position = 0;
+ return out;
+ }
+
+ // client side certficate check - This is probably incorrect somehow
+ public function computeCertificateVerify( side:uint, handshakeMessages:ByteArray ):ByteArray {
+ var seed:ByteArray = new ByteArray;
+ var md5:MD5 = new MD5;
+ seed.writeBytes(md5.hash(handshakeMessages),0,md5.getHashSize());
+ var sha:SHA1 = new SHA1;
+ seed.writeBytes(sha.hash(handshakeMessages),0,sha.getHashSize());
+
+ // Now that I have my hashes of existing handshake messages (which I'm not sure about the length of yet) then
+ // Sign that with my private key
+ seed.position = 0;
+ var out:ByteArray = new ByteArray();
+ key.sign( seed, out, seed.bytesAvailable);
+ out.position = 0;
+ return out;
+ }
+
+ public function getConnectionStates():Object {
+ if (masterSecret != null) {
+ var seed:ByteArray = new ByteArray;
+ seed.writeBytes(serverRandom, 0, serverRandom.length);
+ seed.writeBytes(clientRandom, 0, clientRandom.length);
+ var prf:TLSPRF = new TLSPRF(masterSecret, "key expansion", seed);
+
+ var client_write_MAC:ByteArray = new ByteArray;
+ prf.nextBytes(client_write_MAC, hashSize);
+ var server_write_MAC:ByteArray = new ByteArray;
+ prf.nextBytes(server_write_MAC, hashSize);
+ var client_write_key:ByteArray = new ByteArray;
+ prf.nextBytes(client_write_key, keyMaterialLength);
+ var server_write_key:ByteArray = new ByteArray;
+ prf.nextBytes(server_write_key, keyMaterialLength);
+ var client_write_IV:ByteArray = new ByteArray;
+ prf.nextBytes(client_write_IV, IVSize);
+ var server_write_IV:ByteArray = new ByteArray;
+ prf.nextBytes(server_write_IV, IVSize);
+
+ var client_write:TLSConnectionState = new TLSConnectionState(
+ bulkCipher, cipherType, macAlgorithm,
+ client_write_MAC, client_write_key, client_write_IV);
+ var server_write:TLSConnectionState = new TLSConnectionState(
+ bulkCipher, cipherType, macAlgorithm,
+ server_write_MAC, server_write_key, server_write_IV);
+
+ if (entity == TLSEngine.CLIENT) {
+ return {read:server_write, write:client_write};
+ } else {
+ return {read:client_write, write:server_write};
+ }
+
+ } else {
+ return {read:new TLSConnectionState, write:new TLSConnectionState};
+ }
+ }
+
+ }
+} \ No newline at end of file
diff --git a/signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/TLSSocket.as b/signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/TLSSocket.as
new file mode 100644
index 0000000..10004a7
--- /dev/null
+++ b/signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/TLSSocket.as
@@ -0,0 +1,370 @@
+/**
+ * TLSSocket
+ *
+ * This is the "end-user" TLS class.
+ * It works just like a Socket, by encapsulating a Socket and
+ * wrapping the TLS protocol around the data that passes over it.
+ * This class can either create a socket connection, or reuse an
+ * existing connected socket. The later is useful for STARTTLS flows.
+ *
+ * Copyright (c) 2007 Henri Torgemane
+ *
+ * See LICENSE.txt for full license information.
+ */
+package com.hurlant.crypto.tls {
+ import flash.events.Event;
+ import flash.events.EventDispatcher;
+ import flash.events.IOErrorEvent;
+ import flash.events.ProgressEvent;
+ import flash.events.SecurityErrorEvent;
+ import flash.net.ObjectEncoding;
+ import flash.net.Socket;
+ import flash.utils.ByteArray;
+ import flash.utils.Endian;
+ import flash.utils.IDataInput;
+ import flash.utils.IDataOutput;
+ import flash.utils.clearTimeout;
+ import flash.utils.setTimeout;
+ import com.hurlant.crypto.cert.X509Certificate;
+
+
+ [Event(name="close", type="flash.events.Event")]
+ [Event(name="connect", type="flash.events.Event")]
+ [Event(name="ioError", type="flash.events.IOErrorEvent")]
+ [Event(name="securityError", type="flash.events.SecurityErrorEvent")]
+ [Event(name="socketData", type="flash.events.ProgressEvent")]
+ [Event(name="acceptPeerCertificatePrompt", type="flash.events.Event")]
+
+ /**
+ * It feels like a socket, but it wraps the stream
+ * over TLS 1.0
+ *
+ * That's all.
+ *
+ */
+ public class TLSSocket extends Socket implements IDataInput, IDataOutput {
+
+ private var _endian:String;
+ private var _objectEncoding:uint;
+
+ private var _iStream:ByteArray;
+ private var _oStream:ByteArray;
+ private var _iStream_cursor:uint;
+
+ private var _socket:Socket;
+ private var _config:TLSConfig;
+ private var _engine:TLSEngine;
+ public static const ACCEPT_PEER_CERT_PROMPT:String = "acceptPeerCertificatePrompt"
+
+ public function TLSSocket(host:String = null, port:int = 0, config:TLSConfig = null) {
+ _config = config;
+ if (host!=null && port!=0) {
+ connect(host, port);
+ }
+ }
+
+ override public function get bytesAvailable():uint {
+ return _iStream.bytesAvailable;
+ }
+ override public function get connected():Boolean {
+ return _socket.connected;
+ }
+ override public function get endian():String {
+ return _endian;
+ }
+ override public function set endian(value:String):void {
+ _endian = value;
+ _iStream.endian = value;
+ _oStream.endian = value;
+ }
+ override public function get objectEncoding():uint {
+ return _objectEncoding;
+ }
+ override public function set objectEncoding(value:uint):void {
+ _objectEncoding = value;
+ _iStream.objectEncoding = value;
+ _oStream.objectEncoding = value;
+ }
+
+
+ private function onTLSData(event:TLSEvent):void {
+ if (_iStream.position == _iStream.length) {
+ _iStream.position = 0;
+ _iStream.length = 0;
+ _iStream_cursor = 0;
+ }
+ var cursor:uint = _iStream.position;
+ _iStream.position = _iStream_cursor;
+ _iStream.writeBytes(event.data);
+ _iStream_cursor = _iStream.position;
+ _iStream.position = cursor;
+ dispatchEvent(new ProgressEvent(ProgressEvent.SOCKET_DATA, false, false, event.data.length));
+ }
+
+ private function onTLSReady(event:TLSEvent):void {
+ _ready = true;
+ scheduleWrite();
+ }
+
+ private function onTLSClose(event:Event):void {
+ dispatchEvent(event);
+ // trace("Received TLS close");
+ close();
+ }
+
+ private var _ready:Boolean;
+ private var _writeScheduler:uint;
+ private function scheduleWrite():void {
+ if (_writeScheduler!=0) return;
+ _writeScheduler = setTimeout(commitWrite, 0);
+ }
+ private function commitWrite():void {
+ clearTimeout(_writeScheduler);
+ _writeScheduler = 0;
+ if (_ready) {
+ _engine.sendApplicationData(_oStream);
+ _oStream.length = 0;
+ }
+ }
+
+
+ override public function close():void {
+ _ready = false;
+ _engine.close();
+ if (_socket.connected) {
+ _socket.flush();
+ _socket.close();
+ }
+ }
+ public function setTLSConfig( config:TLSConfig) : void {
+ _config = config;
+ }
+
+ override public function connect(host:String, port:int):void {
+ init(new Socket, _config, host);
+ _socket.connect(host, port);
+ _engine.start();
+ }
+
+ public function releaseSocket() : void {
+ _socket.removeEventListener(Event.CONNECT, dispatchEvent);
+ _socket.removeEventListener(IOErrorEvent.IO_ERROR, dispatchEvent);
+ _socket.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, dispatchEvent);
+ _socket.removeEventListener(Event.CLOSE, dispatchEvent);
+ _socket.removeEventListener(ProgressEvent.SOCKET_DATA, _engine.dataAvailable);
+ _socket = null;
+ }
+
+ public function reinitialize(host:String, config:TLSConfig) : void {
+ // Reinitialize the connection using new values
+ // but re-use the existing socket
+ // Doubt this is useful in any valid context other than my specific case (VMWare)
+ var ba:ByteArray = new ByteArray;
+
+ if (_socket.bytesAvailable > 0) {
+ _socket.readBytes(ba, 0, _socket.bytesAvailable);
+ }
+ // Do nothing with it.
+ _iStream = new ByteArray;
+ _oStream = new ByteArray;
+ _iStream_cursor = 0;
+ objectEncoding = ObjectEncoding.DEFAULT;
+ endian = Endian.BIG_ENDIAN;
+ /*
+ _socket.addEventListener(Event.CONNECT, dispatchEvent);
+ _socket.addEventListener(IOErrorEvent.IO_ERROR, dispatchEvent);
+ _socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, dispatchEvent);
+ _socket.addEventListener(Event.CLOSE, dispatchEvent);
+ */
+
+ if (config == null) {
+ config = new TLSConfig(TLSEngine.CLIENT);
+ }
+
+ _engine = new TLSEngine(config, _socket, _socket, host);
+ _engine.addEventListener(TLSEvent.DATA, onTLSData);
+ _engine.addEventListener(TLSEvent.READY, onTLSReady);
+ _engine.addEventListener(Event.CLOSE, onTLSClose);
+ _engine.addEventListener(ProgressEvent.SOCKET_DATA, function(e:*):void { _socket.flush(); });
+ _socket.addEventListener(ProgressEvent.SOCKET_DATA, _engine.dataAvailable);
+ _engine.addEventListener( TLSEvent.PROMPT_ACCEPT_CERT, onAcceptCert );
+
+ _ready = false;
+ _engine.start();
+ }
+
+ public function startTLS(socket:Socket, host:String, config:TLSConfig = null):void {
+ if (!socket.connected) {
+ throw new Error("Cannot STARTTLS on a socket that isn't connected.");
+ }
+ init(socket, config, host);
+ _engine.start();
+ }
+
+ private function init(socket:Socket, config:TLSConfig, host:String):void {
+ _iStream = new ByteArray;
+ _oStream = new ByteArray;
+ _iStream_cursor = 0;
+ objectEncoding = ObjectEncoding.DEFAULT;
+ endian = Endian.BIG_ENDIAN;
+ _socket = socket;
+ _socket.addEventListener(Event.CONNECT, dispatchEvent);
+ _socket.addEventListener(IOErrorEvent.IO_ERROR, dispatchEvent);
+ _socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, dispatchEvent);
+ _socket.addEventListener(Event.CLOSE, dispatchEvent);
+
+ if (config == null) {
+ config = new TLSConfig(TLSEngine.CLIENT);
+ }
+ _engine = new TLSEngine(config, _socket, _socket, host);
+ _engine.addEventListener(TLSEvent.DATA, onTLSData);
+ _engine.addEventListener( TLSEvent.PROMPT_ACCEPT_CERT, onAcceptCert );
+ _engine.addEventListener(TLSEvent.READY, onTLSReady);
+ _engine.addEventListener(Event.CLOSE, onTLSClose);
+ _engine.addEventListener(ProgressEvent.SOCKET_DATA, function(e:*):void { if(connected) _socket.flush(); });
+ _socket.addEventListener(ProgressEvent.SOCKET_DATA, _engine.dataAvailable);
+
+ _ready = false;
+ }
+
+ override public function flush():void {
+ commitWrite();
+ _socket.flush();
+ }
+
+ override public function readBoolean():Boolean {
+ return _iStream.readBoolean();
+ }
+
+ override public function readByte():int {
+ return _iStream.readByte();
+ }
+
+ override public function readBytes(bytes:ByteArray, offset:uint = 0, length:uint = 0):void {
+ return _iStream.readBytes(bytes, offset, length);
+ }
+
+ override public function readDouble():Number {
+ return _iStream.readDouble();
+ }
+
+ override public function readFloat():Number {
+ return _iStream.readFloat();
+ }
+
+ override public function readInt():int {
+ return _iStream.readInt();
+ }
+
+ override public function readMultiByte(length:uint, charSet:String):String {
+ return _iStream.readMultiByte(length, charSet);
+ }
+
+ override public function readObject():* {
+ return _iStream.readObject();
+ }
+
+ override public function readShort():int {
+ return _iStream.readShort();
+ }
+
+ override public function readUnsignedByte():uint {
+ return _iStream.readUnsignedByte();
+ }
+
+ override public function readUnsignedInt():uint {
+ return _iStream.readUnsignedInt();
+ }
+
+ override public function readUnsignedShort():uint {
+ return _iStream.readUnsignedShort();
+ }
+
+ override public function readUTF():String {
+ return _iStream.readUTF();
+ }
+
+ override public function readUTFBytes(length:uint):String {
+ return _iStream.readUTFBytes(length);
+ }
+
+ override public function writeBoolean(value:Boolean):void {
+ _oStream.writeBoolean(value);
+ scheduleWrite();
+ }
+
+ override public function writeByte(value:int):void {
+ _oStream.writeByte(value);
+ scheduleWrite();
+ }
+
+ override public function writeBytes(bytes:ByteArray, offset:uint = 0, length:uint = 0):void {
+ _oStream.writeBytes(bytes, offset, length);
+ scheduleWrite();
+ }
+
+ override public function writeDouble(value:Number):void {
+ _oStream.writeDouble(value);
+ scheduleWrite();
+ }
+
+ override public function writeFloat(value:Number):void {
+ _oStream.writeFloat(value);
+ scheduleWrite();
+ }
+
+ override public function writeInt(value:int):void {
+ _oStream.writeInt(value);
+ scheduleWrite();
+ }
+
+ override public function writeMultiByte(value:String, charSet:String):void {
+ _oStream.writeMultiByte(value, charSet);
+ scheduleWrite();
+ }
+
+ override public function writeObject(object:*):void {
+ _oStream.writeObject(object);
+ scheduleWrite();
+ }
+
+ override public function writeShort(value:int):void {
+ _oStream.writeShort(value);
+ scheduleWrite();
+ }
+
+ override public function writeUnsignedInt(value:uint):void {
+ _oStream.writeUnsignedInt(value);
+ scheduleWrite();
+ }
+
+ override public function writeUTF(value:String):void {
+ _oStream.writeUTF(value);
+ scheduleWrite();
+ }
+
+ override public function writeUTFBytes(value:String):void {
+ _oStream.writeUTFBytes(value);
+ scheduleWrite();
+ }
+
+ public function getPeerCertificate() : X509Certificate {
+ return _engine.peerCertificate;
+ }
+
+ public function onAcceptCert( event:TLSEvent ) : void {
+ dispatchEvent( new TLSSocketEvent( _engine.peerCertificate ) );
+ }
+
+ // These are just a passthroughs to the engine. Encapsulation, et al
+ public function acceptPeerCertificate( event:Event ) : void {
+ _engine.acceptPeerCertificate();
+ }
+
+ public function rejectPeerCertificate( event:Event ) : void {
+ _engine.rejectPeerCertificate();
+ }
+
+ }
+}
+
diff --git a/signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/TLSSocketEvent.as b/signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/TLSSocketEvent.as
new file mode 100644
index 0000000..c38f0dc
--- /dev/null
+++ b/signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/TLSSocketEvent.as
@@ -0,0 +1,26 @@
+/**
+ * TLSEvent
+ *
+ * This is used by TLSEngine to let the application layer know
+ * when we're ready for sending, or have received application data
+ * Copyright (c) 2007 Henri Torgemane
+ *
+ * See LICENSE.txt for full license information.
+ */
+package com.hurlant.crypto.tls {
+ import flash.events.Event;
+ import flash.utils.ByteArray;
+ import com.hurlant.crypto.cert.X509Certificate;
+
+ public class TLSSocketEvent extends Event {
+
+ static public const PROMPT_ACCEPT_CERT:String = "promptAcceptCert";
+
+ public var cert:X509Certificate;
+
+ public function TLSSocketEvent( cert:X509Certificate = null) {
+ super(PROMPT_ACCEPT_CERT, false, false);
+ this.cert = cert;
+ }
+ }
+} \ No newline at end of file
diff --git a/signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/TLSTest.as b/signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/TLSTest.as
new file mode 100644
index 0000000..d7c70f3
--- /dev/null
+++ b/signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/TLSTest.as
@@ -0,0 +1,180 @@
+/**
+ * TLSTest
+ *
+ * A test class for TLS. Not a finished product.
+ * Copyright (c) 2007 Henri Torgemane
+ *
+ * See LICENSE.txt for full license information.
+ */
+package com.hurlant.crypto.tls {
+ import com.hurlant.crypto.cert.X509Certificate;
+ import com.hurlant.crypto.cert.X509CertificateCollection;
+ import com.hurlant.util.Hex;
+ import com.hurlant.util.der.PEM;
+
+ import flash.events.Event;
+ import flash.events.ProgressEvent;
+ import flash.net.Socket;
+ import flash.utils.ByteArray;
+ import flash.utils.getTimer;
+
+ public class TLSTest {
+
+
+ public var myDebugData:String;
+
+ //[Embed(source="/src/host.cert",mimeType="application/octet-stream")]
+ public var myCert:Class;
+ //[Embed(source="/src/host.key",mimeType="application/octet-stream")]
+ public var myKey:Class;
+
+ public function TLSTest(host:String = null, port:int = 0, type:int = 0 ) {
+ //loopback();
+ if (host != null) {
+ if (type == 0) { // SSL 3.0
+ connectLoginYahooCom();
+ // connectLocalSSL(host, port);
+ } else {
+ connectLocalTLS(host, port);
+ }
+ } else {
+ testSocket();
+ }
+ }
+
+ public function connectLoginYahooCom():void {
+ trace("Connecting test socket");
+ var s:Socket = new Socket("esx.bluebearllc.net", 903);
+
+ var clientConfig:TLSConfig = new TLSConfig(TLSEngine.CLIENT,
+ null,
+ null,
+ null,
+ null,
+ null,
+ SSLSecurityParameters.PROTOCOL_VERSION);
+
+ var client:TLSEngine = new TLSEngine(clientConfig, s, s);
+ // hook some events.
+ s.addEventListener(ProgressEvent.SOCKET_DATA, client.dataAvailable);
+ client.addEventListener(ProgressEvent.SOCKET_DATA, function(e:*):void { s.flush(); });
+ client.start();
+
+ }
+ public function connectLocalTLS(host:String, port:int):void {
+ var s:Socket = new Socket(host, port);
+
+ var clientConfig:TLSConfig = new TLSConfig(TLSEngine.CLIENT);
+
+ var client:TLSEngine = new TLSEngine(clientConfig, s, s);
+ // hook some events.
+ s.addEventListener(ProgressEvent.SOCKET_DATA, client.dataAvailable);
+ client.addEventListener(ProgressEvent.SOCKET_DATA, function(e:*):void { s.flush(); });
+
+ client.start();
+
+ }
+ public function connectLocalSSL(host:String, port:int):void {
+ var s:Socket = new Socket(host, port);
+
+ var clientConfig:TLSConfig = new TLSConfig(TLSEngine.CLIENT,
+ null,
+ null,
+ null,
+ null,
+ null,
+ SSLSecurityParameters.PROTOCOL_VERSION);
+
+ var client:TLSEngine = new TLSEngine(clientConfig, s, s);
+ // hook some events.
+ s.addEventListener(ProgressEvent.SOCKET_DATA, client.dataAvailable);
+ client.addEventListener(ProgressEvent.SOCKET_DATA, function(e:*):void { s.flush(); });
+
+ client.start();
+ }
+
+ public function loopback():void {
+
+ var server_write:ByteArray = new ByteArray;
+ var client_write:ByteArray = new ByteArray;
+ var server_write_cursor:uint = 0;
+ var client_write_cursor:uint = 0;
+
+ var clientConfig:TLSConfig = new TLSConfig(TLSEngine.CLIENT, null, null, null, null, null, SSLSecurityParameters.PROTOCOL_VERSION);
+ var serverConfig:TLSConfig = new TLSConfig(TLSEngine.SERVER, null, null, null, null, null, SSLSecurityParameters.PROTOCOL_VERSION);
+
+
+ var cert:ByteArray = new myCert;
+ var key:ByteArray = new myKey;
+ serverConfig.setPEMCertificate(cert.readUTFBytes(cert.length), key.readUTFBytes(key.length));
+ // tmp, for debugging. currently useless
+ cert.position = 0;
+ key.position = 0;
+ clientConfig.setPEMCertificate(cert.readUTFBytes(cert.length), key.readUTFBytes(key.length));
+ // put the server cert in the client's trusted store, to keep things happy.
+ clientConfig.CAStore = new X509CertificateCollection;
+ cert.position = 0;
+ var x509:X509Certificate = new X509Certificate(PEM.readCertIntoArray(cert.readUTFBytes(cert.length)));
+ clientConfig.CAStore.addCertificate(x509);
+
+
+ var server:TLSEngine = new TLSEngine(serverConfig, client_write, server_write);
+ var client:TLSEngine = new TLSEngine(clientConfig, server_write, client_write);
+
+ server.addEventListener(ProgressEvent.SOCKET_DATA, function(e:*=null):void {
+ trace("server wrote something!");
+ trace(Hex.fromArray(server_write));
+ var l:uint = server_write.position;
+ server_write.position = server_write_cursor;
+ client.dataAvailable(e);
+ server_write.position = l;
+ server_write_cursor = l;
+ });
+ client.addEventListener(ProgressEvent.SOCKET_DATA, function(e:*=null):void {
+ trace("client wrote something!");
+ trace(Hex.fromArray(client_write));
+ var l:uint = client_write.position;
+ client_write.position = client_write_cursor;
+ server.dataAvailable(e);
+ client_write.position = l;
+ client_write_cursor = l;
+ });
+
+ server.start();
+ client.start();
+ }
+
+ public function testSocket():void {
+ var hosts:Array = [
+ "bugs.adobe.com", // apache
+ "login.yahoo.com", // apache, bigger response
+ "login.live.com", // IIS-6, chain of 3 certs
+ "banking.wellsfargo.com", // custom, sends its CA cert along for the ride.
+ "www.bankofamerica.com" // sun-one, chain of 3 certs
+ ];
+ var i:int =0;
+ (function next():void {
+ testHost(hosts[i++], next);
+ })();
+ }
+
+ private function testHost(host:String, next:Function):void {
+ if (host==null) return;
+ var t1:int = getTimer();
+
+ var host:String = host;
+ var t:TLSSocket = new TLSSocket;
+ t.connect(host, 4433);
+ t.writeUTFBytes("GET / HTTP/1.0\nHost: "+host+"\n\n");
+ t.addEventListener(Event.CLOSE, function(e:*):void {
+ var s:String = t.readUTFBytes(t.bytesAvailable);
+ trace("Response from "+host+": "+s.length+" characters");
+ var bytes:ByteArray = new ByteArray();
+ t.readBytes(bytes, 0, t.bytesAvailable);
+ trace(Hex.fromArray(bytes));
+ trace("Time used = "+(getTimer()-t1)+"ms");
+ next();
+ });
+ }
+ }
+}