diff --git a/shadowsocks-csharp/Controller/Service/PACServer.cs b/shadowsocks-csharp/Controller/Service/PACServer.cs index ee5ed89e..b17fece0 100644 --- a/shadowsocks-csharp/Controller/Service/PACServer.cs +++ b/shadowsocks-csharp/Controller/Service/PACServer.cs @@ -51,7 +51,8 @@ namespace Shadowsocks.Controller private static string GetHash(string content) { - return HttpServerUtilityUrlToken.Encode(MbedTLS.MD5(Encoding.ASCII.GetBytes(content))); + + return HttpServerUtilityUrlToken.Encode(CryptoUtils.MD5(Encoding.ASCII.GetBytes(content))); } public override bool Handle(byte[] firstPacket, int length, Socket socket, object state) diff --git a/shadowsocks-csharp/Data/libsscrypto.dll.gz b/shadowsocks-csharp/Data/libsscrypto.dll.gz deleted file mode 100755 index ff39152f..00000000 Binary files a/shadowsocks-csharp/Data/libsscrypto.dll.gz and /dev/null differ diff --git a/shadowsocks-csharp/Encryption/AEAD/AEADBouncyCastleEncryptor.cs b/shadowsocks-csharp/Encryption/AEAD/AEADBouncyCastleEncryptor.cs new file mode 100644 index 00000000..be028808 --- /dev/null +++ b/shadowsocks-csharp/Encryption/AEAD/AEADBouncyCastleEncryptor.cs @@ -0,0 +1,77 @@ +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Modes; +using Org.BouncyCastle.Crypto.Parameters; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Shadowsocks.Encryption.AEAD +{ + public class AEADBouncyCastleEncryptor : AEADEncryptor, IDisposable + { + static int CIPHER_AES = 1; // dummy + + public AEADBouncyCastleEncryptor(string method, string password) + : base(method, password) + { + } + + + private static readonly Dictionary _ciphers = new Dictionary + { + {"aes-128-gcm", new EncryptorInfo("AES-128-GCM", 16, 16, 12, 16, CIPHER_AES)}, + {"aes-192-gcm", new EncryptorInfo("AES-192-GCM", 24, 24, 12, 16, CIPHER_AES)}, + {"aes-256-gcm", new EncryptorInfo("AES-256-GCM", 32, 32, 12, 16, CIPHER_AES)}, + }; + + protected override Dictionary getCiphers() + { + return _ciphers; + } + + public override void InitCipher(byte[] salt, bool isEncrypt, bool isUdp) + { + base.InitCipher(salt, isEncrypt, isUdp); + + DeriveSessionKey(isEncrypt ? _encryptSalt : _decryptSalt, + _Masterkey, _sessionKey); + } + + public override void cipherDecrypt(byte[] ciphertext, uint clen, byte[] plaintext, ref uint plen) + { + var cipher = new GcmBlockCipher(new AesEngine()); + AeadParameters parameters = new AeadParameters(new KeyParameter(_sessionKey), tagLen * 8, _decNonce); + + cipher.Init(false, parameters); + var plaintextBC = new byte[cipher.GetOutputSize((int)clen)]; + var len = cipher.ProcessBytes(ciphertext, 0, (int)clen, plaintextBC, 0); + cipher.DoFinal(plaintextBC, len); + plen = (uint)(plaintextBC.Length); + Array.Copy(plaintextBC, 0, plaintext, 0, plen); + } + + public override void cipherEncrypt(byte[] plaintext, uint plen, byte[] ciphertext, ref uint clen) + { + var cipher = new GcmBlockCipher(new AesEngine()); + AeadParameters parameters = new AeadParameters(new KeyParameter(_sessionKey), tagLen * 8, _encNonce); + + cipher.Init(true, parameters); + var ciphertextBC = new byte[cipher.GetOutputSize((int)plen)]; + var len = cipher.ProcessBytes(plaintext, 0, (int)plen, ciphertextBC, 0); + cipher.DoFinal(ciphertextBC, len); + clen = (uint)(ciphertextBC.Length); + Array.Copy(ciphertextBC, 0, ciphertext, 0, clen); + } + + public static List SupportedCiphers() + { + return new List(_ciphers.Keys); + } + + public override void Dispose() + { + } + } +} diff --git a/shadowsocks-csharp/Encryption/AEAD/AEADEncryptor.cs b/shadowsocks-csharp/Encryption/AEAD/AEADEncryptor.cs index 2acd54bd..d33c3c65 100644 --- a/shadowsocks-csharp/Encryption/AEAD/AEADEncryptor.cs +++ b/shadowsocks-csharp/Encryption/AEAD/AEADEncryptor.cs @@ -103,15 +103,13 @@ namespace Shadowsocks.Encryption.AEAD public void DeriveSessionKey(byte[] salt, byte[] masterKey, byte[] sessionKey) { - int ret = MbedTLS.hkdf(salt, saltLen, masterKey, keyLen, InfoBytes, InfoBytes.Length, sessionKey, - keyLen); - if (ret != 0) throw new System.Exception("failed to generate session key"); + CryptoUtils.HKDF(keyLen, masterKey, salt, InfoBytes).CopyTo(sessionKey,0); } protected void IncrementNonce(bool isEncrypt) { lock (_nonceIncrementLock) { - Sodium.sodium_increment(isEncrypt ? _encNonce : _decNonce, nonceLen); + CryptoUtils.SodiumIncrement(isEncrypt ? _encNonce : _decNonce); } } diff --git a/shadowsocks-csharp/Encryption/AEAD/AEADMbedTLSEncryptor.cs b/shadowsocks-csharp/Encryption/AEAD/AEADMbedTLSEncryptor.cs deleted file mode 100644 index 2f73f9e4..00000000 --- a/shadowsocks-csharp/Encryption/AEAD/AEADMbedTLSEncryptor.cs +++ /dev/null @@ -1,178 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Runtime.InteropServices; -using Shadowsocks.Encryption.Exception; - -namespace Shadowsocks.Encryption.AEAD -{ - public class AEADMbedTLSEncryptor - : AEADEncryptor, IDisposable - { - const int CIPHER_AES = 1; - - private IntPtr _encryptCtx = IntPtr.Zero; - private IntPtr _decryptCtx = IntPtr.Zero; - - public AEADMbedTLSEncryptor(string method, string password) - : base(method, password) - { - } - - private static readonly Dictionary _ciphers = new Dictionary - { - {"aes-128-gcm", new EncryptorInfo("AES-128-GCM", 16, 16, 12, 16, CIPHER_AES)}, - {"aes-192-gcm", new EncryptorInfo("AES-192-GCM", 24, 24, 12, 16, CIPHER_AES)}, - {"aes-256-gcm", new EncryptorInfo("AES-256-GCM", 32, 32, 12, 16, CIPHER_AES)}, - }; - - public static List SupportedCiphers() - { - return new List(_ciphers.Keys); - } - - protected override Dictionary getCiphers() - { - return _ciphers; - } - - public override void InitCipher(byte[] salt, bool isEncrypt, bool isUdp) - { - base.InitCipher(salt, isEncrypt, isUdp); - IntPtr ctx = Marshal.AllocHGlobal(MbedTLS.cipher_get_size_ex()); - if (isEncrypt) - { - _encryptCtx = ctx; - } - else - { - _decryptCtx = ctx; - } - - MbedTLS.cipher_init(ctx); - if (MbedTLS.cipher_setup(ctx, MbedTLS.cipher_info_from_string(_innerLibName)) != 0) - throw new System.Exception("Cannot initialize mbed TLS cipher context"); - - DeriveSessionKey(isEncrypt ? _encryptSalt : _decryptSalt, - _Masterkey, _sessionKey); - CipherSetKey(isEncrypt, _sessionKey); - } - - private void CipherSetKey(bool isEncrypt, byte[] key) - { - IntPtr ctx = isEncrypt ? _encryptCtx : _decryptCtx; - int ret = MbedTLS.cipher_setkey(ctx, key, keyLen * 8, - isEncrypt ? MbedTLS.MBEDTLS_ENCRYPT : MbedTLS.MBEDTLS_DECRYPT); - if (ret != 0) throw new System.Exception("failed to set key"); - ret = MbedTLS.cipher_reset(ctx); - if (ret != 0) throw new System.Exception("failed to finish preparation"); - } - - public override void cipherEncrypt(byte[] plaintext, uint plen, byte[] ciphertext, ref uint clen) - { - // buf: all plaintext - // outbuf: ciphertext + tag - int ret; - byte[] tagbuf = new byte[tagLen]; - uint olen = 0; - switch (_cipher) - { - case CIPHER_AES: - ret = MbedTLS.cipher_auth_encrypt(_encryptCtx, - /* nonce */ - _encNonce, (uint) nonceLen, - /* AD */ - IntPtr.Zero, 0, - /* plain */ - plaintext, plen, - /* cipher */ - ciphertext, ref olen, - tagbuf, (uint) tagLen); - if (ret != 0) throw new CryptoErrorException(String.Format("ret is {0}", ret)); - Debug.Assert(olen == plen); - // attach tag to ciphertext - Array.Copy(tagbuf, 0, ciphertext, (int) plen, tagLen); - clen = olen + (uint) tagLen; - break; - default: - throw new System.Exception("not implemented"); - } - } - - public override void cipherDecrypt(byte[] ciphertext, uint clen, byte[] plaintext, ref uint plen) - { - // buf: ciphertext + tag - // outbuf: plaintext - int ret; - uint olen = 0; - // split tag - byte[] tagbuf = new byte[tagLen]; - Array.Copy(ciphertext, (int) (clen - tagLen), tagbuf, 0, tagLen); - switch (_cipher) - { - case CIPHER_AES: - ret = MbedTLS.cipher_auth_decrypt(_decryptCtx, - _decNonce, (uint) nonceLen, - IntPtr.Zero, 0, - ciphertext, (uint) (clen - tagLen), - plaintext, ref olen, - tagbuf, (uint) tagLen); - if (ret != 0) throw new CryptoErrorException(String.Format("ret is {0}", ret)); - Debug.Assert(olen == clen - tagLen); - plen = olen; - break; - default: - throw new System.Exception("not implemented"); - } - } - - #region IDisposable - - private bool _disposed; - - // instance based lock - private readonly object _lock = new object(); - - public override void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - ~AEADMbedTLSEncryptor() - { - Dispose(false); - } - - protected virtual void Dispose(bool disposing) - { - lock (_lock) - { - if (_disposed) return; - _disposed = true; - } - - if (disposing) - { - // free managed objects - } - - // free unmanaged objects - if (_encryptCtx != IntPtr.Zero) - { - MbedTLS.cipher_free(_encryptCtx); - Marshal.FreeHGlobal(_encryptCtx); - _encryptCtx = IntPtr.Zero; - } - - if (_decryptCtx != IntPtr.Zero) - { - MbedTLS.cipher_free(_decryptCtx); - Marshal.FreeHGlobal(_decryptCtx); - _decryptCtx = IntPtr.Zero; - } - } - - #endregion - } -} \ No newline at end of file diff --git a/shadowsocks-csharp/Encryption/AEAD/AEADNativeEncryptor.cs b/shadowsocks-csharp/Encryption/AEAD/AEADNativeEncryptor.cs new file mode 100644 index 00000000..6a14aae1 --- /dev/null +++ b/shadowsocks-csharp/Encryption/AEAD/AEADNativeEncryptor.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; + +namespace Shadowsocks.Encryption.AEAD +{ + public class AEADNativeEncryptor : AEADEncryptor + { + public AEADNativeEncryptor(string method, string password) + : base(method, password) + { + } + + public override void cipherDecrypt(byte[] ciphertext, uint clen, byte[] plaintext, ref uint plen) + { + Array.Copy(ciphertext, plaintext, 0); + plen = clen; + + } + + public override void cipherEncrypt(byte[] plaintext, uint plen, byte[] ciphertext, ref uint clen) + { + Array.Copy(plaintext, ciphertext, 0); + clen = plen; + } + + public override void Dispose() + { + return; + } + + private static Dictionary _ciphers = new Dictionary() + { + {"plain-fake-aead",new EncryptorInfo("PLAIN_AEAD",0,0,0,0,0) } + }; + + + protected override Dictionary getCiphers() + { + return _ciphers; + } + + public static IEnumerable SupportedCiphers() + { + return _ciphers.Keys; + } + + } +} diff --git a/shadowsocks-csharp/Encryption/AEAD/AEADOpenSSLEncryptor.cs b/shadowsocks-csharp/Encryption/AEAD/AEADOpenSSLEncryptor.cs deleted file mode 100644 index e122e4b8..00000000 --- a/shadowsocks-csharp/Encryption/AEAD/AEADOpenSSLEncryptor.cs +++ /dev/null @@ -1,192 +0,0 @@ -using System; -using System.Collections.Generic; -using Shadowsocks.Encryption.Exception; - -namespace Shadowsocks.Encryption.AEAD -{ - public class AEADOpenSSLEncryptor - : AEADEncryptor, IDisposable - { - const int CIPHER_AES = 1; - const int CIPHER_CHACHA20IETFPOLY1305 = 2; - - private byte[] _opensslEncSubkey; - private byte[] _opensslDecSubkey; - - private IntPtr _encryptCtx = IntPtr.Zero; - private IntPtr _decryptCtx = IntPtr.Zero; - - private IntPtr _cipherInfoPtr = IntPtr.Zero; - - public AEADOpenSSLEncryptor(string method, string password) - : base(method, password) - { - _opensslEncSubkey = new byte[keyLen]; - _opensslDecSubkey = new byte[keyLen]; - } - - private static readonly Dictionary _ciphers = new Dictionary - { - {"aes-128-gcm", new EncryptorInfo("aes-128-gcm", 16, 16, 12, 16, CIPHER_AES)}, - {"aes-192-gcm", new EncryptorInfo("aes-192-gcm", 24, 24, 12, 16, CIPHER_AES)}, - {"aes-256-gcm", new EncryptorInfo("aes-256-gcm", 32, 32, 12, 16, CIPHER_AES)}, - {"chacha20-ietf-poly1305", new EncryptorInfo("chacha20-poly1305", 32, 32, 12, 16, CIPHER_CHACHA20IETFPOLY1305)} - }; - - public static List SupportedCiphers() - { - return new List(_ciphers.Keys); - } - - protected override Dictionary getCiphers() - { - return _ciphers; - } - - public override void InitCipher(byte[] salt, bool isEncrypt, bool isUdp) - { - base.InitCipher(salt, isEncrypt, isUdp); - _cipherInfoPtr = OpenSSL.GetCipherInfo(_innerLibName); - if (_cipherInfoPtr == IntPtr.Zero) throw new System.Exception("openssl: cipher not found"); - IntPtr ctx = OpenSSL.EVP_CIPHER_CTX_new(); - if (ctx == IntPtr.Zero) throw new System.Exception("openssl: fail to create ctx"); - - if (isEncrypt) - { - _encryptCtx = ctx; - } - else - { - _decryptCtx = ctx; - } - - DeriveSessionKey(isEncrypt ? _encryptSalt : _decryptSalt, _Masterkey, - isEncrypt ? _opensslEncSubkey : _opensslDecSubkey); - - var ret = OpenSSL.EVP_CipherInit_ex(ctx, _cipherInfoPtr, IntPtr.Zero, null, null, - isEncrypt ? OpenSSL.OPENSSL_ENCRYPT : OpenSSL.OPENSSL_DECRYPT); - if (ret != 1) throw new System.Exception("openssl: fail to init ctx"); - - ret = OpenSSL.EVP_CIPHER_CTX_set_key_length(ctx, keyLen); - if (ret != 1) throw new System.Exception("openssl: fail to set key length"); - - ret = OpenSSL.EVP_CIPHER_CTX_ctrl(ctx, OpenSSL.EVP_CTRL_AEAD_SET_IVLEN, - nonceLen, IntPtr.Zero); - if (ret != 1) throw new System.Exception("openssl: fail to set AEAD nonce length"); - - ret = OpenSSL.EVP_CipherInit_ex(ctx, IntPtr.Zero, IntPtr.Zero, - isEncrypt ? _opensslEncSubkey : _opensslDecSubkey, - null, - isEncrypt ? OpenSSL.OPENSSL_ENCRYPT : OpenSSL.OPENSSL_DECRYPT); - if (ret != 1) throw new System.Exception("openssl: cannot set key"); - OpenSSL.EVP_CIPHER_CTX_set_padding(ctx, 0); - } - - public override void cipherEncrypt(byte[] plaintext, uint plen, byte[] ciphertext, ref uint clen) - { - OpenSSL.SetCtxNonce(_encryptCtx, _encNonce, true); - // buf: all plaintext - // outbuf: ciphertext + tag - int ret; - int tmpLen = 0; - clen = 0; - var tagBuf = new byte[tagLen]; - - ret = OpenSSL.EVP_CipherUpdate(_encryptCtx, ciphertext, out tmpLen, - plaintext, (int) plen); - if (ret != 1) throw new CryptoErrorException("openssl: fail to encrypt AEAD"); - clen += (uint) tmpLen; - // For AEAD cipher, it should not output anything - ret = OpenSSL.EVP_CipherFinal_ex(_encryptCtx, ciphertext, ref tmpLen); - if (ret != 1) throw new CryptoErrorException("openssl: fail to finalize AEAD"); - if (tmpLen > 0) - { - throw new System.Exception("openssl: fail to finish AEAD"); - } - - OpenSSL.AEADGetTag(_encryptCtx, tagBuf, tagLen); - Array.Copy(tagBuf, 0, ciphertext, clen, tagLen); - clen += (uint) tagLen; - } - - public override void cipherDecrypt(byte[] ciphertext, uint clen, byte[] plaintext, ref uint plen) - { - OpenSSL.SetCtxNonce(_decryptCtx, _decNonce, false); - // buf: ciphertext + tag - // outbuf: plaintext - int ret; - int tmpLen = 0; - plen = 0; - - // split tag - byte[] tagbuf = new byte[tagLen]; - Array.Copy(ciphertext, (int) (clen - tagLen), tagbuf, 0, tagLen); - OpenSSL.AEADSetTag(_decryptCtx, tagbuf, tagLen); - - ret = OpenSSL.EVP_CipherUpdate(_decryptCtx, - plaintext, out tmpLen, ciphertext, (int) (clen - tagLen)); - if (ret != 1) throw new CryptoErrorException("openssl: fail to decrypt AEAD"); - plen += (uint) tmpLen; - - // For AEAD cipher, it should not output anything - ret = OpenSSL.EVP_CipherFinal_ex(_decryptCtx, plaintext, ref tmpLen); - if (ret <= 0) - { - // If this is not successful authenticated - throw new CryptoErrorException(String.Format("ret is {0}", ret)); - } - - if (tmpLen > 0) - { - throw new System.Exception("openssl: fail to finish AEAD"); - } - } - - #region IDisposable - - private bool _disposed; - - // instance based lock - private readonly object _lock = new object(); - - public override void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - ~AEADOpenSSLEncryptor() - { - Dispose(false); - } - - protected virtual void Dispose(bool disposing) - { - lock (_lock) - { - if (_disposed) return; - _disposed = true; - } - - if (disposing) - { - // free managed objects - } - - // free unmanaged objects - if (_encryptCtx != IntPtr.Zero) - { - OpenSSL.EVP_CIPHER_CTX_free(_encryptCtx); - _encryptCtx = IntPtr.Zero; - } - - if (_decryptCtx != IntPtr.Zero) - { - OpenSSL.EVP_CIPHER_CTX_free(_decryptCtx); - _decryptCtx = IntPtr.Zero; - } - } - - #endregion - } -} \ No newline at end of file diff --git a/shadowsocks-csharp/Encryption/AEAD/AEADSodiumEncryptor.cs b/shadowsocks-csharp/Encryption/AEAD/AEADSodiumEncryptor.cs deleted file mode 100644 index 06aef5d7..00000000 --- a/shadowsocks-csharp/Encryption/AEAD/AEADSodiumEncryptor.cs +++ /dev/null @@ -1,141 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using NLog; -using Shadowsocks.Controller; -using Shadowsocks.Encryption.Exception; - -namespace Shadowsocks.Encryption.AEAD -{ - public class AEADSodiumEncryptor - : AEADEncryptor, IDisposable - { - private static Logger logger = LogManager.GetCurrentClassLogger(); - - private const int CIPHER_CHACHA20IETFPOLY1305 = 1; - private const int CIPHER_XCHACHA20IETFPOLY1305 = 2; - private const int CIPHER_AES256GCM = 3; - - private byte[] _sodiumEncSubkey; - private byte[] _sodiumDecSubkey; - - public AEADSodiumEncryptor(string method, string password) - : base(method, password) - { - _sodiumEncSubkey = new byte[keyLen]; - _sodiumDecSubkey = new byte[keyLen]; - } - - private static readonly Dictionary _ciphers = new Dictionary - { - {"chacha20-ietf-poly1305", new EncryptorInfo(32, 32, 12, 16, CIPHER_CHACHA20IETFPOLY1305)}, - {"xchacha20-ietf-poly1305", new EncryptorInfo(32, 32, 24, 16, CIPHER_XCHACHA20IETFPOLY1305)}, - {"aes-256-gcm", new EncryptorInfo(32, 32, 12, 16, CIPHER_AES256GCM)}, - }; - - public static List SupportedCiphers() - { - return new List(_ciphers.Keys); - } - - protected override Dictionary getCiphers() - { - return _ciphers; - } - - public override void InitCipher(byte[] salt, bool isEncrypt, bool isUdp) - { - base.InitCipher(salt, isEncrypt, isUdp); - DeriveSessionKey(isEncrypt ? _encryptSalt : _decryptSalt, _Masterkey, - isEncrypt ? _sodiumEncSubkey : _sodiumDecSubkey); - } - - - public override void cipherEncrypt(byte[] plaintext, uint plen, byte[] ciphertext, ref uint clen) - { - Debug.Assert(_sodiumEncSubkey != null); - // buf: all plaintext - // outbuf: ciphertext + tag - int ret; - ulong encClen = 0; - logger.Dump("_encNonce before enc", _encNonce, nonceLen); - logger.Dump("_sodiumEncSubkey", _sodiumEncSubkey, keyLen); - logger.Dump("before cipherEncrypt: plain", plaintext, (int) plen); - switch (_cipher) - { - case CIPHER_CHACHA20IETFPOLY1305: - ret = Sodium.crypto_aead_chacha20poly1305_ietf_encrypt(ciphertext, ref encClen, - plaintext, (ulong) plen, - null, 0, - null, _encNonce, - _sodiumEncSubkey); - break; - case CIPHER_XCHACHA20IETFPOLY1305: - ret = Sodium.crypto_aead_xchacha20poly1305_ietf_encrypt(ciphertext, ref encClen, - plaintext, (ulong)plen, - null, 0, - null, _encNonce, - _sodiumEncSubkey); - break; - case CIPHER_AES256GCM: - ret = Sodium.crypto_aead_aes256gcm_encrypt(ciphertext, ref encClen, - plaintext, (ulong)plen, - null, 0, - null, _encNonce, - _sodiumEncSubkey); - break; - default: - throw new System.Exception("not implemented"); - } - if (ret != 0) throw new CryptoErrorException(String.Format("ret is {0}", ret)); - logger.Dump("after cipherEncrypt: cipher", ciphertext, (int) encClen); - clen = (uint) encClen; - } - - public override void cipherDecrypt(byte[] ciphertext, uint clen, byte[] plaintext, ref uint plen) - { - Debug.Assert(_sodiumDecSubkey != null); - // buf: ciphertext + tag - // outbuf: plaintext - int ret; - ulong decPlen = 0; - logger.Dump("_decNonce before dec", _decNonce, nonceLen); - logger.Dump("_sodiumDecSubkey", _sodiumDecSubkey, keyLen); - logger.Dump("before cipherDecrypt: cipher", ciphertext, (int) clen); - switch (_cipher) - { - case CIPHER_CHACHA20IETFPOLY1305: - ret = Sodium.crypto_aead_chacha20poly1305_ietf_decrypt(plaintext, ref decPlen, - null, - ciphertext, (ulong) clen, - null, 0, - _decNonce, _sodiumDecSubkey); - break; - case CIPHER_XCHACHA20IETFPOLY1305: - ret = Sodium.crypto_aead_xchacha20poly1305_ietf_decrypt(plaintext, ref decPlen, - null, - ciphertext, (ulong)clen, - null, 0, - _decNonce, _sodiumDecSubkey); - break; - case CIPHER_AES256GCM: - ret = Sodium.crypto_aead_aes256gcm_decrypt(plaintext, ref decPlen, - null, - ciphertext, (ulong)clen, - null, 0, - _decNonce, _sodiumDecSubkey); - break; - default: - throw new System.Exception("not implemented"); - } - - if (ret != 0) throw new CryptoErrorException(String.Format("ret is {0}", ret)); - logger.Dump("after cipherDecrypt: plain", plaintext, (int) decPlen); - plen = (uint) decPlen; - } - - public override void Dispose() - { - } - } -} \ No newline at end of file diff --git a/shadowsocks-csharp/Encryption/CryptoUtils.cs b/shadowsocks-csharp/Encryption/CryptoUtils.cs new file mode 100644 index 00000000..cd4fe394 --- /dev/null +++ b/shadowsocks-csharp/Encryption/CryptoUtils.cs @@ -0,0 +1,42 @@ +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Crypto.Parameters; + +namespace Shadowsocks.Encryption +{ + public static class CryptoUtils + { + public static byte[] MD5(byte[] b) + { + MD5Digest md5 = new MD5Digest(); + md5.BlockUpdate(b, 0, b.Length); + byte[] r = new byte[16]; + md5.DoFinal(r, 0); + return r; + } + + public static byte[] HKDF(int keylen, byte[] master, byte[] salt, byte[] info) + { + byte[] ret = new byte[keylen]; + IDigest degist = new Sha1Digest(); + HkdfParameters parameters = new HkdfParameters(master, salt, info); + HkdfBytesGenerator hkdf = new HkdfBytesGenerator(degist); + hkdf.Init(parameters); + hkdf.GenerateBytes(ret, 0, keylen); + return ret; + } + + public static void SodiumIncrement(byte[] salt) + { + bool o = true; // overflow flag + for (int i = 0; i < salt.Length; i++) + { + if (!o) continue; + + salt[i]++; + o = salt[i] == 0; + } + } + } +} diff --git a/shadowsocks-csharp/Encryption/EncryptorFactory.cs b/shadowsocks-csharp/Encryption/EncryptorFactory.cs index fcae221a..05000796 100644 --- a/shadowsocks-csharp/Encryption/EncryptorFactory.cs +++ b/shadowsocks-csharp/Encryption/EncryptorFactory.cs @@ -11,59 +11,28 @@ namespace Shadowsocks.Encryption { private static Dictionary _registeredEncryptors = new Dictionary(); - private static readonly Type[] ConstructorTypes = {typeof(string), typeof(string)}; + private static readonly Type[] ConstructorTypes = { typeof(string), typeof(string) }; static EncryptorFactory() { - var AEADMbedTLSEncryptorSupportedCiphers = AEADMbedTLSEncryptor.SupportedCiphers(); - var AEADSodiumEncryptorSupportedCiphers = AEADSodiumEncryptor.SupportedCiphers(); - if (Sodium.AES256GCMAvailable) - { - // prefer to aes-256-gcm in libsodium - AEADMbedTLSEncryptorSupportedCiphers.Remove("aes-256-gcm"); - } - else - { - AEADSodiumEncryptorSupportedCiphers.Remove("aes-256-gcm"); - } - - // XXX: sequence matters, OpenSSL > Sodium > MbedTLS - foreach (string method in StreamOpenSSLEncryptor.SupportedCiphers()) + foreach (string method in StreamNativeEncryptor.SupportedCiphers()) { if (!_registeredEncryptors.ContainsKey(method)) - _registeredEncryptors.Add(method, typeof(StreamOpenSSLEncryptor)); + _registeredEncryptors.Add(method, typeof(StreamNativeEncryptor)); } - foreach (string method in StreamSodiumEncryptor.SupportedCiphers()) + foreach (string method in AEADNativeEncryptor.SupportedCiphers()) { if (!_registeredEncryptors.ContainsKey(method)) - _registeredEncryptors.Add(method, typeof(StreamSodiumEncryptor)); + _registeredEncryptors.Add(method, typeof(AEADNativeEncryptor)); } - foreach (string method in StreamMbedTLSEncryptor.SupportedCiphers()) + foreach (string method in AEADBouncyCastleEncryptor.SupportedCiphers()) { if (!_registeredEncryptors.ContainsKey(method)) - _registeredEncryptors.Add(method, typeof(StreamMbedTLSEncryptor)); + _registeredEncryptors.Add(method, typeof(AEADBouncyCastleEncryptor)); } - - foreach (string method in AEADOpenSSLEncryptor.SupportedCiphers()) - { - if (!_registeredEncryptors.ContainsKey(method)) - _registeredEncryptors.Add(method, typeof(AEADOpenSSLEncryptor)); - } - - foreach (string method in AEADSodiumEncryptorSupportedCiphers) - { - if (!_registeredEncryptors.ContainsKey(method)) - _registeredEncryptors.Add(method, typeof(AEADSodiumEncryptor)); - } - - foreach (string method in AEADMbedTLSEncryptorSupportedCiphers) - { - if (!_registeredEncryptors.ContainsKey(method)) - _registeredEncryptors.Add(method, typeof(AEADMbedTLSEncryptor)); - } } public static IEncryptor GetEncryptor(string method, string password) @@ -78,7 +47,7 @@ namespace Shadowsocks.Encryption ConstructorInfo c = t.GetConstructor(ConstructorTypes); if (c == null) throw new System.Exception("Invalid ctor"); - IEncryptor result = (IEncryptor) c.Invoke(new object[] {method, password}); + IEncryptor result = (IEncryptor)c.Invoke(new object[] { method, password }); return result; } diff --git a/shadowsocks-csharp/Encryption/MbedTLS.cs b/shadowsocks-csharp/Encryption/MbedTLS.cs deleted file mode 100644 index be681670..00000000 --- a/shadowsocks-csharp/Encryption/MbedTLS.cs +++ /dev/null @@ -1,109 +0,0 @@ -using System; -using System.IO; -using System.Runtime.InteropServices; -using NLog; -using Shadowsocks.Controller; -using Shadowsocks.Properties; -using Shadowsocks.Util; - -namespace Shadowsocks.Encryption -{ - public static class MbedTLS - { - private static Logger logger = LogManager.GetCurrentClassLogger(); - - private const string DLLNAME = "libsscrypto.dll"; - - public const int MBEDTLS_ENCRYPT = 1; - public const int MBEDTLS_DECRYPT = 0; - - static MbedTLS() - { - string dllPath = Utils.GetTempPath(DLLNAME); - try - { - FileManager.UncompressFile(dllPath, Resources.libsscrypto_dll); - } - catch (IOException) - { - } - catch (System.Exception e) - { - logger.LogUsefulException(e); - } - LoadLibrary(dllPath); - } - - public static byte[] MD5(byte[] input) - { - byte[] output = new byte[16]; - if (md5_ret(input, (uint) input.Length, output) != 0) - throw new System.Exception("mbedtls: MD5 failure"); - return output; - } - - [DllImport("Kernel32.dll")] - private static extern IntPtr LoadLibrary(string path); - - [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] - public static extern int md5_ret(byte[] input, uint ilen, byte[] output); - - /// - /// Get cipher ctx size for unmanaged memory allocation - /// - /// - [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] - public static extern int cipher_get_size_ex(); - - #region Cipher layer wrappers - - [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] - public static extern IntPtr cipher_info_from_string(string cipher_name); - - [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] - public static extern void cipher_init(IntPtr ctx); - - [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] - public static extern int cipher_setup(IntPtr ctx, IntPtr cipher_info); - - // XXX: Check operation before using it - [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] - public static extern int cipher_setkey(IntPtr ctx, byte[] key, int key_bitlen, int operation); - - [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] - public static extern int cipher_set_iv(IntPtr ctx, byte[] iv, int iv_len); - - [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] - public static extern int cipher_reset(IntPtr ctx); - - [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] - public static extern int cipher_update(IntPtr ctx, byte[] input, int ilen, byte[] output, ref int olen); - - [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] - public static extern void cipher_free(IntPtr ctx); - - [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] - public static extern int cipher_auth_encrypt(IntPtr ctx, - byte[] iv, uint iv_len, - IntPtr ad, uint ad_len, - byte[] input, uint ilen, - byte[] output, ref uint olen, - byte[] tag, uint tag_len); - - [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] - public static extern int cipher_auth_decrypt(IntPtr ctx, - byte[] iv, uint iv_len, - IntPtr ad, uint ad_len, - byte[] input, uint ilen, - byte[] output, ref uint olen, - byte[] tag, uint tag_len); - - [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] - public static extern int hkdf(byte[] salt, - int salt_len, byte[] ikm, int ikm_len, - byte[] info, int info_len, byte[] okm, - int okm_len); - - #endregion - } -} \ No newline at end of file diff --git a/shadowsocks-csharp/Encryption/OpenSSL.cs b/shadowsocks-csharp/Encryption/OpenSSL.cs deleted file mode 100644 index 00056a04..00000000 --- a/shadowsocks-csharp/Encryption/OpenSSL.cs +++ /dev/null @@ -1,164 +0,0 @@ -using System; -using System.IO; -using System.Runtime.InteropServices; -using System.Security; -using System.Text; -using NLog; -using Shadowsocks.Controller; -using Shadowsocks.Encryption.Exception; -using Shadowsocks.Properties; -using Shadowsocks.Util; - -namespace Shadowsocks.Encryption -{ - // XXX: only for OpenSSL 1.1.0 and higher - public static class OpenSSL - { - private static Logger logger = LogManager.GetCurrentClassLogger(); - - private const string DLLNAME = "libsscrypto.dll"; - - public const int OPENSSL_ENCRYPT = 1; - public const int OPENSSL_DECRYPT = 0; - - public const int EVP_CTRL_AEAD_SET_IVLEN = 0x9; - public const int EVP_CTRL_AEAD_GET_TAG = 0x10; - public const int EVP_CTRL_AEAD_SET_TAG = 0x11; - - static OpenSSL() - { - string dllPath = Utils.GetTempPath(DLLNAME); - try - { - FileManager.UncompressFile(dllPath, Resources.libsscrypto_dll); - } - catch (IOException) - { - } - catch (System.Exception e) - { - logger.LogUsefulException(e); - } - LoadLibrary(dllPath); - } - - public static IntPtr GetCipherInfo(string cipherName) - { - var name = Encoding.ASCII.GetBytes(cipherName); - Array.Resize(ref name, name.Length + 1); - return EVP_get_cipherbyname(name); - } - - /// - /// Need init cipher context after EVP_CipherFinal_ex to reuse context - /// - /// - /// - /// - public static void SetCtxNonce(IntPtr ctx, byte[] nonce, bool isEncrypt) - { - var ret = EVP_CipherInit_ex(ctx, IntPtr.Zero, - IntPtr.Zero, null, - nonce, - isEncrypt ? OPENSSL_ENCRYPT : OPENSSL_DECRYPT); - if (ret != 1) throw new System.Exception("openssl: fail to set AEAD nonce"); - } - - public static void AEADGetTag(IntPtr ctx, byte[] tagbuf, int taglen) - { - IntPtr tagBufIntPtr = IntPtr.Zero; - try - { - tagBufIntPtr = Marshal.AllocHGlobal(taglen); - var ret = EVP_CIPHER_CTX_ctrl(ctx, - EVP_CTRL_AEAD_GET_TAG, taglen, tagBufIntPtr); - if (ret != 1) throw new CryptoErrorException("openssl: fail to get AEAD tag"); - // take tag from unmanaged memory - Marshal.Copy(tagBufIntPtr, tagbuf, 0, taglen); - } - finally - { - if (tagBufIntPtr != IntPtr.Zero) - { - Marshal.FreeHGlobal(tagBufIntPtr); - } - } - } - - public static void AEADSetTag(IntPtr ctx, byte[] tagbuf, int taglen) - { - IntPtr tagBufIntPtr = IntPtr.Zero; - try - { - // allocate unmanaged memory for tag - tagBufIntPtr = Marshal.AllocHGlobal(taglen); - - // copy tag to unmanaged memory - Marshal.Copy(tagbuf, 0, tagBufIntPtr, taglen); - - var ret = EVP_CIPHER_CTX_ctrl(ctx, - EVP_CTRL_AEAD_SET_TAG, taglen, tagBufIntPtr); - - if (ret != 1) throw new CryptoErrorException("openssl: fail to set AEAD tag"); - - } - finally - { - if (tagBufIntPtr != IntPtr.Zero) - { - Marshal.FreeHGlobal(tagBufIntPtr); - } - } - } - - [DllImport("Kernel32.dll")] - private static extern IntPtr LoadLibrary(string path); - - [SuppressUnmanagedCodeSecurity] - [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] - public static extern IntPtr EVP_CIPHER_CTX_new(); - - [SuppressUnmanagedCodeSecurity] - [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] - public static extern void EVP_CIPHER_CTX_free(IntPtr ctx); - - [SuppressUnmanagedCodeSecurity] - [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] - public static extern int EVP_CIPHER_CTX_reset(IntPtr ctx); - - [SuppressUnmanagedCodeSecurity] - [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] - public static extern int EVP_CipherInit_ex(IntPtr ctx, IntPtr type, - IntPtr impl, byte[] key, byte[] iv, int enc); - - [SuppressUnmanagedCodeSecurity] - [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] - public static extern int EVP_CipherUpdate(IntPtr ctx, byte[] outb, - out int outl, byte[] inb, int inl); - - [SuppressUnmanagedCodeSecurity] - [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] - public static extern int EVP_CipherFinal_ex(IntPtr ctx, byte[] outm, ref int outl); - - [SuppressUnmanagedCodeSecurity] - [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] - public static extern int EVP_CIPHER_CTX_set_padding(IntPtr x, int padding); - - [SuppressUnmanagedCodeSecurity] - [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] - public static extern int EVP_CIPHER_CTX_set_key_length(IntPtr x, int keylen); - - [SuppressUnmanagedCodeSecurity] - [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] - public static extern int EVP_CIPHER_CTX_ctrl(IntPtr ctx, int type, int arg, IntPtr ptr); - - /// - /// simulate NUL-terminated string - /// - /// - /// - [SuppressUnmanagedCodeSecurity] - [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] - public static extern IntPtr EVP_get_cipherbyname(byte[] name); - } -} \ No newline at end of file diff --git a/shadowsocks-csharp/Encryption/Sodium.cs b/shadowsocks-csharp/Encryption/Sodium.cs deleted file mode 100755 index 6b9441dd..00000000 --- a/shadowsocks-csharp/Encryption/Sodium.cs +++ /dev/null @@ -1,113 +0,0 @@ -using System; -using System.IO; -using System.Runtime.InteropServices; -using NLog; -using Shadowsocks.Controller; -using Shadowsocks.Properties; -using Shadowsocks.Util; - -namespace Shadowsocks.Encryption -{ - public static class Sodium - { - private static Logger logger = LogManager.GetCurrentClassLogger(); - - private const string DLLNAME = "libsscrypto.dll"; - - private static bool _initialized = false; - private static readonly object _initLock = new object(); - - public static bool AES256GCMAvailable { get; private set; } = false; - - static Sodium() - { - string dllPath = Utils.GetTempPath(DLLNAME); - try - { - FileManager.UncompressFile(dllPath, Resources.libsscrypto_dll); - } - catch (IOException) - { - } - catch (System.Exception e) - { - logger.LogUsefulException(e); - } - LoadLibrary(dllPath); - - lock (_initLock) - { - if (!_initialized) - { - if (sodium_init() == -1) - { - throw new System.Exception("Failed to initialize sodium"); - } - else /* 1 means already initialized; 0 means success */ - { - _initialized = true; - } - - AES256GCMAvailable = crypto_aead_aes256gcm_is_available() == 1; - logger.Debug($"sodium: AES256GCMAvailable is {AES256GCMAvailable}"); - } - } - } - - [DllImport("Kernel32.dll")] - private static extern IntPtr LoadLibrary(string path); - - [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] - private static extern int sodium_init(); - - [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] - private static extern int crypto_aead_aes256gcm_is_available(); - - #region AEAD - - [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] - public static extern int sodium_increment(byte[] n, int nlen); - - [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] - public static extern int crypto_aead_chacha20poly1305_ietf_encrypt(byte[] c, ref ulong clen_p, byte[] m, - ulong mlen, byte[] ad, ulong adlen, byte[] nsec, byte[] npub, byte[] k); - - [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] - public static extern int crypto_aead_chacha20poly1305_ietf_decrypt(byte[] m, ref ulong mlen_p, - byte[] nsec, byte[] c, ulong clen, byte[] ad, ulong adlen, byte[] npub, byte[] k); - - [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] - public static extern int crypto_aead_xchacha20poly1305_ietf_encrypt(byte[] c, ref ulong clen_p, byte[] m, ulong mlen, - byte[] ad, ulong adlen, byte[] nsec, byte[] npub, byte[] k); - - [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] - public static extern int crypto_aead_xchacha20poly1305_ietf_decrypt(byte[] m, ref ulong mlen_p, byte[] nsec, byte[] c, - ulong clen, byte[] ad, ulong adlen, byte[] npub, byte[] k); - - [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] - public static extern int crypto_aead_aes256gcm_encrypt(byte[] c, ref ulong clen_p, byte[] m, ulong mlen, - byte[] ad, ulong adlen, byte[] nsec, byte[] npub, byte[] k); - - [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] - public static extern int crypto_aead_aes256gcm_decrypt(byte[] m, ref ulong mlen_p, byte[] nsec, byte[] c, - ulong clen, byte[] ad, ulong adlen, byte[] npub, byte[] k); - - #endregion - - #region Stream - - [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] - public static extern int crypto_stream_salsa20_xor_ic(byte[] c, byte[] m, ulong mlen, byte[] n, ulong ic, - byte[] k); - - [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] - public static extern int crypto_stream_chacha20_xor_ic(byte[] c, byte[] m, ulong mlen, byte[] n, ulong ic, - byte[] k); - - [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] - public static extern int crypto_stream_chacha20_ietf_xor_ic(byte[] c, byte[] m, ulong mlen, byte[] n, uint ic, - byte[] k); - - #endregion - } -} \ No newline at end of file diff --git a/shadowsocks-csharp/Encryption/Stream/StreamEncryptor.cs b/shadowsocks-csharp/Encryption/Stream/StreamEncryptor.cs index a93a7cf8..6dd736be 100644 --- a/shadowsocks-csharp/Encryption/Stream/StreamEncryptor.cs +++ b/shadowsocks-csharp/Encryption/Stream/StreamEncryptor.cs @@ -75,11 +75,11 @@ namespace Shadowsocks.Encryption.Stream byte[] md5sum = null; while (i < keylen) { if (i == 0) { - md5sum = MbedTLS.MD5(password); + md5sum = CryptoUtils.MD5(password); } else { Array.Copy(md5sum, 0, result, 0, MD5_LEN); Array.Copy(password, 0, result, MD5_LEN, password.Length); - md5sum = MbedTLS.MD5(result); + md5sum = CryptoUtils.MD5(result); } Array.Copy(md5sum, 0, key, i, Math.Min(MD5_LEN, keylen - i)); i += MD5_LEN; diff --git a/shadowsocks-csharp/Encryption/Stream/StreamMbedTLSEncryptor.cs b/shadowsocks-csharp/Encryption/Stream/StreamMbedTLSEncryptor.cs deleted file mode 100644 index 210fcef7..00000000 --- a/shadowsocks-csharp/Encryption/Stream/StreamMbedTLSEncryptor.cs +++ /dev/null @@ -1,155 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Runtime.InteropServices; -using Shadowsocks.Encryption.Exception; - -namespace Shadowsocks.Encryption.Stream -{ - public class StreamMbedTLSEncryptor - : StreamEncryptor, IDisposable - { - const int CIPHER_RC4 = 1; - const int CIPHER_AES = 2; - const int CIPHER_BLOWFISH = 3; - const int CIPHER_CAMELLIA = 4; - - private IntPtr _encryptCtx = IntPtr.Zero; - private IntPtr _decryptCtx = IntPtr.Zero; - - public StreamMbedTLSEncryptor(string method, string password) - : base(method, password) - { - } - - private static Dictionary _ciphers = new Dictionary { - { "aes-128-cfb", new EncryptorInfo("AES-128-CFB128", 16, 16, CIPHER_AES) }, - { "aes-192-cfb", new EncryptorInfo("AES-192-CFB128", 24, 16, CIPHER_AES) }, - { "aes-256-cfb", new EncryptorInfo("AES-256-CFB128", 32, 16, CIPHER_AES) }, - { "aes-128-ctr", new EncryptorInfo("AES-128-CTR", 16, 16, CIPHER_AES) }, - { "aes-192-ctr", new EncryptorInfo("AES-192-CTR", 24, 16, CIPHER_AES) }, - { "aes-256-ctr", new EncryptorInfo("AES-256-CTR", 32, 16, CIPHER_AES) }, - { "bf-cfb", new EncryptorInfo("BLOWFISH-CFB64", 16, 8, CIPHER_BLOWFISH) }, - { "camellia-128-cfb", new EncryptorInfo("CAMELLIA-128-CFB128", 16, 16, CIPHER_CAMELLIA) }, - { "camellia-192-cfb", new EncryptorInfo("CAMELLIA-192-CFB128", 24, 16, CIPHER_CAMELLIA) }, - { "camellia-256-cfb", new EncryptorInfo("CAMELLIA-256-CFB128", 32, 16, CIPHER_CAMELLIA) }, - { "rc4-md5", new EncryptorInfo("ARC4-128", 16, 16, CIPHER_RC4) } - }; - - public static List SupportedCiphers() - { - return new List(_ciphers.Keys); - } - - protected override Dictionary getCiphers() - { - return _ciphers; - } - - protected override void initCipher(byte[] iv, bool isEncrypt) - { - base.initCipher(iv, isEncrypt); - IntPtr ctx = Marshal.AllocHGlobal(MbedTLS.cipher_get_size_ex()); - if (isEncrypt) - { - _encryptCtx = ctx; - } - else - { - _decryptCtx = ctx; - } - byte[] realkey; - if (_method == "rc4-md5") - { - 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; - } - MbedTLS.cipher_init(ctx); - if (MbedTLS.cipher_setup( ctx, MbedTLS.cipher_info_from_string( _innerLibName ) ) != 0 ) - throw new System.Exception("Cannot initialize mbed TLS cipher context"); - /* - * MbedTLS takes key length by bit - * cipher_setkey() will set the correct key schedule - * and operation - * - * MBEDTLS_AES_{EN,DE}CRYPT - * == MBEDTLS_BLOWFISH_{EN,DE}CRYPT - * == MBEDTLS_CAMELLIA_{EN,DE}CRYPT - * == MBEDTLS_{EN,DE}CRYPT - * - */ - if (MbedTLS.cipher_setkey(ctx, realkey, keyLen * 8, - isEncrypt ? MbedTLS.MBEDTLS_ENCRYPT : MbedTLS.MBEDTLS_DECRYPT) != 0 ) - throw new System.Exception("Cannot set mbed TLS cipher key"); - if (MbedTLS.cipher_set_iv(ctx, iv, ivLen) != 0) - throw new System.Exception("Cannot set mbed TLS cipher IV"); - if (MbedTLS.cipher_reset(ctx) != 0) - throw new System.Exception("Cannot finalize mbed TLS cipher context"); - } - - protected override void cipherUpdate(bool isEncrypt, int length, byte[] buf, byte[] outbuf) - { - // C# could be multi-threaded - if (_disposed) - { - throw new ObjectDisposedException(this.ToString()); - } - if (MbedTLS.cipher_update(isEncrypt ? _encryptCtx : _decryptCtx, - buf, length, outbuf, ref length) != 0 ) - throw new CryptoErrorException(); - } - - #region IDisposable - - private bool _disposed; - - // instance based lock - private readonly object _lock = new object(); - - public override void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - ~StreamMbedTLSEncryptor() - { - Dispose(false); - } - - protected virtual void Dispose(bool disposing) - { - lock (_lock) - { - if (_disposed) return; - _disposed = true; - } - - if (disposing) - { - // free managed objects - } - - // free unmanaged objects - if (_encryptCtx != IntPtr.Zero) - { - MbedTLS.cipher_free(_encryptCtx); - Marshal.FreeHGlobal(_encryptCtx); - _encryptCtx = IntPtr.Zero; - } - if (_decryptCtx != IntPtr.Zero) - { - MbedTLS.cipher_free(_decryptCtx); - Marshal.FreeHGlobal(_decryptCtx); - _decryptCtx = IntPtr.Zero; - } - } - - #endregion - } -} diff --git a/shadowsocks-csharp/Encryption/Stream/StreamNativeEncryptor.cs b/shadowsocks-csharp/Encryption/Stream/StreamNativeEncryptor.cs new file mode 100644 index 00000000..528e99ab --- /dev/null +++ b/shadowsocks-csharp/Encryption/Stream/StreamNativeEncryptor.cs @@ -0,0 +1,213 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Shadowsocks.Encryption.Stream +{ + public class StreamNativeEncryptor : StreamEncryptor + { + 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) + { + _password = password; + } + + public override void Dispose() + { + return; + } + + protected override void initCipher(byte[] iv, bool isEncrypt) + { + base.initCipher(iv, isEncrypt); + if (_cipher >= Rc4) + { + if (_cipher == Rc4Md5) + { + byte[] temp = new byte[keyLen + ivLen]; + Array.Copy(_key, 0, temp, 0, keyLen); + Array.Copy(iv, 0, temp, keyLen, ivLen); + realkey = CryptoUtils.MD5(temp); + } + else + { + realkey = _key; + } + sbox = SBox(realkey); + } + else if (_cipher == Table) + { + ulong a = BitConverter.ToUInt64(CryptoUtils.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; + } + } + } + + protected override void cipherUpdate(bool isEncrypt, int length, byte[] buf, byte[] outbuf) + { + 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); + + RC4(ctx, sbox, t, length); + Array.Copy(t, outbuf, length); + } + } + + private static readonly Dictionary _ciphers = new Dictionary + { + {"plain", new EncryptorInfo("PLAIN", 0, 0, Plain) }, + {"table", new EncryptorInfo("TABLE", 0, 0, Table) }, + { "rc4", new EncryptorInfo("RC4", 16, 0, Rc4) }, // original RC4 doesn't use IV + { "rc4-md5", new EncryptorInfo("RC4", 16, 16, Rc4Md5) }, + }; + + public static IEnumerable SupportedCiphers() + { + return _ciphers.Keys; + } + + protected override Dictionary getCiphers() + { + 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; + public int index2 = 0; + } + + private Context enc_ctx = new Context(); + private Context dec_ctx = new Context(); + + private byte[] SBox(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 RC4(Context ctx, byte[] s, byte[] data, int length) + { + for (int n = 0; n < length; n++) + { + byte b = data[n]; + + ctx.index1 = (ctx.index1 + 1) & 255; + ctx.index2 = (ctx.index2 + s[ctx.index1]) & 255; + + Swap(s, ctx.index1, ctx.index2); + + data[n] = (byte)(b ^ s[(s[ctx.index1] + s[ctx.index2]) & 255]); + } + } + + private static void Swap(byte[] s, int i, int j) + { + byte c = s[i]; + + s[i] = s[j]; + s[j] = c; + } + #endregion + } +} diff --git a/shadowsocks-csharp/Encryption/Stream/StreamOpenSSLEncryptor.cs b/shadowsocks-csharp/Encryption/Stream/StreamOpenSSLEncryptor.cs deleted file mode 100644 index 5897e09b..00000000 --- a/shadowsocks-csharp/Encryption/Stream/StreamOpenSSLEncryptor.cs +++ /dev/null @@ -1,159 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using Shadowsocks.Encryption.Exception; - - -namespace Shadowsocks.Encryption.Stream -{ - public class StreamOpenSSLEncryptor - : StreamEncryptor, IDisposable - { - const int CIPHER_RC4 = 1; - const int CIPHER_AES = 2; - const int CIPHER_CAMELLIA = 3; - const int CIPHER_BLOWFISH = 4; - const int CIPHER_CHACHA20_IETF = 5; - - private IntPtr _encryptCtx = IntPtr.Zero; - private IntPtr _decryptCtx = IntPtr.Zero; - - public StreamOpenSSLEncryptor(string method, string password) - : base(method, password) - { - } - - // XXX: name=RC4,blkSz=1,keyLen=16,ivLen=0, do NOT pass IV to it - private static readonly Dictionary _ciphers = new Dictionary - { - { "aes-128-cfb", new EncryptorInfo("AES-128-CFB", 16, 16, CIPHER_AES) }, - { "aes-192-cfb", new EncryptorInfo("AES-192-CFB", 24, 16, CIPHER_AES) }, - { "aes-256-cfb", new EncryptorInfo("AES-256-CFB", 32, 16, CIPHER_AES) }, - { "aes-128-ctr", new EncryptorInfo("aes-128-ctr", 16, 16, CIPHER_AES) }, - { "aes-192-ctr", new EncryptorInfo("aes-192-ctr", 24, 16, CIPHER_AES) }, - { "aes-256-ctr", new EncryptorInfo("aes-256-ctr", 32, 16, CIPHER_AES) }, - { "bf-cfb", new EncryptorInfo("bf-cfb", 16, 8, CIPHER_BLOWFISH) }, - { "camellia-128-cfb", new EncryptorInfo("CAMELLIA-128-CFB", 16, 16, CIPHER_CAMELLIA) }, - { "camellia-192-cfb", new EncryptorInfo("CAMELLIA-192-CFB", 24, 16, CIPHER_CAMELLIA) }, - { "camellia-256-cfb", new EncryptorInfo("CAMELLIA-256-CFB", 32, 16, CIPHER_CAMELLIA) }, - { "rc4-md5", new EncryptorInfo("RC4", 16, 16, CIPHER_RC4) }, - // it's using ivLen=16, not compatible - //{ "chacha20-ietf", new EncryptorInfo("chacha20", 32, 12, CIPHER_CHACHA20_IETF) } - }; - - public static List SupportedCiphers() - { - return new List(_ciphers.Keys); - } - - protected override Dictionary getCiphers() - { - return _ciphers; - } - - protected override void initCipher(byte[] iv, bool isEncrypt) - { - base.initCipher(iv, isEncrypt); - IntPtr cipherInfo = OpenSSL.GetCipherInfo(_innerLibName); - if (cipherInfo == IntPtr.Zero) throw new System.Exception("openssl: cipher not found"); - IntPtr ctx = OpenSSL.EVP_CIPHER_CTX_new(); - if (ctx == IntPtr.Zero) throw new System.Exception("fail to create ctx"); - - if (isEncrypt) - { - _encryptCtx = ctx; - } - else - { - _decryptCtx = ctx; - } - - byte[] realkey; - if (_method == "rc4-md5") - { - 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; - } - - var ret = OpenSSL.EVP_CipherInit_ex(ctx, cipherInfo, IntPtr.Zero, null,null, - isEncrypt ? OpenSSL.OPENSSL_ENCRYPT : OpenSSL.OPENSSL_DECRYPT); - if (ret != 1) throw new System.Exception("openssl: fail to set key length"); - ret = OpenSSL.EVP_CIPHER_CTX_set_key_length(ctx, keyLen); - if (ret != 1) throw new System.Exception("openssl: fail to set key length"); - ret = OpenSSL.EVP_CipherInit_ex(ctx, IntPtr.Zero, IntPtr.Zero, realkey, - _method == "rc4-md5" ? null : iv, - isEncrypt ? OpenSSL.OPENSSL_ENCRYPT : OpenSSL.OPENSSL_DECRYPT); - if (ret != 1) throw new System.Exception("openssl: cannot set key and iv"); - OpenSSL.EVP_CIPHER_CTX_set_padding(ctx, 0); - } - - protected override void cipherUpdate(bool isEncrypt, int length, byte[] buf, byte[] outbuf) - { - // C# could be multi-threaded - if (_disposed) - { - throw new ObjectDisposedException(this.ToString()); - } - - int outlen = 0; - var ret = OpenSSL.EVP_CipherUpdate(isEncrypt ? _encryptCtx : _decryptCtx, - outbuf, out outlen, buf, length); - if (ret != 1) - throw new CryptoErrorException(String.Format("ret is {0}", ret)); - Debug.Assert(outlen == length); - } - - #region IDisposable - - private bool _disposed; - - // instance based lock - private readonly object _lock = new object(); - - public override void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - ~StreamOpenSSLEncryptor() - { - Dispose(false); - } - - protected virtual void Dispose(bool disposing) - { - lock (_lock) - { - if (_disposed) return; - _disposed = true; - } - - if (disposing) - { - // free managed objects - } - - // free unmanaged objects - if (_encryptCtx != IntPtr.Zero) - { - OpenSSL.EVP_CIPHER_CTX_free(_encryptCtx); - _encryptCtx = IntPtr.Zero; - } - - if (_decryptCtx != IntPtr.Zero) - { - OpenSSL.EVP_CIPHER_CTX_free(_decryptCtx); - _decryptCtx = IntPtr.Zero; - } - } - - #endregion - } -} \ No newline at end of file diff --git a/shadowsocks-csharp/Encryption/Stream/StreamSodiumEncryptor.cs b/shadowsocks-csharp/Encryption/Stream/StreamSodiumEncryptor.cs deleted file mode 100644 index 523fab46..00000000 --- a/shadowsocks-csharp/Encryption/Stream/StreamSodiumEncryptor.cs +++ /dev/null @@ -1,107 +0,0 @@ -using System; -using System.Collections.Generic; -using Shadowsocks.Encryption.Exception; - -namespace Shadowsocks.Encryption.Stream -{ - public class StreamSodiumEncryptor - : StreamEncryptor, IDisposable - { - const int CIPHER_SALSA20 = 1; - const int CIPHER_CHACHA20 = 2; - const int CIPHER_CHACHA20_IETF = 3; - - const int SODIUM_BLOCK_SIZE = 64; - - protected int _encryptBytesRemaining; - protected int _decryptBytesRemaining; - protected ulong _encryptIC; - protected ulong _decryptIC; - protected byte[] _encryptBuf; - protected byte[] _decryptBuf; - - public StreamSodiumEncryptor(string method, string password) - : base(method, password) - { - _encryptBuf = new byte[MAX_INPUT_SIZE + SODIUM_BLOCK_SIZE]; - _decryptBuf = new byte[MAX_INPUT_SIZE + SODIUM_BLOCK_SIZE]; - } - - private static readonly Dictionary _ciphers = new Dictionary { - { "salsa20", new EncryptorInfo(32, 8, CIPHER_SALSA20) }, - { "chacha20", new EncryptorInfo(32, 8, CIPHER_CHACHA20) }, - { "chacha20-ietf", new EncryptorInfo(32, 12, CIPHER_CHACHA20_IETF) } - }; - - protected override Dictionary getCiphers() - { - return _ciphers; - } - - public static List SupportedCiphers() - { - return new List(_ciphers.Keys); - } - - protected override void cipherUpdate(bool isEncrypt, int length, byte[] buf, byte[] outbuf) - { - // TODO write a unidirection cipher so we don't have to if if if - int bytesRemaining; - ulong ic; - byte[] sodiumBuf; - byte[] iv; - int ret = -1; - - if (isEncrypt) - { - bytesRemaining = _encryptBytesRemaining; - ic = _encryptIC; - sodiumBuf = _encryptBuf; - iv = _encryptIV; - } - else - { - bytesRemaining = _decryptBytesRemaining; - ic = _decryptIC; - sodiumBuf = _decryptBuf; - iv = _decryptIV; - } - int padding = bytesRemaining; - Buffer.BlockCopy(buf, 0, sodiumBuf, padding, length); - - switch (_cipher) - { - case CIPHER_SALSA20: - ret = Sodium.crypto_stream_salsa20_xor_ic(sodiumBuf, sodiumBuf, (ulong)(padding + length), iv, ic, _key); - break; - case CIPHER_CHACHA20: - ret = Sodium.crypto_stream_chacha20_xor_ic(sodiumBuf, sodiumBuf, (ulong)(padding + length), iv, ic, _key); - break; - case CIPHER_CHACHA20_IETF: - ret = Sodium.crypto_stream_chacha20_ietf_xor_ic(sodiumBuf, sodiumBuf, (ulong)(padding + length), iv, (uint)ic, _key); - break; - } - if (ret != 0) throw new CryptoErrorException(); - - Buffer.BlockCopy(sodiumBuf, padding, outbuf, 0, length); - padding += length; - ic += (ulong)padding / SODIUM_BLOCK_SIZE; - bytesRemaining = padding % SODIUM_BLOCK_SIZE; - - if (isEncrypt) - { - _encryptBytesRemaining = bytesRemaining; - _encryptIC = ic; - } - else - { - _decryptBytesRemaining = bytesRemaining; - _decryptIC = ic; - } - } - - public override void Dispose() - { - } - } -} diff --git a/shadowsocks-csharp/Properties/Resources.Designer.cs b/shadowsocks-csharp/Properties/Resources.Designer.cs index bc5b8c24..a4e06702 100644 --- a/shadowsocks-csharp/Properties/Resources.Designer.cs +++ b/shadowsocks-csharp/Properties/Resources.Designer.cs @@ -1,10 +1,10 @@ //------------------------------------------------------------------------------ // -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 // -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 // //------------------------------------------------------------------------------ @@ -13,12 +13,12 @@ namespace Shadowsocks.Properties { /// - /// A strongly-typed resource class, for looking up localized strings, etc. + /// 一个强类型的资源类,用于查找本地化的字符串等。 /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] @@ -33,7 +33,7 @@ namespace Shadowsocks.Properties { } /// - /// Returns the cached ResourceManager instance used by this class. + /// 返回此类使用的缓存的 ResourceManager 实例。 /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] internal static global::System.Resources.ResourceManager ResourceManager { @@ -47,8 +47,8 @@ namespace Shadowsocks.Properties { } /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. + /// 重写当前线程的 CurrentUICulture 属性 + /// 重写当前线程的 CurrentUICulture 属性。 /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] internal static global::System.Globalization.CultureInfo Culture { @@ -61,7 +61,7 @@ namespace Shadowsocks.Properties { } /// - /// Looks up a localized string similar to /* eslint-disable */ + /// 查找类似 /* eslint-disable */ ///// Was generated by gfwlist2pac in precise mode ///// https://github.com/clowwindy/gfwlist2pac /// @@ -76,7 +76,7 @@ namespace Shadowsocks.Properties { ///* This file is part of Adblock Plus <http://adblockplus.org/>, ///* Copyright (C) 2006-2014 Eyeo GmbH ///* - ///* Adblock Plus is free software: you can redistribute it and/or [rest of string was truncated]";. + ///* Adblock Plus is free software: you can redistribute it and/or [字符串的其余部分被截断]"; 的本地化字符串。 /// internal static string abp_js { get { @@ -85,29 +85,28 @@ namespace Shadowsocks.Properties { } /// - /// Looks up a localized string similar to var __USERRULES__ = []; - ///var __RULES__ = [ - /// "|http://85.17.73.31/", - /// "||agnesb.fr", - /// "||akiba-web.com", - /// "||altrec.com", - /// "||angela-merkel.de", - /// "||angola.org", - /// "||apartmentratings.com", - /// "||apartments.com", - /// "||arena.taipei", - /// "||asianspiss.com", - /// "||assimp.org", - /// "||athenaeizou.com", - /// "||azubu.tv", - /// "||bankmobilevibe.com", - /// "||banorte.com", - /// "||bash-hackers.org", - /// "||beeg.com", - /// "||global.bing.com", - /// "||bloombergview.com", - /// "||booktopia.com.au", - /// [rest of string was truncated]";. + /// 查找类似 var __USERRULES__ = []; + ///var __RULES__ = [ + /// "|http://85.17.73.31/", + /// "||agnesb.fr", + /// "||akiba-web.com", + /// "||altrec.com", + /// "||angela-merkel.de", + /// "||angola.org", + /// "||apartmentratings.com", + /// "||apartments.com", + /// "||arena.taipei", + /// "||asianspiss.com", + /// "||assimp.org", + /// "||athenaeizou.com", + /// "||azubu.tv", + /// "||bankmobilevibe.com", + /// "||banorte.com", + /// "||bash-hackers.org", + /// "||beeg.com", + /// "||global.bing.com", + /// "||bloombergview.com", + /// " [字符串的其余部分被截断]"; 的本地化字符串。 /// internal static string default_abp_rule { get { @@ -116,24 +115,21 @@ namespace Shadowsocks.Properties { } /// - /// Looks up a localized string similar to en,zh-CN,zh-TW,ja - ///#Restart program to apply translation,,, - ///#This is comment line,,, - ///#Always keep language name at head of file,,, - ///#Language name is output in log,,, - ///"#You can find it by search ""Current language is:""",,, - ///#Please use UTF-8 with BOM encoding so we can edit it in Excel,,, - ///,,, - ///Shadowsocks,Shadowsocks,Shadowsocks,Shadowsocks - ///,,, - ///#Menu,,, - ///,,, - ///System Proxy,系统代理,系統代理,システムプロキシ - ///Disable,禁用,禁用,無効 - ///PAC,PAC 模式,PAC 模式,PAC - ///Global,全局模式,全局模式,全般 - ///Servers,服务器,伺服器,サーバー - ///Edit Servers...,编辑服务器...,編輯伺服器...,サーバーの編集.. [rest of string was truncated]";. + /// 查找类似 en,ru-RU,zh-CN,zh-TW,ja + ///#Restart program to apply translation,,,, + ///#This is comment line,,,, + ///#Always keep language name at head of file,,,, + ///#Language name is output in log,,,, + ///"#You can find it by search ""Current language is:""",,,, + ///#Please use UTF-8 with BOM encoding so we can edit it in Excel,,,, + ///,,,, + ///Shadowsocks,Shadowsocks,Shadowsocks,Shadowsocks,Shadowsocks + ///,,,, + ///#Menu,,,, + ///,,,, + ///System Proxy,Системный прокси-сервер,系统代理,系統代理,システムプロキシ + ///Disable,Отключен,禁用,禁用,無効 + ///PAC,Сценарий настройки (PAC),PA [字符串的其余部分被截断]"; 的本地化字符串。 /// internal static string i18n_csv { get { @@ -142,26 +138,13 @@ namespace Shadowsocks.Properties { } /// - /// Looks up a localized resource of type System.Byte[]. - /// - internal static byte[] libsscrypto_dll { - get { - object obj = ResourceManager.GetObject("libsscrypto_dll", resourceCulture); - return ((byte[])(obj)); - } - } - - /// - /// Looks up a localized string similar to <?xml version="1.0" encoding="utf-8" ?> + /// 查找类似 <?xml version="1.0" encoding="utf-8" ?> + ///<!-- Warning: Configuration may reset after shadowsocks upgrade. --> + ///<!-- If you messed it up, delete this file and Shadowsocks will create a new one. --> ///<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> /// <targets> - /// <target name="file" xsi:type="File" fileName="shadowsocks.log"/> - /// - /// </targets> - /// <rules> - /// <logger name="Name.Space.Class1" minlevel="Debug" writeTo="f1" /> - /// </rules> - ///</nlog>. + /// <!-- This line is managed by Shadowsocks. Do not modify it unless you know what you are doing.--> + /// <target name="file" xsi:type="File" fileName="ss_win_temp\shadowsocks.log" writ [字符串的其余部分被截断]"; 的本地化字符串。 /// internal static string NLog_config { get { @@ -170,7 +153,7 @@ namespace Shadowsocks.Properties { } /// - /// Looks up a localized string similar to listen-address __PRIVOXY_BIND_IP__:__PRIVOXY_BIND_PORT__ + /// 查找类似 listen-address __PRIVOXY_BIND_IP__:__PRIVOXY_BIND_PORT__ ///toggle 0 ///logfile ss_privoxy.log ///show-on-task-bar 0 @@ -178,7 +161,7 @@ namespace Shadowsocks.Properties { ///forward-socks5 / __SOCKS_HOST__:__SOCKS_PORT__ . ///max-client-connections 2048 ///hide-console - ///. + /// 的本地化字符串。 /// internal static string privoxy_conf { get { @@ -187,7 +170,7 @@ namespace Shadowsocks.Properties { } /// - /// Looks up a localized resource of type System.Byte[]. + /// 查找 System.Byte[] 类型的本地化资源。 /// internal static byte[] privoxy_exe { get { @@ -197,7 +180,7 @@ namespace Shadowsocks.Properties { } /// - /// Looks up a localized resource of type System.Drawing.Bitmap. + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 /// internal static System.Drawing.Bitmap ss32Fill { get { @@ -207,7 +190,7 @@ namespace Shadowsocks.Properties { } /// - /// Looks up a localized resource of type System.Drawing.Bitmap. + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 /// internal static System.Drawing.Bitmap ss32In { get { @@ -217,7 +200,7 @@ namespace Shadowsocks.Properties { } /// - /// Looks up a localized resource of type System.Drawing.Bitmap. + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 /// internal static System.Drawing.Bitmap ss32Out { get { @@ -227,7 +210,7 @@ namespace Shadowsocks.Properties { } /// - /// Looks up a localized resource of type System.Drawing.Bitmap. + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 /// internal static System.Drawing.Bitmap ss32Outline { get { @@ -237,7 +220,7 @@ namespace Shadowsocks.Properties { } /// - /// Looks up a localized resource of type System.Drawing.Bitmap. + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 /// internal static System.Drawing.Bitmap ssw128 { get { @@ -247,7 +230,7 @@ namespace Shadowsocks.Properties { } /// - /// Looks up a localized resource of type System.Byte[]. + /// 查找 System.Byte[] 类型的本地化资源。 /// internal static byte[] sysproxy_exe { get { @@ -257,7 +240,7 @@ namespace Shadowsocks.Properties { } /// - /// Looks up a localized resource of type System.Byte[]. + /// 查找 System.Byte[] 类型的本地化资源。 /// internal static byte[] sysproxy64_exe { get { @@ -267,9 +250,9 @@ namespace Shadowsocks.Properties { } /// - /// Looks up a localized string similar to ! Put user rules line by line in this file. + /// 查找类似 ! Put user rules line by line in this file. ///! See https://adblockplus.org/en/filter-cheatsheet - ///. + /// 的本地化字符串。 /// internal static string user_rule { get { diff --git a/shadowsocks-csharp/Properties/Resources.resx b/shadowsocks-csharp/Properties/Resources.resx index 99f2c596..253c66c0 100755 --- a/shadowsocks-csharp/Properties/Resources.resx +++ b/shadowsocks-csharp/Properties/Resources.resx @@ -127,9 +127,6 @@ ..\Data\i18n.csv;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 - - ..\Data\libsscrypto.dll.gz;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - ..\data\nlog.config;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 diff --git a/shadowsocks-csharp/View/ConfigForm.cs b/shadowsocks-csharp/View/ConfigForm.cs index 68fc3a7d..1384b336 100755 --- a/shadowsocks-csharp/View/ConfigForm.cs +++ b/shadowsocks-csharp/View/ConfigForm.cs @@ -31,6 +31,18 @@ namespace Shadowsocks.View "salsa20", "chacha20", "bf-cfb", + + "rc4", + "plain", + "table", + }; + private static string[] inuseMethod = new string[] + { + "aes-256-gcm", + "aes-192-gcm", + "aes-128-gcm", + "chacha20-ietf-poly1305", + "xchacha20-ietf-poly1305", "chacha20-ietf", "aes-256-cfb", "aes-192-cfb", @@ -42,14 +54,7 @@ namespace Shadowsocks.View "camellia-192-cfb", "camellia-128-cfb", }; - private static string[] inuseMethod = new string[] - { - "aes-256-gcm", - "aes-192-gcm", - "aes-128-gcm", - "chacha20-ietf-poly1305", - "xchacha20-ietf-poly1305", - }; + public static EncryptionMethod[] AllMethods { get diff --git a/shadowsocks-csharp/packages.config b/shadowsocks-csharp/packages.config new file mode 100644 index 00000000..97b73835 --- /dev/null +++ b/shadowsocks-csharp/packages.config @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/shadowsocks-csharp/shadowsocks-csharp.csproj b/shadowsocks-csharp/shadowsocks-csharp.csproj index 7d9c4467..de582723 100644 --- a/shadowsocks-csharp/shadowsocks-csharp.csproj +++ b/shadowsocks-csharp/shadowsocks-csharp.csproj @@ -14,11 +14,6 @@ - - true - x86 - - @@ -62,6 +57,7 @@ + @@ -86,7 +82,6 @@ - diff --git a/test/App.config b/test/App.config new file mode 100644 index 00000000..620550c5 --- /dev/null +++ b/test/App.config @@ -0,0 +1,14 @@ + + + +
+ + + + + + + + + + \ No newline at end of file diff --git a/test/CryptographyTest.cs b/test/CryptographyTest.cs index 68c2e3a8..fd641877 100644 --- a/test/CryptographyTest.cs +++ b/test/CryptographyTest.cs @@ -1,10 +1,9 @@ -using System; -using Microsoft.VisualStudio.TestTools.UnitTesting; +using Microsoft.VisualStudio.TestTools.UnitTesting; using Shadowsocks.Encryption; -using System.Threading; -using System.Collections.Generic; using Shadowsocks.Encryption.Stream; -using System.Diagnostics; +using System; +using System.Collections.Generic; +using System.Threading; namespace Shadowsocks.Test { @@ -22,7 +21,7 @@ namespace Shadowsocks.Test var random = new Random(); random.NextBytes(bytes); string md5str = Convert.ToBase64String(md5.ComputeHash(bytes)); - string md5str2 = Convert.ToBase64String(MbedTLS.MD5(bytes)); + string md5str2 = Convert.ToBase64String(CryptoUtils.MD5(bytes)); Assert.IsTrue(md5str == md5str2); } } @@ -31,7 +30,7 @@ namespace Shadowsocks.Test { RNG.Reload(); byte[] plain = new byte[16384]; - byte[] cipher = new byte[plain.Length + 16]; + byte[] cipher = new byte[plain.Length + 100];// AEAD with IPv4 address type needs +100 byte[] plain2 = new byte[plain.Length + 16]; int outLen = 0; int outLen2 = 0; @@ -64,57 +63,15 @@ namespace Shadowsocks.Test private static object locker = new object(); [TestMethod] - public void TestMbedTLSEncryption() - { - encryptionFailed = false; - // run it once before the multi-threading test to initialize global tables - RunSingleMbedTLSEncryptionThread(); - List threads = new List(); - for (int i = 0; i < 10; i++) - { - Thread t = new Thread(new ThreadStart(RunSingleMbedTLSEncryptionThread)); - threads.Add(t); - t.Start(); - } - foreach (Thread t in threads) - { - t.Join(); - } - RNG.Close(); - Assert.IsFalse(encryptionFailed); - } - - private void RunSingleMbedTLSEncryptionThread() - { - try - { - for (int i = 0; i < 100; i++) - { - IEncryptor encryptor; - IEncryptor decryptor; - encryptor = new StreamMbedTLSEncryptor("aes-256-cfb", "barfoo!"); - decryptor = new StreamMbedTLSEncryptor("aes-256-cfb", "barfoo!"); - RunEncryptionRound(encryptor, decryptor); - } - } - catch - { - encryptionFailed = true; - throw; - } - } - - [TestMethod] - public void TestRC4Encryption() + public void TestBouncyCastleAEADEncryption() { encryptionFailed = false; // run it once before the multi-threading test to initialize global tables - RunSingleRC4EncryptionThread(); + RunSingleBouncyCastleAEADEncryptionThread(); List threads = new List(); for (int i = 0; i < 10; i++) { - Thread t = new Thread(new ThreadStart(RunSingleRC4EncryptionThread)); - threads.Add(t); + Thread t = new Thread(new ThreadStart(RunSingleBouncyCastleAEADEncryptionThread)); threads.Add(t); t.Start(); } foreach (Thread t in threads) @@ -125,37 +82,16 @@ namespace Shadowsocks.Test Assert.IsFalse(encryptionFailed); } - private void RunSingleRC4EncryptionThread() - { - try - { - for (int i = 0; i < 100; i++) - { - var random = new Random(); - IEncryptor encryptor; - IEncryptor decryptor; - encryptor = new StreamMbedTLSEncryptor("rc4-md5", "barfoo!"); - decryptor = new StreamMbedTLSEncryptor("rc4-md5", "barfoo!"); - RunEncryptionRound(encryptor, decryptor); - } - } - catch - { - encryptionFailed = true; - throw; - } - } - [TestMethod] - public void TestSodiumEncryption() + public void TestNativeEncryption() { encryptionFailed = false; // run it once before the multi-threading test to initialize global tables - RunSingleSodiumEncryptionThread(); + RunSingleNativeEncryptionThread(); List threads = new List(); for (int i = 0; i < 10; i++) { - Thread t = new Thread(new ThreadStart(RunSingleSodiumEncryptionThread)); + Thread t = new Thread(new ThreadStart(RunSingleNativeEncryptionThread)); threads.Add(t); t.Start(); } @@ -167,18 +103,17 @@ namespace Shadowsocks.Test Assert.IsFalse(encryptionFailed); } - private void RunSingleSodiumEncryptionThread() + private void RunSingleNativeEncryptionThread() { try { for (int i = 0; i < 100; i++) { - var random = new Random(); - IEncryptor encryptor; - IEncryptor decryptor; - encryptor = new StreamSodiumEncryptor("salsa20", "barfoo!"); - decryptor = new StreamSodiumEncryptor("salsa20", "barfoo!"); - RunEncryptionRound(encryptor, decryptor); + IEncryptor encryptorN; + IEncryptor decryptorN; + encryptorN = new StreamNativeEncryptor("rc4-md5", "barfoo!"); + decryptorN = new StreamNativeEncryptor("rc4-md5", "barfoo!"); + RunEncryptionRound(encryptorN, decryptorN); } } catch @@ -188,28 +123,7 @@ namespace Shadowsocks.Test } } - [TestMethod] - public void TestOpenSSLEncryption() - { - encryptionFailed = false; - // run it once before the multi-threading test to initialize global tables - RunSingleOpenSSLEncryptionThread(); - List threads = new List(); - for (int i = 0; i < 10; i++) - { - Thread t = new Thread(new ThreadStart(RunSingleOpenSSLEncryptionThread)); - threads.Add(t); - t.Start(); - } - foreach (Thread t in threads) - { - t.Join(); - } - RNG.Close(); - Assert.IsFalse(encryptionFailed); - } - - private void RunSingleOpenSSLEncryptionThread() + private void RunSingleBouncyCastleAEADEncryptionThread() { try { @@ -218,8 +132,10 @@ namespace Shadowsocks.Test var random = new Random(); IEncryptor encryptor; IEncryptor decryptor; - encryptor = new StreamOpenSSLEncryptor("aes-256-cfb", "barfoo!"); - decryptor = new StreamOpenSSLEncryptor("aes-256-cfb", "barfoo!"); + encryptor = new Encryption.AEAD.AEADBouncyCastleEncryptor("aes-256-gcm", "barfoo!"); + encryptor.AddrBufLength = 1 + 4 + 2;// ADDR_ATYP_LEN + 4 + ADDR_PORT_LEN; + decryptor = new Encryption.AEAD.AEADBouncyCastleEncryptor("aes-256-gcm", "barfoo!"); + decryptor.AddrBufLength = 1 + 4 + 2;// ADDR_ATYP_LEN + 4 + ADDR_PORT_LEN; RunEncryptionRound(encryptor, decryptor); } } @@ -230,4 +146,4 @@ namespace Shadowsocks.Test } } } -} +} \ No newline at end of file diff --git a/test/ShadowsocksTest.csproj b/test/ShadowsocksTest.csproj index 0a77f8ef..f6a923b8 100644 --- a/test/ShadowsocksTest.csproj +++ b/test/ShadowsocksTest.csproj @@ -1,4 +1,4 @@ - + netcoreapp3.1