diff --git a/shadowsocks-csharp/Encryption/SodiumEncryptor.cs b/shadowsocks-csharp/Encryption/SodiumEncryptor.cs index 661a90af..7dd42d2e 100755 --- a/shadowsocks-csharp/Encryption/SodiumEncryptor.cs +++ b/shadowsocks-csharp/Encryption/SodiumEncryptor.cs @@ -12,16 +12,18 @@ namespace Shadowsocks.Encryption const int SODIUM_BLOCK_SIZE = 64; - static byte[] sodiumBuf = new byte[MAX_INPUT_SIZE + SODIUM_BLOCK_SIZE]; - protected int _encryptBytesRemaining; protected int _decryptBytesRemaining; protected ulong _encryptIC; protected ulong _decryptIC; + protected byte[] _encryptBuf; + protected byte[] _decryptBuf; public SodiumEncryptor(string method, string password, bool onetimeauth, bool isudp) : base(method, password, onetimeauth, isudp) { + _encryptBuf = new byte[MAX_INPUT_SIZE + SODIUM_BLOCK_SIZE]; + _decryptBuf = new byte[MAX_INPUT_SIZE + SODIUM_BLOCK_SIZE]; } private static Dictionary _ciphers = new Dictionary { @@ -45,54 +47,52 @@ namespace Shadowsocks.Encryption // TODO write a unidirection cipher so we don't have to if if if int bytesRemaining; ulong ic; + byte[] sodiumBuf; byte[] iv; - // I'm tired. just add a big lock - // let's optimize for RAM instead of CPU - lock(sodiumBuf) + if (isCipher) + { + bytesRemaining = _encryptBytesRemaining; + ic = _encryptIC; + sodiumBuf = _encryptBuf; + iv = _encryptIV; + } + else { - if (isCipher) - { - bytesRemaining = _encryptBytesRemaining; - ic = _encryptIC; - iv = _encryptIV; - } - else - { - bytesRemaining = _decryptBytesRemaining; - ic = _decryptIC; - iv = _decryptIV; - } - int padding = bytesRemaining; - Buffer.BlockCopy(buf, 0, sodiumBuf, padding, length); + bytesRemaining = _decryptBytesRemaining; + ic = _decryptIC; + sodiumBuf = _decryptBuf; + iv = _decryptIV; + } + int padding = bytesRemaining; + Buffer.BlockCopy(buf, 0, sodiumBuf, padding, length); - switch (_cipher) - { - case CIPHER_SALSA20: - Sodium.crypto_stream_salsa20_xor_ic(sodiumBuf, sodiumBuf, (ulong)(padding + length), iv, ic, _key); - break; - case CIPHER_CHACHA20: - Sodium.crypto_stream_chacha20_xor_ic(sodiumBuf, sodiumBuf, (ulong)(padding + length), iv, ic, _key); - break; - case CIPHER_CHACHA20_IETF: - Sodium.crypto_stream_chacha20_ietf_xor_ic(sodiumBuf, sodiumBuf, (ulong)(padding + length), iv, (uint)ic, _key); - break; - } - Buffer.BlockCopy(sodiumBuf, padding, outbuf, 0, length); - padding += length; - ic += (ulong)padding / SODIUM_BLOCK_SIZE; - bytesRemaining = padding % SODIUM_BLOCK_SIZE; + switch (_cipher) + { + case CIPHER_SALSA20: + Sodium.crypto_stream_salsa20_xor_ic(sodiumBuf, sodiumBuf, (ulong)(padding + length), iv, ic, _key); + break; + case CIPHER_CHACHA20: + Sodium.crypto_stream_chacha20_xor_ic(sodiumBuf, sodiumBuf, (ulong)(padding + length), iv, ic, _key); + break; + case CIPHER_CHACHA20_IETF: + Sodium.crypto_stream_chacha20_ietf_xor_ic(sodiumBuf, sodiumBuf, (ulong)(padding + length), iv, (uint)ic, _key); + break; + } + Buffer.BlockCopy(sodiumBuf, padding, outbuf, 0, length); + padding += length; + ic += (ulong)padding / SODIUM_BLOCK_SIZE; + bytesRemaining = padding % SODIUM_BLOCK_SIZE; - if (isCipher) - { - _encryptBytesRemaining = bytesRemaining; - _encryptIC = ic; - } - else - { - _decryptBytesRemaining = bytesRemaining; - _decryptIC = ic; - } + if (isCipher) + { + _encryptBytesRemaining = bytesRemaining; + _encryptIC = ic; + } + else + { + _decryptBytesRemaining = bytesRemaining; + _decryptIC = ic; } }