From b60df56157ee1fd0bd4938799bac05a62fda91a1 Mon Sep 17 00:00:00 2001 From: lookshe Date: Sat, 14 Mar 2015 20:45:20 +0100 Subject: initial commit from working version --- .../com/hurlant/crypto/tls/BulkCiphers.as | 102 +++ .../com/hurlant/crypto/tls/CipherSuites.as | 117 +++ .../com/hurlant/crypto/tls/IConnectionState.as | 14 + .../com/hurlant/crypto/tls/ISecurityParameters.as | 29 + .../com/hurlant/crypto/tls/KeyExchanges.as | 24 + .../flash-src/com/hurlant/crypto/tls/MACs.as | 38 + .../com/hurlant/crypto/tls/SSLConnectionState.as | 171 ++++ .../flash-src/com/hurlant/crypto/tls/SSLEvent.as | 26 + .../hurlant/crypto/tls/SSLSecurityParameters.as | 340 ++++++++ .../flash-src/com/hurlant/crypto/tls/TLSConfig.as | 70 ++ .../com/hurlant/crypto/tls/TLSConnectionState.as | 151 ++++ .../flash-src/com/hurlant/crypto/tls/TLSEngine.as | 895 +++++++++++++++++++++ .../flash-src/com/hurlant/crypto/tls/TLSError.as | 39 + .../flash-src/com/hurlant/crypto/tls/TLSEvent.as | 27 + .../hurlant/crypto/tls/TLSSecurityParameters.as | 197 +++++ .../flash-src/com/hurlant/crypto/tls/TLSSocket.as | 370 +++++++++ .../com/hurlant/crypto/tls/TLSSocketEvent.as | 26 + .../flash-src/com/hurlant/crypto/tls/TLSTest.as | 180 +++++ 18 files changed, 2816 insertions(+) create mode 100644 signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/BulkCiphers.as create mode 100644 signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/CipherSuites.as create mode 100644 signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/IConnectionState.as create mode 100755 signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/ISecurityParameters.as create mode 100644 signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/KeyExchanges.as create mode 100644 signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/MACs.as create mode 100644 signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/SSLConnectionState.as create mode 100755 signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/SSLEvent.as create mode 100755 signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/SSLSecurityParameters.as create mode 100644 signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/TLSConfig.as create mode 100644 signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/TLSConnectionState.as create mode 100644 signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/TLSEngine.as create mode 100644 signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/TLSError.as create mode 100644 signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/TLSEvent.as create mode 100644 signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/TLSSecurityParameters.as create mode 100644 signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/TLSSocket.as create mode 100644 signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/TLSSocketEvent.as create mode 100644 signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/TLSTest.as (limited to 'signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls') 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 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;i0) { + 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-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 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(); + }); + } + } +} -- cgit v1.2.3