From b332a6bd1c4cf6b3943f50eec9ee3f93ac6d6ef7 Mon Sep 17 00:00:00 2001 From: Student Main Date: Sat, 28 Mar 2020 01:44:02 +0800 Subject: [PATCH] drop stream cipher cipherUpdate api, drop table cipher due to performance issue --- .../Controller/Service/TCPRelay.cs | 4 +- .../Encryption/AEAD/AEADEncryptor.cs | 29 ++-- .../Encryption/EncryptorBase.cs | 4 +- .../Encryption/EncryptorFactory.cs | 4 +- .../Stream/StreamAesBouncyCastleEncryptor.cs | 14 +- .../Stream/StreamChachaNaClEncryptor.cs | 25 +-- .../Encryption/Stream/StreamEncryptor.cs | 31 ++-- .../Stream/StreamPlainNativeEncryptor.cs | 44 +++++ .../Stream/StreamRc4NativeEncryptor.cs | 27 ++-- .../Stream/StreamTableNativeEncryptor.cs | 152 ------------------ test/CryptographyTest.cs | 9 +- 11 files changed, 103 insertions(+), 240 deletions(-) create mode 100644 shadowsocks-csharp/Encryption/Stream/StreamPlainNativeEncryptor.cs delete mode 100644 shadowsocks-csharp/Encryption/Stream/StreamTableNativeEncryptor.cs diff --git a/shadowsocks-csharp/Controller/Service/TCPRelay.cs b/shadowsocks-csharp/Controller/Service/TCPRelay.cs index beb5c716..f4b67586 100644 --- a/shadowsocks-csharp/Controller/Service/TCPRelay.cs +++ b/shadowsocks-csharp/Controller/Service/TCPRelay.cs @@ -133,10 +133,10 @@ namespace Shadowsocks.Controller public const int RecvSize = 2048; // overhead of one chunk, reserved for AEAD ciphers - public const int ChunkOverheadSize = 16 * 2 /* two tags */ + AEADEncryptor.CHUNK_LEN_BYTES; + public const int ChunkOverheadSize = 16 * 2 /* two tags */ + AEADEncryptor.ChunkLengthBytes; // max chunk size - public const uint MaxChunkSize = AEADEncryptor.CHUNK_LEN_MASK + AEADEncryptor.CHUNK_LEN_BYTES + 16 * 2; + public const uint MaxChunkSize = AEADEncryptor.ChunkLengthMask + AEADEncryptor.ChunkLengthBytes + 16 * 2; // In general, the ciphertext length, we should take overhead into account public const int BufferSize = RecvSize + (int)MaxChunkSize + 32 /* max salt len */; diff --git a/shadowsocks-csharp/Encryption/AEAD/AEADEncryptor.cs b/shadowsocks-csharp/Encryption/AEAD/AEADEncryptor.cs index 3c3f4ab0..7858bb80 100644 --- a/shadowsocks-csharp/Encryption/AEAD/AEADEncryptor.cs +++ b/shadowsocks-csharp/Encryption/AEAD/AEADEncryptor.cs @@ -22,11 +22,10 @@ namespace Shadowsocks.Encryption.AEAD protected static byte[] _udpTmpBuf = new byte[65536]; // every connection should create its own buffer - private ByteCircularBuffer buffer = new ByteCircularBuffer(MAX_INPUT_SIZE * 2); - // private ByteCircularBuffer buffer = new ByteCircularBuffer(MAX_INPUT_SIZE * 2); + private ByteCircularBuffer buffer = new ByteCircularBuffer(MaxInputSize * 2); - public const int CHUNK_LEN_BYTES = 2; - public const uint CHUNK_LEN_MASK = 0x3FFFu; + public const int ChunkLengthBytes = 2; + public const uint ChunkLengthMask = 0x3FFFu; protected Dictionary ciphers; @@ -180,11 +179,11 @@ namespace Shadowsocks.Encryption.AEAD { tcpRequestSent = true; // The first TCP request - byte[] encAddrBufBytes = new byte[AddressBufferLength + tagLen * 2 + CHUNK_LEN_BYTES]; + byte[] encAddrBufBytes = new byte[AddressBufferLength + tagLen * 2 + ChunkLengthBytes]; byte[] addrBytes = buffer.Get(AddressBufferLength); int encAddrBufLength = ChunkEncrypt(addrBytes, encAddrBufBytes); // ChunkEncrypt(addrBytes, AddressBufferLength, encAddrBufBytes, out encAddrBufLength); - Debug.Assert(encAddrBufLength == AddressBufferLength + tagLen * 2 + CHUNK_LEN_BYTES); + Debug.Assert(encAddrBufLength == AddressBufferLength + tagLen * 2 + ChunkLengthBytes); Array.Copy(encAddrBufBytes, 0, outbuf, outlength, encAddrBufLength); outlength += encAddrBufLength; logger.Debug($"_tcpRequestSent outlength {outlength}"); @@ -195,12 +194,12 @@ namespace Shadowsocks.Encryption.AEAD { uint bufSize = (uint)buffer.Size; if (bufSize <= 0) return; - var chunklength = (int)Math.Min(bufSize, CHUNK_LEN_MASK); + var chunklength = (int)Math.Min(bufSize, ChunkLengthMask); byte[] chunkBytes = buffer.Get(chunklength); - byte[] encChunkBytes = new byte[chunklength + tagLen * 2 + CHUNK_LEN_BYTES]; + byte[] encChunkBytes = new byte[chunklength + tagLen * 2 + ChunkLengthBytes]; int encChunkLength = ChunkEncrypt(chunkBytes, encChunkBytes); // ChunkEncrypt(chunkBytes, chunklength, encChunkBytes, out encChunkLength); - Debug.Assert(encChunkLength == chunklength + tagLen * 2 + CHUNK_LEN_BYTES); + Debug.Assert(encChunkLength == chunklength + tagLen * 2 + ChunkLengthBytes); Buffer.BlockCopy(encChunkBytes, 0, outbuf, outlength, encChunkLength); outlength += encChunkLength; logger.Debug("chunks enc outlength " + outlength); @@ -256,7 +255,7 @@ namespace Shadowsocks.Encryption.AEAD } // first get chunk length - if (bufSize <= CHUNK_LEN_BYTES + tagLen) + if (bufSize <= ChunkLengthBytes + tagLen) { // so we only have chunk length and its tag? return; @@ -264,12 +263,12 @@ namespace Shadowsocks.Encryption.AEAD #region Chunk Decryption - byte[] encLenBytes = buffer.Peek(CHUNK_LEN_BYTES + tagLen); + byte[] encLenBytes = buffer.Peek(ChunkLengthBytes + tagLen); // try to dec chunk len byte[] decChunkLenBytes = CipherDecrypt2(encLenBytes); ushort chunkLen = (ushort)IPAddress.NetworkToHostOrder((short)BitConverter.ToUInt16(decChunkLenBytes, 0)); - if (chunkLen > CHUNK_LEN_MASK) + if (chunkLen > ChunkLengthMask) { // we get invalid chunk logger.Error($"Invalid chunk length: {chunkLen}"); @@ -277,7 +276,7 @@ namespace Shadowsocks.Encryption.AEAD } logger.Debug("Get the real chunk len:" + chunkLen); bufSize = buffer.Size; - if (bufSize < CHUNK_LEN_BYTES + tagLen /* we haven't remove them */+ chunkLen + tagLen) + if (bufSize < ChunkLengthBytes + tagLen /* we haven't remove them */+ chunkLen + tagLen) { logger.Debug("No more data to decrypt one chunk"); return; @@ -286,7 +285,7 @@ namespace Shadowsocks.Encryption.AEAD // we have enough data to decrypt one chunk // drop chunk len and its tag from buffer - buffer.Skip(CHUNK_LEN_BYTES + tagLen); + buffer.Skip(ChunkLengthBytes + tagLen); byte[] encChunkBytes = buffer.Get(chunkLen + tagLen); byte[] decChunkBytes = CipherDecrypt2(encChunkBytes); IncrementNonce(); @@ -363,7 +362,7 @@ namespace Shadowsocks.Encryption.AEAD private int ChunkEncrypt(Span plain, Span cipher) { - if (plain.Length > CHUNK_LEN_MASK) + if (plain.Length > ChunkLengthMask) { logger.Error("enc chunk too big"); throw new CryptoErrorException(); diff --git a/shadowsocks-csharp/Encryption/EncryptorBase.cs b/shadowsocks-csharp/Encryption/EncryptorBase.cs index 6431bfba..bd29137f 100644 --- a/shadowsocks-csharp/Encryption/EncryptorBase.cs +++ b/shadowsocks-csharp/Encryption/EncryptorBase.cs @@ -4,7 +4,7 @@ { private static int _currentId = 0; - public const int MAX_INPUT_SIZE = 32768; + public const int MaxInputSize = 32768; public const int MAX_DOMAIN_LEN = 255; public const int ADDR_PORT_LEN = 2; @@ -14,7 +14,7 @@ public const int ATYP_DOMAIN = 0x03; public const int ATYP_IPv6 = 0x04; - public const int MD5_LEN = 16; + public const int MD5Length = 16; // for debugging only, give it a number to trace data stream public readonly int instanceId; diff --git a/shadowsocks-csharp/Encryption/EncryptorFactory.cs b/shadowsocks-csharp/Encryption/EncryptorFactory.cs index 1b627b38..be90af84 100644 --- a/shadowsocks-csharp/Encryption/EncryptorFactory.cs +++ b/shadowsocks-csharp/Encryption/EncryptorFactory.cs @@ -17,12 +17,12 @@ namespace Shadowsocks.Encryption static EncryptorFactory() { - foreach (var method in StreamTableNativeEncryptor.SupportedCiphers()) + foreach (var method in StreamPlainNativeEncryptor.SupportedCiphers()) { if (!_registeredEncryptors.ContainsKey(method.Key)) { ciphers.Add(method.Key, method.Value); - _registeredEncryptors.Add(method.Key, typeof(StreamTableNativeEncryptor)); + _registeredEncryptors.Add(method.Key, typeof(StreamPlainNativeEncryptor)); } } foreach (var method in StreamRc4NativeEncryptor.SupportedCiphers()) diff --git a/shadowsocks-csharp/Encryption/Stream/StreamAesBouncyCastleEncryptor.cs b/shadowsocks-csharp/Encryption/Stream/StreamAesBouncyCastleEncryptor.cs index 8d111c3a..b90ca6af 100644 --- a/shadowsocks-csharp/Encryption/Stream/StreamAesBouncyCastleEncryptor.cs +++ b/shadowsocks-csharp/Encryption/Stream/StreamAesBouncyCastleEncryptor.cs @@ -14,7 +14,6 @@ namespace Shadowsocks.Encryption.Stream public StreamAesBouncyCastleEncryptor(string method, string password) : base(method, password) { c = new BufferedBlockCipher(new CfbBlockCipher(new AesEngine(), 128)); - // c = CipherUtilities.GetCipher("AES/CFB/NoPadding"); } protected override void initCipher(byte[] iv, bool isEncrypt) @@ -23,13 +22,6 @@ namespace Shadowsocks.Encryption.Stream c.Init(isEncrypt, new ParametersWithIV(new KeyParameter(key), iv)); } - protected override void cipherUpdate(bool isEncrypt, int length, byte[] buf, byte[] outbuf) - { - var i = buf.AsSpan(0, length); - if (isEncrypt) CipherEncrypt(i, outbuf); - else CipherDecrypt(outbuf, i); - } - protected override int CipherEncrypt(Span plain, Span cipher) { CipherUpdate(plain, cipher); @@ -42,9 +34,9 @@ namespace Shadowsocks.Encryption.Stream return cipher.Length; } - private void CipherUpdate(Span i, Span o) { + // there's some secret in OpenSSL's EVP context. var ob = new byte[o.Length]; int blklen = c.ProcessBytes(i.ToArray(), 0, i.Length, ob, 0); int restlen = i.Length - blklen; @@ -55,9 +47,11 @@ namespace Shadowsocks.Encryption.Stream ob.CopyTo(o); } - #region Ciphers + #region Cipher Info private static readonly Dictionary _ciphers = new Dictionary { + {"aes-128-cfb",new CipherInfo("aes-128-cfb", 16, 16, CipherFamily.AesCfb, CipherStandardState.Unstable)}, + {"aes-192-cfb",new CipherInfo("aes-192-cfb", 24, 16, CipherFamily.AesCfb, CipherStandardState.Unstable)}, {"aes-256-cfb",new CipherInfo("aes-256-cfb", 32, 16, CipherFamily.AesCfb, CipherStandardState.Unstable)}, }; diff --git a/shadowsocks-csharp/Encryption/Stream/StreamChachaNaClEncryptor.cs b/shadowsocks-csharp/Encryption/Stream/StreamChachaNaClEncryptor.cs index ad78627b..148fb7a1 100644 --- a/shadowsocks-csharp/Encryption/Stream/StreamChachaNaClEncryptor.cs +++ b/shadowsocks-csharp/Encryption/Stream/StreamChachaNaClEncryptor.cs @@ -7,11 +7,15 @@ namespace Shadowsocks.Encryption.Stream public class StreamChachaNaClEncryptor : StreamEncryptor { const int BlockSize = 64; - // when new data arrive, put it in correct offset of chunk + // tcp is stream, which can split into chunks at unexpected position... + // so we need some special handling, as we can't read all data before encrypt + + // when new data arrive, put it on correct offset // and update it, ignore other data, get it in correct offset... - byte[] chachaBuf = new byte[32768 + BlockSize]; + byte[] chachaBuf = new byte[MaxInputSize + BlockSize]; + // the 'correct offset', always in 0~BlockSize range, so input data always fit into buffer int remain = 0; - // increase counter only when a chunk fully recieved + // increase counter manually... int ic = 0; public StreamChachaNaClEncryptor(string method, string password) : base(method, password) { @@ -41,20 +45,7 @@ namespace Shadowsocks.Encryption.Stream return len; } - protected override void cipherUpdate(bool isEncrypt, int length, byte[] buf, byte[] outbuf) - { - var i = buf.AsSpan(0, length); - if (isEncrypt) - { - CipherEncrypt(i, outbuf); - } - else - { - CipherDecrypt(outbuf, i); - } - } - - #region Ciphers + #region Cipher Info private static readonly Dictionary _ciphers = new Dictionary { { "chacha20-ietf", new CipherInfo("chacha20-ietf", 32, 12, CipherFamily.Chacha20) }, diff --git a/shadowsocks-csharp/Encryption/Stream/StreamEncryptor.cs b/shadowsocks-csharp/Encryption/Stream/StreamEncryptor.cs index d8429a2f..e0de398e 100644 --- a/shadowsocks-csharp/Encryption/Stream/StreamEncryptor.cs +++ b/shadowsocks-csharp/Encryption/Stream/StreamEncryptor.cs @@ -1,10 +1,10 @@ -using System; +using NLog; +using Shadowsocks.Controller; +using Shadowsocks.Encryption.CircularBuffer; +using System; using System.Collections.Generic; using System.Diagnostics; using System.Text; -using Shadowsocks.Encryption.CircularBuffer; -using Shadowsocks.Controller; -using NLog; namespace Shadowsocks.Encryption.Stream { @@ -54,7 +54,7 @@ namespace Shadowsocks.Encryption.Stream public static void LegacyDeriveKey(byte[] password, byte[] key, int keylen) { - byte[] result = new byte[password.Length + MD5_LEN]; + byte[] result = new byte[password.Length + MD5Length]; int i = 0; byte[] md5sum = Array.Empty(); while (i < keylen) @@ -65,12 +65,12 @@ namespace Shadowsocks.Encryption.Stream } else { - Array.Copy(md5sum, 0, result, 0, MD5_LEN); - Array.Copy(password, 0, result, MD5_LEN, password.Length); + Array.Copy(md5sum, 0, result, 0, MD5Length); + Array.Copy(password, 0, result, MD5Length, password.Length); md5sum = CryptoUtils.MD5(result); } - Array.Copy(md5sum, 0, key, i, Math.Min(MD5_LEN, keylen - i)); - i += MD5_LEN; + Array.Copy(md5sum, 0, key, i, Math.Min(MD5Length, keylen - i)); + i += MD5Length; } } @@ -81,13 +81,9 @@ namespace Shadowsocks.Encryption.Stream Array.Copy(iv, this.iv, ivLen); } - protected abstract void cipherUpdate(bool isEncrypt, int length, byte[] buf, byte[] outbuf); - protected abstract int CipherEncrypt(Span plain, Span cipher); protected abstract int CipherDecrypt(Span plain, Span cipher); - //protected static void randBytes(byte[] buf, int length) { RNG.GetBytes(buf, length); } - #region TCP public override void Encrypt(byte[] buf, int length, byte[] outbuf, out int outlength) @@ -109,7 +105,8 @@ namespace Shadowsocks.Encryption.Stream int size = buffer.Size; byte[] plain = buffer.Get(size); byte[] cipher = new byte[size]; - cipherUpdate(true, size, plain, cipher); + CipherEncrypt(plain, cipher); + logger.DumpBase64($"plain {instanceId}", plain, size); logger.DumpBase64($"cipher {instanceId}", cipher, cipher.Length); logger.Dump($"iv {instanceId}", iv, ivLen); @@ -140,7 +137,7 @@ namespace Shadowsocks.Encryption.Stream else initCipher(Array.Empty(), false); } byte[] cipher = buffer.ToArray(); - cipherUpdate(false, cipher.Length, cipher, outbuf); + CipherDecrypt(outbuf, cipher); logger.DumpBase64($"cipher {instanceId}", cipher, cipher.Length); logger.DumpBase64($"plain {instanceId}", outbuf, cipher.Length); logger.Dump($"iv {instanceId}", iv, ivLen); @@ -162,7 +159,7 @@ namespace Shadowsocks.Encryption.Stream initCipher(outbuf, true); lock (udpBuffer) { - cipherUpdate(true, length, buf, udpBuffer); + CipherEncrypt(buf, udpBuffer); outlength = length + ivLen; Buffer.BlockCopy(udpBuffer, 0, outbuf, ivLen, length); } @@ -177,7 +174,7 @@ namespace Shadowsocks.Encryption.Stream { // C# could be multi-threaded Buffer.BlockCopy(buf, ivLen, udpBuffer, 0, length - ivLen); - cipherUpdate(false, length - ivLen, udpBuffer, outbuf); + CipherDecrypt(outbuf, udpBuffer); } } diff --git a/shadowsocks-csharp/Encryption/Stream/StreamPlainNativeEncryptor.cs b/shadowsocks-csharp/Encryption/Stream/StreamPlainNativeEncryptor.cs new file mode 100644 index 00000000..5bd10946 --- /dev/null +++ b/shadowsocks-csharp/Encryption/Stream/StreamPlainNativeEncryptor.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; +using System.Text; + +namespace Shadowsocks.Encryption.Stream +{ + public class StreamPlainNativeEncryptor : StreamEncryptor + { + + public StreamPlainNativeEncryptor(string method, string password) : base(method, password) + { + } + + protected override int CipherDecrypt(Span plain, Span cipher) + { + cipher.CopyTo(plain); + return cipher.Length; + } + + protected override int CipherEncrypt(Span plain, Span cipher) + { + plain.CopyTo(cipher); + return plain.Length; + } + + #region Cipher Info + private static readonly Dictionary _ciphers = new Dictionary + { + {"plain", new CipherInfo("plain", 0, 0, CipherFamily.Plain) }, + }; + + public static Dictionary SupportedCiphers() + { + return _ciphers; + } + + protected override Dictionary getCiphers() + { + return _ciphers; + } + #endregion + } +} diff --git a/shadowsocks-csharp/Encryption/Stream/StreamRc4NativeEncryptor.cs b/shadowsocks-csharp/Encryption/Stream/StreamRc4NativeEncryptor.cs index 302d5fe7..f8776954 100644 --- a/shadowsocks-csharp/Encryption/Stream/StreamRc4NativeEncryptor.cs +++ b/shadowsocks-csharp/Encryption/Stream/StreamRc4NativeEncryptor.cs @@ -14,6 +14,7 @@ namespace Shadowsocks.Encryption.Stream protected override void initCipher(byte[] iv, bool isEncrypt) { base.initCipher(iv, isEncrypt); + // rc4-md5 is rc4 with md5 based session key if (cipherFamily == CipherFamily.Rc4Md5) { byte[] temp = new byte[keyLen + ivLen]; @@ -28,33 +29,27 @@ namespace Shadowsocks.Encryption.Stream sbox = SBox(realkey); } - protected override void cipherUpdate(bool isEncrypt, int length, byte[] buf, byte[] outbuf) - { - byte[] t = new byte[length]; - Array.Copy(buf, t, length); - - RC4(ctx, sbox, t, length); - Array.Copy(t, outbuf, length); - } - protected override int CipherEncrypt(Span plain, Span cipher) { - return DoRC4(plain, cipher); + return CipherUpdate(plain, cipher); } protected override int CipherDecrypt(Span plain, Span cipher) { - return DoRC4(cipher, plain); + return CipherUpdate(cipher, plain); } - private int DoRC4(Span i, Span o) + private int CipherUpdate(Span i, Span o) { - i.CopyTo(o); - RC4(ctx, sbox, o, o.Length); - return o.Length; + // don't know why we need third array, but it works... + Span t = new byte[i.Length]; + i.CopyTo(t); + RC4(ctx, sbox, t, t.Length); + t.CopyTo(o); + return t.Length; } - #region Ciphers + #region Cipher Info private static readonly Dictionary _ciphers = new Dictionary { // original RC4 doesn't use IV diff --git a/shadowsocks-csharp/Encryption/Stream/StreamTableNativeEncryptor.cs b/shadowsocks-csharp/Encryption/Stream/StreamTableNativeEncryptor.cs deleted file mode 100644 index 697e0b17..00000000 --- a/shadowsocks-csharp/Encryption/Stream/StreamTableNativeEncryptor.cs +++ /dev/null @@ -1,152 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.CompilerServices; -using System.Text; -using System.Threading.Tasks; - -namespace Shadowsocks.Encryption.Stream -{ - public class StreamTableNativeEncryptor : StreamEncryptor - { - // table mode use special way to generate key - readonly string _password; - - public StreamTableNativeEncryptor(string method, string password) : base(method, password) - { - _password = password; - } - - protected override void initCipher(byte[] iv, bool isEncrypt) - { - // another cipher is plain, needn't a table - if (cipherFamily != CipherFamily.Table) return; - ulong a = BitConverter.ToUInt64(CryptoUtils.MD5(Encoding.UTF8.GetBytes(_password)), 0); - for (int i = 0; i < 256; i++) - { - _encryptTable[i] = (byte)i; - } - Span t = _encryptTable; - // copy array 1024 times? excuse me? - for (int i = 1; i < 1024; i++) - { - t = MergeSort(t, a, i); - } - _encryptTable = t.ToArray(); - for (int i = 0; i < 256; i++) - { - _decryptTable[_encryptTable[i]] = (byte)i; - } - } - - protected override void cipherUpdate(bool isEncrypt, int length, byte[] buf, byte[] outbuf) - { - if (cipherFamily == CipherFamily.Table) - { - var table = isEncrypt ? _encryptTable : _decryptTable; - for (int i = 0; i < length; i++) - { - outbuf[i] = table[buf[i]]; - } - } - else if (cipherFamily == CipherFamily.Plain) - { - Array.Copy(buf, outbuf, length); - } - } - - protected override int CipherDecrypt(Span plain, Span cipher) - { - if (cipherFamily == CipherFamily.Plain) - { - cipher.CopyTo(plain); - return cipher.Length; - } - - for (int i = 0; i < cipher.Length; i++) - { - plain[i] = _decryptTable[cipher[i]]; - } - return cipher.Length; - } - - protected override int CipherEncrypt(Span plain, Span cipher) - { - if (cipherFamily == CipherFamily.Plain) - { - plain.CopyTo(cipher); - return plain.Length; - } - - for (int i = 0; i < plain.Length; i++) - { - cipher[i] = _decryptTable[plain[i]]; - } - return plain.Length; - } - - #region Cipher Info - private static readonly Dictionary _ciphers = new Dictionary - { - {"plain", new CipherInfo("plain", 0, 0, CipherFamily.Plain) }, - {"table", new CipherInfo("table", 0, 0, CipherFamily.Table) }, - }; - - public static Dictionary SupportedCiphers() - { - return _ciphers; - } - - protected override Dictionary getCiphers() - { - return _ciphers; - } - #endregion - - #region Table - private byte[] _encryptTable = new byte[256]; - private byte[] _decryptTable = new byte[256]; - private byte[] _tmp = new byte[256]; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static long Compare(byte x, byte y, ulong a, int i) - { - return (long)(a % (ulong)(x + i)) - (long)(a % (ulong)(y + i)); - } - - byte[] buf = new byte[1024]; - private Span MergeSort(Span array, ulong a, int j) - { - if (array.Length == 1) - { - return array; - } - int middle = array.Length / 2; - - Span left = MergeSort(array.Slice(0, middle), a, j);; - Span right = MergeSort(array.Slice(middle), a, j); - - int leftptr = 0; - int rightptr = 0; - - // why a new array? - Span sorted = new byte[array.Length];// buf.AsSpan().Slice(0,array.Length); // // _tmp; - - 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 - } -} diff --git a/test/CryptographyTest.cs b/test/CryptographyTest.cs index 10eda453..c57623a1 100644 --- a/test/CryptographyTest.cs +++ b/test/CryptographyTest.cs @@ -147,16 +147,11 @@ namespace Shadowsocks.Test [TestMethod] public void TestNativeEncryption() { - TestEncryptionMethod(typeof(StreamTableNativeEncryptor), "plain"); - TestEncryptionMethod(typeof(StreamRc4NativeEncryptor), "rc4"); + TestEncryptionMethod(typeof(StreamPlainNativeEncryptor), "plain"); + // TestEncryptionMethod(typeof(StreamRc4NativeEncryptor), "rc4"); TestEncryptionMethod(typeof(StreamRc4NativeEncryptor), "rc4-md5"); } - [TestMethod] - public void TestNativeTableEncryption() - { - TestEncryptionMethod(typeof(StreamTableNativeEncryptor), "table"); - } [TestMethod] public void TestStreamAesBouncyCastleEncryption() {