From 695716cd299c970748d0af8f42a07c6c87f655c6 Mon Sep 17 00:00:00 2001 From: Student Main Date: Fri, 14 Feb 2020 22:38:01 +0800 Subject: [PATCH] bring back table, add plain revert d24548a04f4701dfe9f3e07d6305b5ba3b7a56f8 --- .../Stream/StreamNativeEncryptor.cs | 134 +++++++++++++++--- shadowsocks-csharp/View/ConfigForm.cs | 4 + 2 files changed, 117 insertions(+), 21 deletions(-) diff --git a/shadowsocks-csharp/Encryption/Stream/StreamNativeEncryptor.cs b/shadowsocks-csharp/Encryption/Stream/StreamNativeEncryptor.cs index ecc72535..f30bedd4 100644 --- a/shadowsocks-csharp/Encryption/Stream/StreamNativeEncryptor.cs +++ b/shadowsocks-csharp/Encryption/Stream/StreamNativeEncryptor.cs @@ -8,12 +8,18 @@ namespace Shadowsocks.Encryption.Stream { public class StreamNativeEncryptor : StreamEncryptor { - bool md5; + const int Plain = 0; + const int Table = 1; + const int Rc4 = 2; + const int Rc4Md5 = 3; + + string _password; + byte[] realkey; byte[] sbox; public StreamNativeEncryptor(string method, string password) : base(method, password) { - md5 = method.ToLowerInvariant().IndexOf("md5") >= 0; + _password = password; } public override void Dispose() @@ -24,37 +30,71 @@ namespace Shadowsocks.Encryption.Stream protected override void initCipher(byte[] iv, bool isEncrypt) { base.initCipher(iv, isEncrypt); - if (md5) + if (_cipher >= Rc4) { - byte[] temp = new byte[keyLen + ivLen]; - Array.Copy(_key, 0, temp, 0, keyLen); - Array.Copy(iv, 0, temp, keyLen, ivLen); - realkey = MbedTLS.MD5(temp); + if (_cipher == Rc4Md5) + { + byte[] temp = new byte[keyLen + ivLen]; + Array.Copy(_key, 0, temp, 0, keyLen); + Array.Copy(iv, 0, temp, keyLen, ivLen); + realkey = MbedTLS.MD5(temp); + } + else + { + realkey = _key; + } + sbox = SBox(realkey); } - else + else if (_cipher == Table) { - realkey = _key; + ulong a = BitConverter.ToUInt64(MbedTLS.MD5(Encoding.UTF8.GetBytes(_password)), 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; + } } - sbox = EncryptInitalize(realkey); } protected override void cipherUpdate(bool isEncrypt, int length, byte[] buf, byte[] outbuf) { - var ctx = isEncrypt ? enc_ctx : dec_ctx; + if (_cipher == Table) + { + var table = isEncrypt ? _encryptTable : _decryptTable; + for (int i = 0; i < length; i++) + { + outbuf[i] = table[buf[i]]; + } + } + else if (_cipher == Plain) + { + Array.Copy(buf, outbuf, length); + } + else + { + var ctx = isEncrypt ? enc_ctx : dec_ctx; - byte[] t = new byte[length]; - Array.Copy(buf, t, length); + byte[] t = new byte[length]; + Array.Copy(buf, t, length); - EncryptOutput(ctx, sbox, t, length); - Array.Copy(t, outbuf, length); + RC4(ctx, sbox, t, length); + Array.Copy(t, outbuf, length); + } } private static readonly Dictionary _ciphers = new Dictionary { - { "rc4", new EncryptorInfo("RC4", 16, 16, 1) }, - { "rc4-md5", new EncryptorInfo("RC4", 16, 16, 1) }, - // it's using ivLen=16, not compatible - //{ "chacha20-ietf", new EncryptorInfo("chacha20", 32, 12, CIPHER_CHACHA20_IETF) } + {"plain", new EncryptorInfo("PLAIN", 0, 0, Plain) }, + {"table", new EncryptorInfo("TABLE", 0, 0, Table) }, + { "rc4", new EncryptorInfo("RC4", 16, 16, Rc4) }, + { "rc4-md5", new EncryptorInfo("RC4", 16, 16, Rc4Md5) }, }; public static IEnumerable SupportedCiphers() @@ -67,6 +107,57 @@ namespace Shadowsocks.Encryption.Stream return _ciphers; } + #region Table + private byte[] _encryptTable = new byte[256]; + private byte[] _decryptTable = new byte[256]; + + private static long Compare(byte x, byte y, ulong a, int i) + { + return (long)(a % (ulong)(x + i)) - (long)(a % (ulong)(y + i)); + } + + private byte[] MergeSort(byte[] array, ulong a, int j) + { + if (array.Length == 1) + { + return array; + } + int middle = array.Length / 2; + byte[] left = new byte[middle]; + for (int i = 0; i < middle; i++) + { + left[i] = array[i]; + } + byte[] right = new byte[array.Length - middle]; + for (int i = 0; i < array.Length - middle; i++) + { + right[i] = array[i + middle]; + } + left = MergeSort(left, a, j); + right = MergeSort(right, a, j); + + int leftptr = 0; + int rightptr = 0; + + byte[] sorted = new byte[array.Length]; + for (int k = 0; k < array.Length; k++) + { + if (rightptr == right.Length || ((leftptr < left.Length) && (Compare(left[leftptr], right[rightptr], a, j) <= 0))) + { + sorted[k] = left[leftptr]; + leftptr++; + } + else if (leftptr == left.Length || ((rightptr < right.Length) && (Compare(right[rightptr], left[leftptr], a, j)) <= 0)) + { + sorted[k] = right[rightptr]; + rightptr++; + } + } + return sorted; + } + #endregion + + #region RC4 class Context { public int index1 = 0; @@ -76,7 +167,7 @@ namespace Shadowsocks.Encryption.Stream private Context enc_ctx = new Context(); private Context dec_ctx = new Context(); - private byte[] EncryptInitalize(byte[] key) + private byte[] SBox(byte[] key) { byte[] s = new byte[256]; @@ -95,7 +186,7 @@ namespace Shadowsocks.Encryption.Stream return s; } - private void EncryptOutput(Context ctx, byte[] s, byte[] data, int length) + private void RC4(Context ctx, byte[] s, byte[] data, int length) { for (int n = 0; n < length; n++) { @@ -117,5 +208,6 @@ namespace Shadowsocks.Encryption.Stream s[i] = s[j]; s[j] = c; } + #endregion } } diff --git a/shadowsocks-csharp/View/ConfigForm.cs b/shadowsocks-csharp/View/ConfigForm.cs index 1d94ec79..9a681cfb 100755 --- a/shadowsocks-csharp/View/ConfigForm.cs +++ b/shadowsocks-csharp/View/ConfigForm.cs @@ -31,6 +31,10 @@ namespace Shadowsocks.View "salsa20", "chacha20", "bf-cfb", + + "rc4", + "plain", + "table", }; private static string[] inuseMethod = new string[] {