diff --git a/shadowsocks-csharp/Config.cs b/shadowsocks-csharp/Config.cs index efd75893..23a0a942 100755 --- a/shadowsocks-csharp/Config.cs +++ b/shadowsocks-csharp/Config.cs @@ -14,6 +14,7 @@ namespace shadowsocks_csharp public int server_port; public int local_port; public string password; + public string method; public bool isDefault; @@ -49,6 +50,7 @@ namespace shadowsocks_csharp server_port = 8388, local_port = 1081, password = "barfoo!", + method = "table", isDefault = true }; } @@ -65,7 +67,8 @@ namespace shadowsocks_csharp server = config.server, server_port = config.server_port, local_port = config.local_port, - password = config.password + password = config.password, + method = config.method }); sw.Write(jsonString); sw.Flush(); diff --git a/shadowsocks-csharp/Encryptor.cs b/shadowsocks-csharp/Encryptor.cs index d998cda8..76907635 100755 --- a/shadowsocks-csharp/Encryptor.cs +++ b/shadowsocks-csharp/Encryptor.cs @@ -7,8 +7,13 @@ namespace shadowsocks_csharp { class Encryptor { + public const int TYPE_TABLE = 1; + public const int TYPE_RC4 = 2; + public byte[] encryptTable = new byte[256]; public byte[] decryptTable = new byte[256]; + public int method = TYPE_TABLE; + public RC4 rc4 = null; private long compare(byte x, byte y, ulong a, int i) { @@ -53,43 +58,65 @@ namespace shadowsocks_csharp return sorted; } - public Encryptor(string password) + public Encryptor(string method, string password) { MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.UTF8.GetBytes(password); byte[] hash = md5.ComputeHash(inputBytes); - // TODO endian - var a = BitConverter.ToUInt64(hash, 0); - for (int i = 0; i < 256; i++) - { - encryptTable[i] = (byte)i; - } - for (int i = 1; i < 1024; i++) - { - encryptTable = mergeSort(encryptTable, a, i); - } - for (int i = 0; i < 256; i++) - { - decryptTable[encryptTable[i]] = (byte)i; + if (method != null && method.ToLowerInvariant().Equals("rc4")) { + Console.WriteLine("init rc4"); + this.method = TYPE_RC4; + + rc4 = new RC4(); + encryptTable = rc4.EncryptInitalize(hash); + decryptTable = rc4.EncryptInitalize(hash); + } else { + Console.WriteLine("init table"); + this.method = TYPE_TABLE; + + // TODO endian + var a = BitConverter.ToUInt64(hash, 0); + for (int i = 0; i < 256; i++) + { + encryptTable[i] = (byte)i; + } + for (int i = 1; i < 1024; i++) + { + encryptTable = mergeSort(encryptTable, a, i); + } + for (int i = 0; i < 256; i++) + { + decryptTable[encryptTable[i]] = (byte)i; + } } } public void Encrypt(byte[] buf, int length) { - for (int i = 0; i < length; i++) + switch (method) { - buf[i] = encryptTable[buf[i]]; + case TYPE_TABLE: + for (int i = 0; i < length; i++) + buf[i] = encryptTable[buf[i]]; + break; + case TYPE_RC4: + rc4.Encrypt(encryptTable, buf, length); + break; } } public void Decrypt(byte[] buf, int length) { - for (int i = 0; i < length; i++) + switch (method) { - buf[i] = decryptTable[buf[i]]; + case TYPE_TABLE: + for (int i = 0; i < length; i++) + buf[i] = decryptTable[buf[i]]; + break; + case TYPE_RC4: + rc4.Decrypt(decryptTable, buf, length); + break; } } - - } } diff --git a/shadowsocks-csharp/Form1.Designer.cs b/shadowsocks-csharp/Form1.Designer.cs index 9890ebf6..b8162824 100755 --- a/shadowsocks-csharp/Form1.Designer.cs +++ b/shadowsocks-csharp/Form1.Designer.cs @@ -31,26 +31,29 @@ this.components = new System.ComponentModel.Container(); System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form1)); this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); + this.label5 = new System.Windows.Forms.Label(); this.label1 = new System.Windows.Forms.Label(); this.label2 = new System.Windows.Forms.Label(); + this.comboBox1 = new System.Windows.Forms.ComboBox(); this.label3 = new System.Windows.Forms.Label(); this.label4 = new System.Windows.Forms.Label(); this.textBox1 = new System.Windows.Forms.TextBox(); this.textBox2 = new System.Windows.Forms.TextBox(); this.textBox3 = new System.Windows.Forms.TextBox(); this.textBox4 = new System.Windows.Forms.TextBox(); - this.panel1 = new System.Windows.Forms.Panel(); - this.button2 = new System.Windows.Forms.Button(); - this.button1 = new System.Windows.Forms.Button(); this.notifyIcon1 = new System.Windows.Forms.NotifyIcon(this.components); this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components); this.ConfigItem = new System.Windows.Forms.ToolStripMenuItem(); this.aboutToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator(); this.QuitItem = new System.Windows.Forms.ToolStripMenuItem(); + this.panel2 = new System.Windows.Forms.Panel(); + this.button1 = new System.Windows.Forms.Button(); + this.button2 = new System.Windows.Forms.Button(); + this.panel1 = new System.Windows.Forms.Panel(); this.tableLayoutPanel1.SuspendLayout(); - this.panel1.SuspendLayout(); this.contextMenuStrip1.SuspendLayout(); + this.panel1.SuspendLayout(); this.SuspendLayout(); // // tableLayoutPanel1 @@ -60,33 +63,44 @@ this.tableLayoutPanel1.ColumnCount = 2; this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanel1.Controls.Add(this.label5, 0, 4); this.tableLayoutPanel1.Controls.Add(this.label1, 0, 0); this.tableLayoutPanel1.Controls.Add(this.label2, 0, 1); + this.tableLayoutPanel1.Controls.Add(this.comboBox1, 1, 4); this.tableLayoutPanel1.Controls.Add(this.label3, 0, 2); this.tableLayoutPanel1.Controls.Add(this.label4, 0, 3); this.tableLayoutPanel1.Controls.Add(this.textBox1, 1, 0); this.tableLayoutPanel1.Controls.Add(this.textBox2, 1, 1); this.tableLayoutPanel1.Controls.Add(this.textBox3, 1, 2); this.tableLayoutPanel1.Controls.Add(this.textBox4, 1, 3); - this.tableLayoutPanel1.Location = new System.Drawing.Point(12, 12); + this.tableLayoutPanel1.Location = new System.Drawing.Point(22, 12); this.tableLayoutPanel1.Name = "tableLayoutPanel1"; - this.tableLayoutPanel1.RowCount = 4; + this.tableLayoutPanel1.RowCount = 5; + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); - this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); - this.tableLayoutPanel1.Size = new System.Drawing.Size(196, 104); + this.tableLayoutPanel1.Size = new System.Drawing.Size(203, 131); this.tableLayoutPanel1.TabIndex = 0; // + // label5 + // + this.label5.Anchor = System.Windows.Forms.AnchorStyles.Right; + this.label5.AutoSize = true; + this.label5.Location = new System.Drawing.Point(12, 110); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(58, 15); + this.label5.TabIndex = 8; + this.label5.Text = "Encryptor"; + // // label1 // this.label1.Anchor = System.Windows.Forms.AnchorStyles.Right; this.label1.AutoSize = true; - this.label1.Location = new System.Drawing.Point(12, 6); + this.label1.Location = new System.Drawing.Point(14, 5); this.label1.Name = "label1"; - this.label1.Size = new System.Drawing.Size(51, 13); + this.label1.Size = new System.Drawing.Size(56, 15); this.label1.TabIndex = 0; this.label1.Text = "Server IP"; // @@ -94,19 +108,33 @@ // this.label2.Anchor = System.Windows.Forms.AnchorStyles.Right; this.label2.AutoSize = true; - this.label2.Location = new System.Drawing.Point(3, 32); + this.label2.Location = new System.Drawing.Point(3, 31); this.label2.Name = "label2"; - this.label2.Size = new System.Drawing.Size(60, 13); + this.label2.Size = new System.Drawing.Size(67, 15); this.label2.TabIndex = 1; this.label2.Text = "Server Port"; // + // comboBox1 + // + this.comboBox1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBox1.FormattingEnabled = true; + this.comboBox1.ImeMode = System.Windows.Forms.ImeMode.NoControl; + this.comboBox1.ItemHeight = 13; + this.comboBox1.Items.AddRange(new object[] { + "table", + "rc4"}); + this.comboBox1.Location = new System.Drawing.Point(76, 107); + this.comboBox1.Name = "comboBox1"; + this.comboBox1.Size = new System.Drawing.Size(124, 21); + this.comboBox1.TabIndex = 9; + // // label3 // this.label3.Anchor = System.Windows.Forms.AnchorStyles.Right; this.label3.AutoSize = true; - this.label3.Location = new System.Drawing.Point(10, 58); + this.label3.Location = new System.Drawing.Point(9, 57); this.label3.Name = "label3"; - this.label3.Size = new System.Drawing.Size(53, 13); + this.label3.Size = new System.Drawing.Size(61, 15); this.label3.TabIndex = 2; this.label3.Text = "Password"; // @@ -114,16 +142,16 @@ // this.label4.Anchor = System.Windows.Forms.AnchorStyles.Right; this.label4.AutoSize = true; - this.label4.Location = new System.Drawing.Point(8, 84); + this.label4.Location = new System.Drawing.Point(8, 83); this.label4.Name = "label4"; - this.label4.Size = new System.Drawing.Size(55, 13); + this.label4.Size = new System.Drawing.Size(62, 15); this.label4.TabIndex = 3; this.label4.Text = "Proxy Port"; // // textBox1 // this.textBox1.Anchor = System.Windows.Forms.AnchorStyles.Left; - this.textBox1.Location = new System.Drawing.Point(69, 3); + this.textBox1.Location = new System.Drawing.Point(76, 3); this.textBox1.Name = "textBox1"; this.textBox1.Size = new System.Drawing.Size(124, 20); this.textBox1.TabIndex = 4; @@ -132,7 +160,7 @@ // textBox2 // this.textBox2.Anchor = System.Windows.Forms.AnchorStyles.Left; - this.textBox2.Location = new System.Drawing.Point(69, 29); + this.textBox2.Location = new System.Drawing.Point(76, 29); this.textBox2.Name = "textBox2"; this.textBox2.Size = new System.Drawing.Size(124, 20); this.textBox2.TabIndex = 5; @@ -141,7 +169,7 @@ // textBox3 // this.textBox3.Anchor = System.Windows.Forms.AnchorStyles.Left; - this.textBox3.Location = new System.Drawing.Point(69, 55); + this.textBox3.Location = new System.Drawing.Point(76, 55); this.textBox3.Name = "textBox3"; this.textBox3.Size = new System.Drawing.Size(124, 20); this.textBox3.TabIndex = 6; @@ -150,46 +178,12 @@ // textBox4 // this.textBox4.Anchor = System.Windows.Forms.AnchorStyles.Left; - this.textBox4.Location = new System.Drawing.Point(69, 81); + this.textBox4.Location = new System.Drawing.Point(76, 81); this.textBox4.Name = "textBox4"; this.textBox4.Size = new System.Drawing.Size(124, 20); this.textBox4.TabIndex = 7; this.textBox4.WordWrap = false; // - // panel1 - // - this.panel1.Anchor = System.Windows.Forms.AnchorStyles.Top; - this.panel1.AutoSize = true; - this.panel1.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; - this.panel1.Controls.Add(this.button2); - this.panel1.Controls.Add(this.button1); - this.panel1.Location = new System.Drawing.Point(59, 128); - this.panel1.Name = "panel1"; - this.panel1.Size = new System.Drawing.Size(164, 30); - this.panel1.TabIndex = 1; - // - // button2 - // - this.button2.DialogResult = System.Windows.Forms.DialogResult.Cancel; - this.button2.Location = new System.Drawing.Point(86, 4); - this.button2.Name = "button2"; - this.button2.Size = new System.Drawing.Size(75, 23); - this.button2.TabIndex = 1; - this.button2.Text = "Cancel"; - this.button2.UseVisualStyleBackColor = true; - this.button2.Click += new System.EventHandler(this.cancelButton_Click); - // - // button1 - // - this.button1.DialogResult = System.Windows.Forms.DialogResult.OK; - this.button1.Location = new System.Drawing.Point(4, 4); - this.button1.Name = "button1"; - this.button1.Size = new System.Drawing.Size(75, 23); - this.button1.TabIndex = 0; - this.button1.Text = "OK"; - this.button1.UseVisualStyleBackColor = true; - this.button1.Click += new System.EventHandler(this.OKButton_Click); - // // notifyIcon1 // this.notifyIcon1.ContextMenuStrip = this.contextMenuStrip1; @@ -207,35 +201,79 @@ this.QuitItem}); this.contextMenuStrip1.Name = "contextMenuStrip1"; this.contextMenuStrip1.RenderMode = System.Windows.Forms.ToolStripRenderMode.System; - this.contextMenuStrip1.Size = new System.Drawing.Size(111, 76); + this.contextMenuStrip1.Size = new System.Drawing.Size(123, 82); // // ConfigItem // this.ConfigItem.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Bold); this.ConfigItem.Name = "ConfigItem"; - this.ConfigItem.Size = new System.Drawing.Size(110, 22); + this.ConfigItem.Size = new System.Drawing.Size(122, 24); this.ConfigItem.Text = "Config"; this.ConfigItem.Click += new System.EventHandler(this.Config_Click); // // aboutToolStripMenuItem // this.aboutToolStripMenuItem.Name = "aboutToolStripMenuItem"; - this.aboutToolStripMenuItem.Size = new System.Drawing.Size(110, 22); + this.aboutToolStripMenuItem.Size = new System.Drawing.Size(122, 24); this.aboutToolStripMenuItem.Text = "About"; this.aboutToolStripMenuItem.Click += new System.EventHandler(this.aboutToolStripMenuItem_Click); // // toolStripSeparator2 // this.toolStripSeparator2.Name = "toolStripSeparator2"; - this.toolStripSeparator2.Size = new System.Drawing.Size(107, 6); + this.toolStripSeparator2.Size = new System.Drawing.Size(119, 6); // // QuitItem // this.QuitItem.Name = "QuitItem"; - this.QuitItem.Size = new System.Drawing.Size(110, 22); + this.QuitItem.Size = new System.Drawing.Size(122, 24); this.QuitItem.Text = "Quit"; this.QuitItem.Click += new System.EventHandler(this.Quit_Click); // + // panel2 + // + this.panel2.Anchor = System.Windows.Forms.AnchorStyles.Top; + this.panel2.AutoSize = true; + this.panel2.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; + this.panel2.Location = new System.Drawing.Point(61, 175); + this.panel2.Name = "panel2"; + this.panel2.Size = new System.Drawing.Size(0, 0); + this.panel2.TabIndex = 1; + // + // button1 + // + this.button1.DialogResult = System.Windows.Forms.DialogResult.OK; + this.button1.Location = new System.Drawing.Point(4, 4); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(75, 23); + this.button1.TabIndex = 0; + this.button1.Text = "OK"; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.OKButton_Click); + // + // button2 + // + this.button2.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.button2.Location = new System.Drawing.Point(86, 4); + this.button2.Name = "button2"; + this.button2.Size = new System.Drawing.Size(75, 23); + this.button2.TabIndex = 1; + this.button2.Text = "Cancel"; + this.button2.UseVisualStyleBackColor = true; + this.button2.Click += new System.EventHandler(this.cancelButton_Click); + // + // panel1 + // + this.panel1.Anchor = System.Windows.Forms.AnchorStyles.Top; + this.panel1.AutoSize = true; + this.panel1.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; + this.panel1.Controls.Add(this.button2); + this.panel1.Controls.Add(this.button1); + this.panel1.Location = new System.Drawing.Point(61, 153); + this.panel1.Name = "panel1"; + this.panel1.Size = new System.Drawing.Size(164, 30); + this.panel1.TabIndex = 1; + // // Form1 // this.AcceptButton = this.button1; @@ -245,6 +283,7 @@ this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; this.CancelButton = this.button2; this.ClientSize = new System.Drawing.Size(282, 206); + this.Controls.Add(this.panel2); this.Controls.Add(this.tableLayoutPanel1); this.Controls.Add(this.panel1); this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); @@ -255,8 +294,8 @@ this.Load += new System.EventHandler(this.Form1_Load); this.tableLayoutPanel1.ResumeLayout(false); this.tableLayoutPanel1.PerformLayout(); - this.panel1.ResumeLayout(false); this.contextMenuStrip1.ResumeLayout(false); + this.panel1.ResumeLayout(false); this.ResumeLayout(false); this.PerformLayout(); @@ -273,15 +312,18 @@ private System.Windows.Forms.TextBox textBox2; private System.Windows.Forms.TextBox textBox3; private System.Windows.Forms.TextBox textBox4; - private System.Windows.Forms.Panel panel1; - private System.Windows.Forms.Button button2; - private System.Windows.Forms.Button button1; private System.Windows.Forms.NotifyIcon notifyIcon1; private System.Windows.Forms.ContextMenuStrip contextMenuStrip1; private System.Windows.Forms.ToolStripMenuItem ConfigItem; private System.Windows.Forms.ToolStripMenuItem QuitItem; private System.Windows.Forms.ToolStripMenuItem aboutToolStripMenuItem; private System.Windows.Forms.ToolStripSeparator toolStripSeparator2; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.ComboBox comboBox1; + private System.Windows.Forms.Panel panel2; + private System.Windows.Forms.Button button1; + private System.Windows.Forms.Button button2; + private System.Windows.Forms.Panel panel1; } } diff --git a/shadowsocks-csharp/Form1.cs b/shadowsocks-csharp/Form1.cs index 383ad52d..9543b4d6 100755 --- a/shadowsocks-csharp/Form1.cs +++ b/shadowsocks-csharp/Form1.cs @@ -32,6 +32,7 @@ namespace shadowsocks_csharp textBox2.Text = config.server_port.ToString(); textBox3.Text = config.password; textBox4.Text = config.local_port.ToString(); + comboBox1.Text = config.method == null ? "table" : config.method; } private void Form1_Load(object sender, EventArgs e) @@ -77,6 +78,7 @@ namespace shadowsocks_csharp server_port = int.Parse(textBox2.Text), password = textBox3.Text, local_port = int.Parse(textBox4.Text), + method = comboBox1.Text, isDefault = false }; Config.Save(config); @@ -102,7 +104,7 @@ namespace shadowsocks_csharp private void Form1_FormClosed(object sender, FormClosedEventArgs e) { - local.Stop(); + if (local != null) local.Stop(); } private void aboutToolStripMenuItem_Click(object sender, EventArgs e) diff --git a/shadowsocks-csharp/Local.cs b/shadowsocks-csharp/Local.cs index 6434fcbd..2dd7108c 100755 --- a/shadowsocks-csharp/Local.cs +++ b/shadowsocks-csharp/Local.cs @@ -16,7 +16,7 @@ namespace shadowsocks_csharp public Local(Config config) { this.config = config; - this.encryptor = new Encryptor(config.password); + this.encryptor = new Encryptor(config.method, config.password); } public void Start() @@ -62,7 +62,11 @@ namespace shadowsocks_csharp // Create the state object. Handler handler = new Handler(); handler.connection = conn; - handler.encryptor = encryptor; + if (encryptor.method == Encryptor.TYPE_TABLE) { + handler.encryptor = encryptor; + } else { + handler.encryptor = new Encryptor(config.method, config.password); + } handler.config = config; handler.Start(); diff --git a/shadowsocks-csharp/RC4.cs b/shadowsocks-csharp/RC4.cs new file mode 100755 index 00000000..78ca36a2 --- /dev/null +++ b/shadowsocks-csharp/RC4.cs @@ -0,0 +1,68 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace shadowsocks_csharp +{ + public class RC4 + { + + int enc_index1 = 0; + int enc_index2 = 0; + + int dec_index1 = 0; + int dec_index2 = 0; + + public void Encrypt(byte[] table, byte[] data, int length) + { + EncryptOutput(enc_index1, enc_index2, table, data, length); + } + + public void Decrypt(byte[] table, byte[] data, int length) + { + EncryptOutput(dec_index1, dec_index2, table, data, length); + } + + public byte[] EncryptInitalize(byte[] key) + { + byte[] s = new byte[256]; + + for (int i = 0; i < 256; i++) + { + s[i] = (byte)i; + } + + for (int i = 0, j = 0; i < 256; i++) + { + j = (j + key[i % key.Length] + s[i]) & 255; + + Swap(s, i, j); + } + + return s; + } + + private void EncryptOutput(int index1, int index2, byte[] s, byte[] data, int length) + { + for (int n = 0; n < length; n++) + { + byte b = data[n]; + + index1 = (index1 + 1) & 255; + index2 = (index2 + s[index1]) & 255; + + Swap(s, index1, index2); + + data[n] = (byte)(b ^ s[(s[index1] + s[index2]) & 255]); + } + } + + private static void Swap(byte[] s, int i, int j) + { + byte c = s[i]; + + s[i] = s[j]; + s[j] = c; + } + } +} diff --git a/shadowsocks-csharp/Test.cs b/shadowsocks-csharp/Test.cs index ec255550..1c29c771 100755 --- a/shadowsocks-csharp/Test.cs +++ b/shadowsocks-csharp/Test.cs @@ -12,7 +12,7 @@ namespace shadowsocks_csharp public static void Test1() { - Encryptor encryptor = new Encryptor("foobar!"); + Encryptor encryptor = new Encryptor("table", "foobar!"); for (int i = 0; i < 256; i++) { diff --git a/shadowsocks-csharp/shadowsocks-csharp.csproj b/shadowsocks-csharp/shadowsocks-csharp.csproj index 0b6a5b90..9971b185 100755 --- a/shadowsocks-csharp/shadowsocks-csharp.csproj +++ b/shadowsocks-csharp/shadowsocks-csharp.csproj @@ -62,6 +62,7 @@ +