using System; using System.Net; using System.Text; using System.Timers; using System.Collections.Specialized; namespace MessageRouter { public delegate void OnMessageRouterMessageReceivedDelegate(MessageRouterClient client, string messageType, string eventType, StringDictionary parameters); public class MessageRouterClient : MessageRouterConnection { private const char CRYPT_FORMAT_NONE = '5'; // 5 private const char MESSAGE_VERSION = '2'; // 2 public OnMessageRouterMessageReceivedDelegate OnMessageRouterMessageReceived; private char cryptFormat; private char messageVersion; private Timer echoTimer; public MessageRouterClient(IPEndPoint serverEndPoint) : this(serverEndPoint, CRYPT_FORMAT_NONE, MESSAGE_VERSION) { } public MessageRouterClient(IPEndPoint serverEndPoint, char cryptFormat, char messageVersion) : base(serverEndPoint) { this.cryptFormat = cryptFormat; this.messageVersion = messageVersion; // NOTE: Message Version only exists if Crypt Format > 5 Init(); } private void Init() { OnPacketReceived += new OnMessageRouterPacketReceivedDelegate(MessageRouterPacketReceived); echoTimer = new Timer(150 * 1000); // 150 secs echoTimer.Elapsed += new ElapsedEventHandler(EchoTimerElapsed); echoTimer.Enabled = true; } void EchoTimerElapsed(object sender, ElapsedEventArgs e) { this.SendEcho(); } protected void MessageRouterPacketReceived(MessageRouterConnection client, MessageRouterPacket p) { // Parse message router packet and retrieve // 1. Message Type // 2. Event Type // 3. Parameters ASCIIEncoding enc = new ASCIIEncoding(); string data = enc.GetString(p.buf); if (cryptFormat != '5') { byte[] bytes = new byte[p.buf.Length - 1]; Buffer.BlockCopy(p.buf, 0, bytes, 0, p.buf.Length - 1); // trim '^' string szKey = string.Format("{0:d5}|{1:c}|{2:d6}", p.buf.Length, cryptFormat, LocalPort); byte[] ba = SSFCrypt(bytes, szKey); data = enc.GetString(ba); } //Console.WriteLine("READ DATA: " + data); string[] entries = data.Split(new Char[] { '|' }); // Message Version (0) // User ID (1) // Message Type (2) // Event Type (3) // Destination (4) // Origin (5) // Parameters in name=value format // ^ if (entries.Length < 8) { // TODO: Handle malformed message dta } string msgType = entries[2]; string evtType = entries[3]; StringDictionary sd = new StringDictionary(); for (int i = 6; i < entries.Length - 1; i++) { string param = entries[i]; // find the first index of '=' int pos = param.IndexOf('='); if (pos == -1) continue; string key = param.Substring(0, pos); string val = param.Substring(pos + 1); if (key == null || key.Length == 0) continue; sd.Add(key, val); } if (OnMessageRouterMessageReceived != null) OnMessageRouterMessageReceived(this, msgType, evtType, sd); } private bool SendEcho() { String msg = this.messageVersion + "||ECHO|||||^"; return SendMessage(msg); } public bool SendMessage(string msg) { //Console.WriteLine("WRITE LEN: {0}", msg.Length + 1); //Console.WriteLine("WRITE CRYPT: {0}", cryptFormat); //Console.WriteLine("WRITE DATA: {0}", msg); string msgx; if (cryptFormat != '5') { msg = msg.TrimEnd('^'); string szKey = string.Format("{0:d5}|{1:c}|{2:d6}", msg.Length + 1, cryptFormat, LocalPort); return Write(cryptFormat, SSFCrypt(msg, szKey)); } msgx = msg; ASCIIEncoding encoding = new ASCIIEncoding(); return Write(cryptFormat, encoding.GetBytes(msgx)); } private byte[] SSFCrypt(string data, string key) { ASCIIEncoding enc = new ASCIIEncoding(); byte[] ba = enc.GetBytes(data); return SSFCrypt(ba, key); } private byte[] SSFCrypt(byte[] data, string key) { //we will consider size of sbox 256 bytes //(extra byte are only to prevent any mishep just in case) sbyte[] Sbox = new sbyte[257]; sbyte[] Sbox2 = new sbyte[257]; UInt32 i, j, t; sbyte temp, k; i = j = t = 0; temp = k = (sbyte)0x00; //always initialize the arrays with zero for (i = 0; i < 257; i++) { Sbox[i] = Sbox2[i] = (sbyte)0x00; } //initialize sbox i for (i = 0; i < 256; i++) { Sbox[i] = (sbyte)i; } j = 0; //initialize the sbox2 with user key for (i = 0; i < 256; i++) { if (j == Convert.ToUInt32(key.Length)) { j = 0; } Sbox2[i] = (sbyte)key[Convert.ToInt32(j++)]; } j = 0; //Initialize j //scramble sbox1 with sbox2 for (i = 0; i < 256; i++) { j = (j + (UInt32)Sbox[i] + (UInt32)Sbox2[i]) % 256; temp = Sbox[i]; Sbox[i] = Sbox[j]; Sbox[j] = temp; } i = j = 0; sbyte[] res = new sbyte[data.Length]; for (int x = 0; x < data.Length; x++) { //increment i i = (i + 1) % 256; //increment j j = (j + (UInt32)Sbox[i]) % 256; //Scramble SBox #1 further so encryption routine will //will repeat itself at great interval temp = Sbox[i]; Sbox[i] = Sbox[j]; Sbox[j] = temp; //Get ready to create pseudo random byte for encryption key t = ((UInt32)Sbox[i] + (UInt32)Sbox[j]) % 256; //get the random byte k = Sbox[t]; //xor with the data and done res[x] = (sbyte)(data[x] ^ k); } byte[] bytes = new byte[res.Length + 1]; Buffer.BlockCopy(res, 0, bytes, 0, res.Length); bytes[res.Length] = 0x5E; // '^' return bytes; } } }