Compare commits

..
29 Commits
Author SHA1 Message Date
celeron533 25c1d02395 Update CHANGES and bump version 2018-03-14 22:32:31 +08:00
celeron533 897934c233 Add comments in app.config 2018-03-11 21:46:01 +08:00
Allen Zhu fdbd3a975b Merge pull request #1732 from wongsyrone/patch-1
add official way to dump network tracing info
2018-03-11 08:34:45 -05:00
Syrone Wong 7fd9ce2bc3 add official way to dump network tracing info
just uncomment the specific node in app.config, no need to recompile
to take effect. It will be shipped as Shadowsocks.exe.config after built.

This is for debugging only.
2018-03-11 16:05:37 +08:00
Allen Zhu c168af6975 Merge pull request #1725 from celeron533/master
add xchacha20-ietf-poly1305
2018-03-07 06:27:57 -06:00
Syrone Wong 3329291ab9 add xchacha20-ietf-poly1305
- update mbedtls to 2.7.0, use new md5 api
- update libsodium to 1.0.16
- static link to openssl 1.1.0g, check libsscrypto repo for detail
2018-03-03 22:22:01 +08:00
celeron533 1e04279d37 Update issue template 2018-03-03 20:37:18 +08:00
celeron533 20fa87ba89 Fix proxy bypass list #1674 2018-02-22 10:29:46 +08:00
celeron533 5db7c79407 Minor changes on Forward Proxy 2018-02-20 18:27:26 +08:00
HYec 85bd65e021 Only start the current server's plugin 2018-02-20 12:32:01 +08:00
HYec 7197e46b53 Close sockets before stop plugins 2018-02-20 12:31:53 +08:00
Allen Zhu b2c0bba953 Merge pull request #1682 from chenshaoju/patch-1
Add new requirement
2018-02-17 09:06:05 -06:00
Chen Shaoju d266ea2e39 fix 2018-02-17 11:28:01 +08:00
Chen Shaoju a5b11aee34 Add new requirements 2018-02-17 11:21:16 +08:00
celeron533 e2b9822224 Update CHANGES and bump version 2018-02-16 10:15:53 +08:00
Allen Zhu a12a70ccf0 Merge pull request #1671 from wongsyrone/master
Add OpenSSL 1.1.0g support due to hardware acceleration
2018-02-15 10:05:42 -06:00
Syrone Wong b2645f9f0a Fix bf-cfb name
Don't use Cname
2018-02-15 21:29:40 +08:00
Syrone Wong 4d4f1753c7 Add OpenSSL 1.1.0g support due to hardware acceleration
Note: If you want to compile it by yourself, please make sure
do NOT use `no-asm` configure option, since the main point of
this commit is to utilize assembly in openssl

Add OpenSSL test
2018-02-10 08:27:32 +08:00
celeron533 502397b5f9 Update nuget packages 2018-01-29 22:29:49 +08:00
celeron533 f042e91305 Minor changes
SIP003 server port validation
Year 2018
2018-01-29 21:23:41 +08:00
Allen Zhu d1219bbfca Merge pull request #1618 from hyec/master
Close sockets before stop plugins

Do not activate all servers' plugins at the same time
2018-01-27 09:35:19 -06:00
HYec 7564e79ede Only start the current server's plugin 2018-01-09 23:08:50 +08:00
HYec 511feb2e31 Close sockets before stop plugins 2018-01-06 22:06:15 +08:00
celeron533 647f986003 Avoid raise FileSystemWatcher event twice
When saving user-rule.txt file, some text editors can raise FileSystemWatcher event twice.
The 1st time is blank content, then the 2nd time is the modified content.
2017-12-20 22:48:52 +08:00
celeron533 8cd64d4022 Reuse the PAC file merge procedure 2017-12-20 21:49:05 +08:00
Allen Zhu 7021edd61f Merge pull request #1564 from jinliming2/user-rule
Put user rules at the begin of the PAC file.
2017-12-20 06:32:43 -06:00
Allen Zhu f7cd2390b2 Merge pull request #1568 from wongsyrone/patch-1
Close connection if received zero bytes
2017-12-15 06:22:19 -06:00
Syrone Wong 218925e191 Close connection if received zero bytes
This might fix 500 Privoxy Internal Error: no-server-data
2017-12-14 09:54:31 +08:00
Liming Jin dc718a583b Put user rules at the begin of the PAC file.
Fix: #1468
Enhance: 46d40fec67
2017-12-10 17:25:07 +08:00
31 changed files with 895 additions and 245 deletions
+9 -8
View File
@@ -1,19 +1,20 @@
Please read Wiki carefully, especially https://github.com/shadowsocks/shadowsocks-windows/wiki/Troubleshooting.
Please answer these questions before submitting your issue. Thanks!
Please read Wiki carefully, especially / 提问前请先阅读wiki https://github.com/shadowsocks/shadowsocks-windows/wiki/Troubleshooting.
Or search from issue board / 或在issue board中搜索 https://github.com/shadowsocks/shadowsocks-windows/issues?utf8=%E2%9C%93&q=is%3Aissue
Please answer these questions before submitting your issue. Thanks! / 请按照以下格式描述你的问题
### Version(release version or AppVeyor link)
### Version(release version or AppVeyor link) / 版本(正式版或基于AppVeyor的链接)
### Environment(Operating system, .NET Framework, etc)
### Environment(Operating system, .NET Framework, etc) / 操作环境(操作系统,.NET Framework等)
### Steps you have tried
### Steps you have tried / 操作步骤
### What did you expect to see?
### What did you expect to see? / 期望的结果
### What did you see instead?
### What did you see instead? / 实际结果
### Config and error log in detail (with all sensitive info masked)
### Config and error log in detail (with all sensitive info masked) / 配置文件和日志文件(请隐去敏感信息)
+11
View File
@@ -1,3 +1,14 @@
4.0.9 2018-03-14
- Fix port occupied issue
- Add xchacha20-ietf-poly1305
- Update cryptographic libraries
- Bug fixes and improvements
4.0.8 2018-02-16
- Add OpenSSL 1.1.0g support #1671
- Update nuget packages
- Bug fixes and improvements
4.0.7 2017-12-09
- Fix QR code and ss:// protocol import issue
- Add an option to show password
+15
View File
@@ -0,0 +1,15 @@
OpenSSL library guide for VS2017
# Read NOTES.WIN and NOTES.PERL
# use Visual Studio native tools command prompt
# use activeperl, install NASM assembler
ppm install dmake
# Win32 x86
set PATH=D:\NASM-32;%PATH%
perl Configure VC-WIN32 --release --prefix=C:\Users\home\Downloads\openssl-1.1.0g\x86-build --openssldir=C:\Users\home\Downloads\openssl-1.1.0g\x86-install
nmake
nmake test
# to rebuild
nmake distclean
+2 -1
View File
@@ -21,7 +21,7 @@ Download the [latest release].
#### Requirements
Microsoft [.NET Framework 4.6.2] or higher.
Microsoft [.NET Framework 4.6.2] or higher, Microsoft [Visual C++ 2015 Redistributable] (x86) .
#### Basic
@@ -118,3 +118,4 @@ GPLv3
[.NET Framework 4.6.2]: https://www.microsoft.com/en-US/download/details.aspx?id=53344
[Visual Studio 2015]: https://www.visualstudio.com/downloads/
[.NET Framework 4.6.2 Developer Pack]: https://www.microsoft.com/download/details.aspx?id=53321
[Visual C++ 2015 Redistributable]: https://www.microsoft.com/en-us/download/details.aspx?id=53840
@@ -36,52 +36,52 @@ namespace Shadowsocks.Controller
try
{
File.WriteAllText(Utils.GetTempPath("gfwlist.txt"), e.Result, Encoding.UTF8);
List<string> lines = ParseResult(e.Result);
if (File.Exists(PACServer.USER_RULE_FILE))
{
string local = FileManager.NonExclusiveReadAllText(PACServer.USER_RULE_FILE, Encoding.UTF8);
using (var sr = new StringReader(local))
{
foreach (var rule in sr.NonWhiteSpaceLines())
{
if (rule.BeginWithAny(IgnoredLineBegins))
continue;
lines.Add(rule);
}
}
}
string abpContent;
if (File.Exists(PACServer.USER_ABP_FILE))
{
abpContent = FileManager.NonExclusiveReadAllText(PACServer.USER_ABP_FILE, Encoding.UTF8);
}
else
{
abpContent = Utils.UnGzip(Resources.abp_js);
}
abpContent = abpContent.Replace("__RULES__", JsonConvert.SerializeObject(lines, Formatting.Indented));
if (File.Exists(PACServer.PAC_FILE))
{
string original = FileManager.NonExclusiveReadAllText(PACServer.PAC_FILE, Encoding.UTF8);
if (original == abpContent)
{
UpdateCompleted(this, new ResultEventArgs(false));
return;
}
}
File.WriteAllText(PACServer.PAC_FILE, abpContent, Encoding.UTF8);
if (UpdateCompleted != null)
{
UpdateCompleted(this, new ResultEventArgs(true));
}
bool pacFileChanged = MergeAndWritePACFile(e.Result);
UpdateCompleted?.Invoke(this, new ResultEventArgs(pacFileChanged));
}
catch (Exception ex)
{
if (Error != null)
Error?.Invoke(this, new ErrorEventArgs(ex));
}
}
public static bool MergeAndWritePACFile(string gfwListResult)
{
List<string> lines = new List<string>();
if (File.Exists(PACServer.USER_RULE_FILE))
{
string local = FileManager.NonExclusiveReadAllText(PACServer.USER_RULE_FILE, Encoding.UTF8);
using (var sr = new StringReader(local))
{
Error(this, new ErrorEventArgs(ex));
foreach (var rule in sr.NonWhiteSpaceLines())
{
if (rule.BeginWithAny(IgnoredLineBegins))
continue;
lines.Add(rule);
}
}
}
lines.AddRange(ParseResult(gfwListResult));
string abpContent;
if (File.Exists(PACServer.USER_ABP_FILE))
{
abpContent = FileManager.NonExclusiveReadAllText(PACServer.USER_ABP_FILE, Encoding.UTF8);
}
else
{
abpContent = Utils.UnGzip(Resources.abp_js);
}
abpContent = abpContent.Replace("__RULES__", JsonConvert.SerializeObject(lines, Formatting.Indented));
if (File.Exists(PACServer.PAC_FILE))
{
string original = FileManager.NonExclusiveReadAllText(PACServer.PAC_FILE, Encoding.UTF8);
if (original == abpContent)
{
return false;
}
}
File.WriteAllText(PACServer.PAC_FILE, abpContent, Encoding.UTF8);
return true;
}
public void UpdatePACFromGFWList(Configuration config)
@@ -85,6 +85,7 @@ namespace Shadowsocks.Controller
// Start an asynchronous socket to listen for connections.
Logging.Info("Shadowsocks started");
Logging.Info(Encryption.EncryptorFactory.DumpRegisteredEncryptor());
_tcpSocket.BeginAccept(new AsyncCallback(AcceptCallback), _tcpSocket);
UDPState udpState = new UDPState();
udpState.socket = _udpSocket;
@@ -202,6 +203,7 @@ namespace Shadowsocks.Controller
try
{
int bytesRead = conn.EndReceive(ar);
if (bytesRead <= 0) goto Shutdown;
foreach (IService service in _services)
{
if (service.Handle(buf, bytesRead, conn, null))
@@ -209,6 +211,7 @@ namespace Shadowsocks.Controller
return;
}
}
Shutdown:
// no service found for this
if (conn.ProtocolType == ProtocolType.Tcp)
{
@@ -9,6 +9,7 @@ using Shadowsocks.Encryption;
using Shadowsocks.Model;
using Shadowsocks.Properties;
using Shadowsocks.Util;
using System.Threading.Tasks;
namespace Shadowsocks.Controller
{
@@ -241,42 +242,34 @@ Connection: Close
#region FileSystemWatcher.OnChanged()
// FileSystemWatcher Changed event is raised twice
// http://stackoverflow.com/questions/1764809/filesystemwatcher-changed-event-is-raised-twice
private static Hashtable fileChangedTime = new Hashtable();
// Add a short delay to avoid raise event twice in a short period
private void PACFileWatcher_Changed(object sender, FileSystemEventArgs e)
{
string path = e.FullPath.ToString();
string currentLastWriteTime = File.GetLastWriteTime(e.FullPath).ToString(CultureInfo.InvariantCulture);
// if there is no path info stored yet or stored path has different time of write then the one now is inspected
if (!fileChangedTime.ContainsKey(path) || fileChangedTime[path].ToString() != currentLastWriteTime)
if (PACFileChanged != null)
{
if (PACFileChanged != null)
Logging.Info($"Detected: PAC file '{e.Name}' was {e.ChangeType.ToString().ToLower()}.");
Task.Factory.StartNew(() =>
{
Logging.Info($"Detected: PAC file '{e.Name}' was {e.ChangeType.ToString().ToLower()}.");
((FileSystemWatcher)sender).EnableRaisingEvents = false;
System.Threading.Thread.Sleep(10);
PACFileChanged(this, new EventArgs());
}
// lastly we update the last write time in the hashtable
fileChangedTime[path] = currentLastWriteTime;
((FileSystemWatcher)sender).EnableRaisingEvents = true;
});
}
}
private void UserRuleFileWatcher_Changed(object sender, FileSystemEventArgs e)
{
string path = e.FullPath.ToString();
string currentLastWriteTime = File.GetLastWriteTime(e.FullPath).ToString(CultureInfo.InvariantCulture);
// if there is no path info stored yet or stored path has different time of write then the one now is inspected
if (!fileChangedTime.ContainsKey(path) || fileChangedTime[path].ToString() != currentLastWriteTime)
if (UserRuleFileChanged != null)
{
if (UserRuleFileChanged != null)
Logging.Info($"Detected: User Rule file '{e.Name}' was {e.ChangeType.ToString().ToLower()}.");
Task.Factory.StartNew(()=>
{
Logging.Info($"Detected: User Rule file '{e.Name}' was {e.ChangeType.ToString().ToLower()}.");
((FileSystemWatcher)sender).EnableRaisingEvents = false;
System.Threading.Thread.Sleep(10);
UserRuleFileChanged(this, new EventArgs());
}
// lastly we update the last write time in the hashtable
fileChangedTime[path] = currentLastWriteTime;
((FileSystemWatcher)sender).EnableRaisingEvents = true;
});
}
}
#endregion
@@ -43,7 +43,7 @@ namespace Shadowsocks.Controller.Service
{
throw new ArgumentException("Value cannot be null or whitespace.", nameof(serverAddress));
}
if ((ushort)serverPort != serverPort)
if (serverPort <= 0 || serverPort > 65535)
{
throw new ArgumentOutOfRangeException("serverPort");
}
@@ -24,7 +24,7 @@ namespace Shadowsocks.Controller
public string LatestVersionLocalName;
public event EventHandler CheckUpdateCompleted;
public const string Version = "4.0.7";
public const string Version = "4.0.9";
private class CheckUpdateTimer : System.Timers.Timer
{
@@ -240,19 +240,9 @@ namespace Shadowsocks.Controller
}
}
public void DisableProxy()
public void SaveProxy(ProxyConfig proxyConfig)
{
_config.proxy.useProxy = false;
SaveConfig(_config);
}
public void EnableProxy(int type, string proxy, int port, int timeout)
{
_config.proxy.useProxy = true;
_config.proxy.proxyType = type;
_config.proxy.proxyServer = proxy;
_config.proxy.proxyPort = port;
_config.proxy.proxyTimeout = timeout;
_config.proxy = proxyConfig;
SaveConfig(_config);
}
@@ -490,8 +480,6 @@ namespace Shadowsocks.Controller
protected void Reload()
{
StopPlugins();
Encryption.RNG.Reload();
// some logic in configuration updated the config when saving, we need to read it again
_config = Configuration.Load();
@@ -521,6 +509,9 @@ namespace Shadowsocks.Controller
{
_listener.Stop();
}
StopPlugins();
// don't put PrivoxyRunner.Start() before pacServer.Stop()
// or bind will fail when switching bind address from 0.0.0.0 to 127.0.0.1
// though UseShellExecute is set to true now
@@ -534,7 +525,7 @@ namespace Shadowsocks.Controller
strategy.ReloadServers();
}
StartPlugins();
StartPlugin();
privoxyRunner.Start(_config);
TCPRelay tcpRelay = new TCPRelay(this, _config);
@@ -572,13 +563,10 @@ namespace Shadowsocks.Controller
Utils.ReleaseMemory(true);
}
private void StartPlugins()
private void StartPlugin()
{
foreach (var server in _config.configs)
{
// Early start plugin processes
GetPluginLocalEndPointIfConfigured(server);
}
var server = _config.GetCurrentServer();
GetPluginLocalEndPointIfConfigured(server);
}
protected void SaveConfig(Configuration newConfig)
@@ -612,46 +600,14 @@ namespace Shadowsocks.Controller
private static readonly IEnumerable<char> IgnoredLineBegins = new[] { '!', '[' };
private void pacServer_UserRuleFileChanged(object sender, EventArgs e)
{
// TODO: this is a dirty hack. (from code GListUpdater.http_DownloadStringCompleted())
if (!File.Exists(Utils.GetTempPath("gfwlist.txt")))
{
UpdatePACFromGFWList();
return;
}
List<string> lines = new List<string>();
if (File.Exists(PACServer.USER_RULE_FILE))
{
string local = FileManager.NonExclusiveReadAllText(PACServer.USER_RULE_FILE, Encoding.UTF8);
using (var sr = new StringReader(local))
{
foreach (var rule in sr.NonWhiteSpaceLines())
{
if (rule.BeginWithAny(IgnoredLineBegins))
continue;
lines.Add(rule);
}
}
}
lines.AddRange(GFWListUpdater.ParseResult(FileManager.NonExclusiveReadAllText(Utils.GetTempPath("gfwlist.txt"))));
string abpContent;
if (File.Exists(PACServer.USER_ABP_FILE))
{
abpContent = FileManager.NonExclusiveReadAllText(PACServer.USER_ABP_FILE, Encoding.UTF8);
}
else
{
abpContent = Utils.UnGzip(Resources.abp_js);
GFWListUpdater.MergeAndWritePACFile(FileManager.NonExclusiveReadAllText(Utils.GetTempPath("gfwlist.txt")));
}
abpContent = abpContent.Replace("__RULES__", JsonConvert.SerializeObject(lines, Formatting.Indented));
if (File.Exists(PACServer.PAC_FILE))
{
string original = FileManager.NonExclusiveReadAllText(PACServer.PAC_FILE, Encoding.UTF8);
if (original == abpContent)
{
return;
}
}
File.WriteAllText(PACServer.PAC_FILE, abpContent, Encoding.UTF8);
}
public void CopyPacUrl()
Binary file not shown.
@@ -127,9 +127,9 @@ namespace Shadowsocks.Encryption.AEAD
public static void randBytes(byte[] buf, int length) { RNG.GetBytes(buf, length); }
public abstract int cipherEncrypt(byte[] plaintext, uint plen, byte[] ciphertext, ref uint clen);
public abstract void cipherEncrypt(byte[] plaintext, uint plen, byte[] ciphertext, ref uint clen);
public abstract int cipherDecrypt(byte[] ciphertext, uint clen, byte[] plaintext, ref uint plen);
public abstract void cipherDecrypt(byte[] ciphertext, uint clen, byte[] plaintext, ref uint plen);
#region TCP
@@ -19,7 +19,7 @@ namespace Shadowsocks.Encryption.AEAD
{
}
private static Dictionary<string, EncryptorInfo> _ciphers = new Dictionary<string, EncryptorInfo>
private static readonly Dictionary<string, EncryptorInfo> _ciphers = new Dictionary<string, EncryptorInfo>
{
{"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)},
@@ -48,6 +48,7 @@ namespace Shadowsocks.Encryption.AEAD
{
_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");
@@ -67,7 +68,7 @@ namespace Shadowsocks.Encryption.AEAD
if (ret != 0) throw new System.Exception("failed to finish preparation");
}
public override int cipherEncrypt(byte[] plaintext, uint plen, byte[] ciphertext, ref uint clen)
public override void cipherEncrypt(byte[] plaintext, uint plen, byte[] ciphertext, ref uint clen)
{
// buf: all plaintext
// outbuf: ciphertext + tag
@@ -87,18 +88,18 @@ namespace Shadowsocks.Encryption.AEAD
/* cipher */
ciphertext, ref olen,
tagbuf, (uint) tagLen);
if (ret != 0) throw new CryptoErrorException();
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;
return ret;
break;
default:
throw new System.Exception("not implemented");
}
}
public override int cipherDecrypt(byte[] ciphertext, uint clen, byte[] plaintext, ref uint plen)
public override void cipherDecrypt(byte[] ciphertext, uint clen, byte[] plaintext, ref uint plen)
{
// buf: ciphertext + tag
// outbuf: plaintext
@@ -116,10 +117,10 @@ namespace Shadowsocks.Encryption.AEAD
ciphertext, (uint) (clen - tagLen),
plaintext, ref olen,
tagbuf, (uint) tagLen);
if (ret != 0) throw new CryptoErrorException();
if (ret != 0) throw new CryptoErrorException(String.Format("ret is {0}", ret));
Debug.Assert(olen == clen - tagLen);
plen = olen;
return ret;
break;
default:
throw new System.Exception("not implemented");
}
@@ -163,6 +164,7 @@ namespace Shadowsocks.Encryption.AEAD
Marshal.FreeHGlobal(_encryptCtx);
_encryptCtx = IntPtr.Zero;
}
if (_decryptCtx != IntPtr.Zero)
{
MbedTLS.cipher_free(_decryptCtx);
@@ -0,0 +1,192 @@
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<string, EncryptorInfo> _ciphers = new Dictionary<string, EncryptorInfo>
{
{"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<string> SupportedCiphers()
{
return new List<string>(_ciphers.Keys);
}
protected override Dictionary<string, EncryptorInfo> 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
}
}
@@ -10,7 +10,8 @@ namespace Shadowsocks.Encryption.AEAD
: AEADEncryptor, IDisposable
{
private const int CIPHER_CHACHA20IETFPOLY1305 = 1;
private const int CIPHER_AES256GCM = 2;
private const int CIPHER_XCHACHA20IETFPOLY1305 = 2;
private const int CIPHER_AES256GCM = 3;
private byte[] _sodiumEncSubkey;
private byte[] _sodiumDecSubkey;
@@ -22,9 +23,10 @@ namespace Shadowsocks.Encryption.AEAD
_sodiumDecSubkey = new byte[keyLen];
}
private static Dictionary<string, EncryptorInfo> _ciphers = new Dictionary<string, EncryptorInfo>
private static readonly Dictionary<string, EncryptorInfo> _ciphers = new Dictionary<string, EncryptorInfo>
{
{"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)},
};
@@ -46,7 +48,7 @@ namespace Shadowsocks.Encryption.AEAD
}
public override int cipherEncrypt(byte[] plaintext, uint plen, byte[] ciphertext, ref uint clen)
public override void cipherEncrypt(byte[] plaintext, uint plen, byte[] ciphertext, ref uint clen)
{
Debug.Assert(_sodiumEncSubkey != null);
// buf: all plaintext
@@ -65,6 +67,13 @@ namespace Shadowsocks.Encryption.AEAD
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,
@@ -75,13 +84,12 @@ namespace Shadowsocks.Encryption.AEAD
default:
throw new System.Exception("not implemented");
}
if (ret != 0) throw new CryptoErrorException();
if (ret != 0) throw new CryptoErrorException(String.Format("ret is {0}", ret));
Logging.Dump("after cipherEncrypt: cipher", ciphertext, (int) encClen);
clen = (uint) encClen;
return ret;
}
public override int cipherDecrypt(byte[] ciphertext, uint clen, byte[] plaintext, ref uint plen)
public override void cipherDecrypt(byte[] ciphertext, uint clen, byte[] plaintext, ref uint plen)
{
Debug.Assert(_sodiumDecSubkey != null);
// buf: ciphertext + tag
@@ -100,6 +108,13 @@ namespace Shadowsocks.Encryption.AEAD
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,
@@ -111,10 +126,9 @@ namespace Shadowsocks.Encryption.AEAD
throw new System.Exception("not implemented");
}
if (ret != 0) throw new CryptoErrorException();
if (ret != 0) throw new CryptoErrorException(String.Format("ret is {0}", ret));
Logging.Dump("after cipherDecrypt: plain", plaintext, (int) decPlen);
plen = (uint) decPlen;
return ret;
}
public override void Dispose()
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
using Shadowsocks.Encryption.AEAD;
using Shadowsocks.Encryption.Stream;
@@ -26,21 +27,42 @@ namespace Shadowsocks.Encryption
AEADSodiumEncryptorSupportedCiphers.Remove("aes-256-gcm");
}
foreach (string method in StreamMbedTLSEncryptor.SupportedCiphers())
// XXX: sequence matters, OpenSSL > Sodium > MbedTLS
foreach (string method in StreamOpenSSLEncryptor.SupportedCiphers())
{
_registeredEncryptors.Add(method, typeof(StreamMbedTLSEncryptor));
if (!_registeredEncryptors.ContainsKey(method))
_registeredEncryptors.Add(method, typeof(StreamOpenSSLEncryptor));
}
foreach (string method in StreamSodiumEncryptor.SupportedCiphers())
{
_registeredEncryptors.Add(method, typeof(StreamSodiumEncryptor));
if (!_registeredEncryptors.ContainsKey(method))
_registeredEncryptors.Add(method, typeof(StreamSodiumEncryptor));
}
foreach (string method in AEADMbedTLSEncryptorSupportedCiphers)
foreach (string method in StreamMbedTLSEncryptor.SupportedCiphers())
{
_registeredEncryptors.Add(method, typeof(AEADMbedTLSEncryptor));
if (!_registeredEncryptors.ContainsKey(method))
_registeredEncryptors.Add(method, typeof(StreamMbedTLSEncryptor));
}
foreach (string method in AEADOpenSSLEncryptor.SupportedCiphers())
{
if (!_registeredEncryptors.ContainsKey(method))
_registeredEncryptors.Add(method, typeof(AEADOpenSSLEncryptor));
}
foreach (string method in AEADSodiumEncryptorSupportedCiphers)
{
_registeredEncryptors.Add(method, typeof(AEADSodiumEncryptor));
if (!_registeredEncryptors.ContainsKey(method))
_registeredEncryptors.Add(method, typeof(AEADSodiumEncryptor));
}
foreach (string method in AEADMbedTLSEncryptorSupportedCiphers)
{
if (!_registeredEncryptors.ContainsKey(method))
_registeredEncryptors.Add(method, typeof(AEADMbedTLSEncryptor));
}
}
@@ -50,12 +72,29 @@ namespace Shadowsocks.Encryption
{
method = "aes-256-cfb";
}
method = method.ToLowerInvariant();
Type t = _registeredEncryptors[method];
ConstructorInfo c = t.GetConstructor(ConstructorTypes);
if (c == null) throw new System.Exception("Invalid ctor");
IEncryptor result = (IEncryptor) c.Invoke(new object[] {method, password});
return result;
}
public static string DumpRegisteredEncryptor()
{
var sb = new StringBuilder();
sb.Append(Environment.NewLine);
sb.AppendLine("=========================");
sb.AppendLine("Registered Encryptor Info");
foreach (var encryptor in _registeredEncryptors)
{
sb.AppendLine(String.Format("{0}=>{1}", encryptor.Key, encryptor.Value.Name));
}
sb.AppendLine("=========================");
return sb.ToString();
}
}
}
+3 -2
View File
@@ -34,7 +34,8 @@ namespace Shadowsocks.Encryption
public static byte[] MD5(byte[] input)
{
byte[] output = new byte[16];
md5(input, (uint) input.Length, output);
if (md5_ret(input, (uint) input.Length, output) != 0)
throw new System.Exception("mbedtls: MD5 failure");
return output;
}
@@ -42,7 +43,7 @@ namespace Shadowsocks.Encryption
private static extern IntPtr LoadLibrary(string path);
[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
public static extern void md5(byte[] input, uint ilen, byte[] output);
public static extern int md5_ret(byte[] input, uint ilen, byte[] output);
/// <summary>
/// Get cipher ctx size for unmanaged memory allocation
+161
View File
@@ -0,0 +1,161 @@
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Security;
using System.Text;
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 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)
{
Logging.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);
}
/// <summary>
/// Need init cipher context after EVP_CipherFinal_ex to reuse context
/// </summary>
/// <param name="ctx"></param>
/// <param name="cipherType"></param>
/// <param name="nonce"></param>
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);
/// <summary>
/// simulate NUL-terminated string
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
[SuppressUnmanagedCodeSecurity]
[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr EVP_get_cipherbyname(byte[] name);
}
}
+8
View File
@@ -73,6 +73,14 @@ namespace Shadowsocks.Encryption
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);
@@ -0,0 +1,160 @@
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<string, EncryptorInfo> _ciphers = new Dictionary<string, EncryptorInfo>
{
{ "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<string> SupportedCiphers()
{
return new List<string>(_ciphers.Keys);
}
protected override Dictionary<string, EncryptorInfo> 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];
realkey = new byte[keyLen];
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
}
}
@@ -27,7 +27,7 @@ namespace Shadowsocks.Encryption.Stream
_decryptBuf = new byte[MAX_INPUT_SIZE + SODIUM_BLOCK_SIZE];
}
private static Dictionary<string, EncryptorInfo> _ciphers = new Dictionary<string, EncryptorInfo> {
private static readonly Dictionary<string, EncryptorInfo> _ciphers = new Dictionary<string, EncryptorInfo> {
{ "salsa20", new EncryptorInfo(32, 8, CIPHER_SALSA20) },
{ "chacha20", new EncryptorInfo(32, 8, CIPHER_CHACHA20) },
{ "chacha20-ietf", new EncryptorInfo(32, 12, CIPHER_CHACHA20_IETF) }
@@ -11,7 +11,7 @@ using System.Runtime.InteropServices;
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Shadowsocks")]
[assembly: AssemblyCopyright("clowwindy & community 2017")]
[assembly: AssemblyCopyright("clowwindy & community 2018")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
+44 -44
View File
@@ -1,10 +1,10 @@
//------------------------------------------------------------------------------
// <auto-generated>
// 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.
// 对此文件的更改可能会导致不正确的行为,并且如果
// 重新生成代码,这些更改将会丢失。
// </auto-generated>
//------------------------------------------------------------------------------
@@ -13,13 +13,13 @@ namespace Shadowsocks.Properties {
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// 一个强类型的资源类,用于查找本地化的字符串等。
/// </summary>
// 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.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
// 此类是由 StronglyTypedResourceBuilder
// 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
// 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen
// (以 /str 作为命令选项),或重新生成 VS 项目。
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
@@ -33,7 +33,7 @@ namespace Shadowsocks.Properties {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// 返回此类使用的缓存的 ResourceManager 实例。
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
@@ -47,8 +47,8 @@ namespace Shadowsocks.Properties {
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// 使用此强类型资源类,为所有资源查找
/// 重写当前线程的 CurrentUICulture 属性。
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
@@ -61,7 +61,7 @@ namespace Shadowsocks.Properties {
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// 查找 System.Byte[] 类型的本地化资源。
/// </summary>
internal static byte[] abp_js {
get {
@@ -71,28 +71,28 @@ namespace Shadowsocks.Properties {
}
/// <summary>
/// Looks up a localized string similar to # translation for Japanese
/// 查找类似 # translation for Japanese
///
///Shadowsocks=Shadowsocks
///
///# Menu items
///
///Enable System Proxy=システムの代理を有効にする
///Enable System Proxy=システム プロキシを有効にする
///Mode=モード
///PAC=PAC
///Global=全般
///Servers=サーバ
///Edit Servers...=サーバーを編集する...
///Servers=サーバー
///Edit Servers...=サーバーの編集...
///Statistics Config...=統計情報の設定...
///Start on Boot=システムと同時に起動
///Forward Proxy...=代理を転送する...
///Allow Clients from LAN=LANからのクライアントを許可する
///Forward Proxy...=フォワードプロキシの設定...
///Allow Clients from LAN=LAN からのアクセスを許可
///Local PAC=ローカル PAC
///Online PAC=オンライン PAC
///Edit Local PAC File...=ローカル PAC ファイルを編集する...
///Update Local PAC from GFWList=GFWList から、ローカル PACを更新する
///Edit User Rule for GFWList...=利用者規則を編集する...
///Secure Local [rest of string was truncated]&quot;;.
///Edit Local PAC File...=ローカル PAC ファイルの編集...
///Update Local PAC from GFWList=GFWList からローカル PAC を更新
///Edit User Rule for GFWList...=ユーザールールの編集...
///Secure Local [字符串的其余部分被截断]&quot;; 的本地化字符串。
/// </summary>
internal static string ja {
get {
@@ -101,7 +101,7 @@ namespace Shadowsocks.Properties {
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// 查找 System.Byte[] 类型的本地化资源。
/// </summary>
internal static byte[] libsscrypto_dll {
get {
@@ -111,7 +111,7 @@ namespace Shadowsocks.Properties {
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// 查找 System.Byte[] 类型的本地化资源。
/// </summary>
internal static byte[] mgwz_dll {
get {
@@ -121,14 +121,14 @@ namespace Shadowsocks.Properties {
}
/// <summary>
/// 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
///activity-animation 0
///forward-socks5 / 127.0.0.1:__SOCKS_PORT__ .
///hide-console
///.
/// 的本地化字符串。
/// </summary>
internal static string privoxy_conf {
get {
@@ -137,7 +137,7 @@ namespace Shadowsocks.Properties {
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// 查找 System.Byte[] 类型的本地化资源。
/// </summary>
internal static byte[] privoxy_exe {
get {
@@ -147,7 +147,7 @@ namespace Shadowsocks.Properties {
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// 查找 System.Byte[] 类型的本地化资源。
/// </summary>
internal static byte[] proxy_pac_txt {
get {
@@ -157,7 +157,7 @@ namespace Shadowsocks.Properties {
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// 查找 System.Drawing.Bitmap 类型的本地化资源。
/// </summary>
internal static System.Drawing.Bitmap ss16 {
get {
@@ -167,7 +167,7 @@ namespace Shadowsocks.Properties {
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// 查找 System.Drawing.Bitmap 类型的本地化资源。
/// </summary>
internal static System.Drawing.Bitmap ss20 {
get {
@@ -177,7 +177,7 @@ namespace Shadowsocks.Properties {
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// 查找 System.Drawing.Bitmap 类型的本地化资源。
/// </summary>
internal static System.Drawing.Bitmap ss24 {
get {
@@ -187,7 +187,7 @@ namespace Shadowsocks.Properties {
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// 查找 System.Drawing.Bitmap 类型的本地化资源。
/// </summary>
internal static System.Drawing.Bitmap ssIn24 {
get {
@@ -197,7 +197,7 @@ namespace Shadowsocks.Properties {
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// 查找 System.Drawing.Bitmap 类型的本地化资源。
/// </summary>
internal static System.Drawing.Bitmap ssOut24 {
get {
@@ -207,7 +207,7 @@ namespace Shadowsocks.Properties {
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// 查找 System.Drawing.Bitmap 类型的本地化资源。
/// </summary>
internal static System.Drawing.Bitmap ssw128 {
get {
@@ -217,7 +217,7 @@ namespace Shadowsocks.Properties {
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// 查找 System.Byte[] 类型的本地化资源。
/// </summary>
internal static byte[] sysproxy_exe {
get {
@@ -227,7 +227,7 @@ namespace Shadowsocks.Properties {
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// 查找 System.Byte[] 类型的本地化资源。
/// </summary>
internal static byte[] sysproxy64_exe {
get {
@@ -237,9 +237,9 @@ namespace Shadowsocks.Properties {
}
/// <summary>
/// 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
///.
/// 的本地化字符串。
/// </summary>
internal static string user_rule {
get {
@@ -248,7 +248,7 @@ namespace Shadowsocks.Properties {
}
/// <summary>
/// Looks up a localized string similar to # translation for Simplified Chinese
/// 查找类似 # translation for Simplified Chinese
///
///Shadowsocks=Shadowsocks
///
@@ -270,7 +270,7 @@ namespace Shadowsocks.Properties {
///Update Local PAC from GFWList=从 GFWList 更新本地 PAC
///Edit User Rule for GFWList...=编辑 GFWList 的用户规则...
///Secure Local PAC=保护本地 PAC
///Cop [rest of string was truncated]&quot;;.
///Cop [字符串的其余部分被截断]&quot;; 的本地化字符串。
/// </summary>
internal static string zh_CN {
get {
@@ -279,7 +279,7 @@ namespace Shadowsocks.Properties {
}
/// <summary>
/// Looks up a localized string similar to # translation for Traditional Chinese
/// 查找类似 # translation for Traditional Chinese
///
///Shadowsocks=Shadowsocks
///
@@ -300,7 +300,7 @@ namespace Shadowsocks.Properties {
///Edit Local PAC File...=編輯本機 PAC 檔案...
///Update Local PAC from GFWList=從 GFWList 更新本機 PAC
///Edit User Rule for GFWList...=編輯 GFWList 的使用者規則...
///Secure Local PAC=安全本機 [rest of string was truncated]&quot;;.
///Secure Local PAC=安全本機 [字符串的其余部分被截断]&quot;; 的本地化字符串。
/// </summary>
internal static string zh_TW {
get {
+1 -1
View File
@@ -125,7 +125,7 @@
<value>..\Data\ja.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
</data>
<data name="libsscrypto_dll" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\data\libsscrypto.dll.gz;System.Byte[], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
<value>..\Data\libsscrypto.dll.gz;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="mgwz_dll" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\data\mgwz.dll.gz;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
@@ -60,7 +60,7 @@ namespace Shadowsocks.Util.SystemProxy
if (enable)
{
arguments = global
? $"global {proxyServer} <local>;localhost;127.*;10.*;172.16.*;172.17.*;172.18.*;172.19.*;172.20.*;172.21.*;172.22.*;172.23.*;172.24.*;172.25.*;172.26.*;172.27.*;172.28.*;172.29.*;172.30.*;172.31.*;172.32.*;192.168.*"
? $"global {proxyServer} <local>;localhost;127.*;10.*;172.16.*;172.17.*;172.18.*;172.19.*;172.20.*;172.21.*;172.22.*;172.23.*;172.24.*;172.25.*;172.26.*;172.27.*;172.28.*;172.29.*;172.30.*;172.31.*;192.168.*"
: $"pac {pacURL}";
}
else
+2 -1
View File
@@ -252,7 +252,8 @@
"aes-128-gcm",
"aes-192-gcm",
"aes-256-gcm",
"chacha20-ietf-poly1305"});
"chacha20-ietf-poly1305",
"xchacha20-ietf-poly1305"});
this.EncryptionSelect.Location = new System.Drawing.Point(101, 109);
this.EncryptionSelect.Name = "EncryptionSelect";
this.EncryptionSelect.Size = new System.Drawing.Size(160, 20);
+24 -30
View File
@@ -12,7 +12,7 @@ namespace Shadowsocks.View
private ShadowsocksController controller;
// this is a copy of configuration that we are working on
private ProxyConfig _modifiedConfiguration;
private ProxyConfig _modifiedProxyConfig;
public ProxyForm(ShadowsocksController controller)
{
@@ -49,53 +49,47 @@ namespace Shadowsocks.View
private void LoadCurrentConfiguration()
{
_modifiedConfiguration = controller.GetConfigurationCopy().proxy;
UseProxyCheckBox.Checked = _modifiedConfiguration.useProxy;
ProxyServerTextBox.Text = _modifiedConfiguration.proxyServer;
ProxyPortTextBox.Text = _modifiedConfiguration.proxyPort.ToString();
ProxyTimeoutTextBox.Text = _modifiedConfiguration.proxyTimeout.ToString();
ProxyTypeComboBox.SelectedIndex = _modifiedConfiguration.proxyType;
_modifiedProxyConfig = controller.GetConfigurationCopy().proxy;
UseProxyCheckBox.Checked = _modifiedProxyConfig.useProxy;
ProxyServerTextBox.Text = _modifiedProxyConfig.proxyServer;
ProxyPortTextBox.Text = _modifiedProxyConfig.proxyPort.ToString();
ProxyTimeoutTextBox.Text = _modifiedProxyConfig.proxyTimeout.ToString();
ProxyTypeComboBox.SelectedIndex = _modifiedProxyConfig.proxyType;
}
private void OKButton_Click(object sender, EventArgs e)
{
if (UseProxyCheckBox.Checked)
if (_modifiedProxyConfig.useProxy=UseProxyCheckBox.Checked)
{
int port;
int timeout;
if (!int.TryParse(ProxyPortTextBox.Text, out port))
if (!int.TryParse(ProxyPortTextBox.Text, out _modifiedProxyConfig.proxyPort))
{
MessageBox.Show(I18N.GetString("Illegal port number format"));
return;
}
if (!int.TryParse(ProxyTimeoutTextBox.Text, out timeout))
if (!int.TryParse(ProxyTimeoutTextBox.Text, out _modifiedProxyConfig.proxyTimeout))
{
MessageBox.Show(I18N.GetString("Illegal timeout format"));
return;
}
var type = ProxyTypeComboBox.SelectedIndex;
var proxy = ProxyServerTextBox.Text;
_modifiedProxyConfig.proxyType = ProxyTypeComboBox.SelectedIndex;
try
{
Configuration.CheckServer(proxy);
Configuration.CheckPort(port);
Configuration.CheckTimeout(timeout, ProxyConfig.MaxProxyTimeoutSec);
Configuration.CheckServer(_modifiedProxyConfig.proxyServer = ProxyServerTextBox.Text);
Configuration.CheckPort(_modifiedProxyConfig.proxyPort);
Configuration.CheckTimeout(_modifiedProxyConfig.proxyTimeout, ProxyConfig.MaxProxyTimeoutSec);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
return;
}
}
controller.EnableProxy(type, proxy, port, timeout);
}
else
{
controller.DisableProxy();
}
controller.SaveProxy(_modifiedProxyConfig);
this.Close();
}
@@ -119,17 +113,17 @@ namespace Shadowsocks.View
{
if (UseProxyCheckBox.Checked)
{
ProxyServerTextBox.Enabled = true;
ProxyPortTextBox.Enabled = true;
ProxyTimeoutTextBox.Enabled = true;
ProxyServerTextBox.Enabled =
ProxyPortTextBox.Enabled =
ProxyTimeoutTextBox.Enabled =
ProxyTypeComboBox.Enabled = true;
}
else
{
ProxyServerTextBox.Enabled = false;
ProxyPortTextBox.Enabled = false;
ProxyTimeoutTextBox.Enabled = false;
ProxyTypeComboBox.Enabled = false;
ProxyServerTextBox.Enabled =
ProxyPortTextBox.Enabled =
ProxyTimeoutTextBox.Enabled =
ProxyTypeComboBox.Enabled = false;
}
}
}
+45
View File
@@ -39,4 +39,49 @@
</setting>
</Shadowsocks.Properties.Settings>
</userSettings>
<!-- Uncomment to dump network tracing info
<system.diagnostics>
<sources>
<source name="System.Net" tracemode="includehex" maxdatasize="1024">
<listeners>
<add name="System.Net"/>
</listeners>
</source>
<source name="System.Net.Cache">
<listeners>
<add name="System.Net"/>
</listeners>
</source>
<source name="System.Net.Http">
<listeners>
<add name="System.Net"/>
</listeners>
</source>
<source name="System.Net.Sockets">
<listeners>
<add name="System.Net"/>
</listeners>
</source>
<source name="System.Net.WebSockets">
<listeners>
<add name="System.Net"/>
</listeners>
</source>
</sources>
<switches>
<add name="System.Net" value="Verbose"/>
<add name="System.Net.Cache" value="Verbose"/>
<add name="System.Net.Http" value="Verbose"/>
<add name="System.Net.Sockets" value="Verbose"/>
<add name="System.Net.WebSockets" value="Verbose"/>
</switches>
<sharedListeners>
<add name="System.Net"
type="System.Diagnostics.TextWriterTraceListener"
initializeData="network-tracing.log"
/>
</sharedListeners>
<trace autoflush="true"/>
</system.diagnostics>
-->
</configuration>
+5 -5
View File
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Caseless.Fody" version="1.5.0" targetFramework="net462" developmentDependency="true" />
<package id="Costura.Fody" version="1.4.1" targetFramework="net462" developmentDependency="true" />
<package id="Fody" version="2.0.9" targetFramework="net462" developmentDependency="true" />
<package id="Caseless.Fody" version="1.7.3" targetFramework="net462" developmentDependency="true" />
<package id="Costura.Fody" version="1.6.2" targetFramework="net462" developmentDependency="true" />
<package id="Fody" version="2.3.23" targetFramework="net462" developmentDependency="true" />
<package id="GlobalHotKey" version="1.1.0" targetFramework="net462" />
<package id="Newtonsoft.Json" version="10.0.2" targetFramework="net462" />
<package id="Newtonsoft.Json" version="10.0.3" targetFramework="net462" />
<package id="StringEx.CS" version="0.3.1" targetFramework="net462" developmentDependency="true" />
<package id="ZXing.Net" version="0.15.0" targetFramework="net462" />
<package id="ZXing.Net" version="0.16.2" targetFramework="net462" />
</packages>
+20 -8
View File
@@ -66,6 +66,13 @@
<ApplicationManifest>app.manifest</ApplicationManifest>
</PropertyGroup>
<ItemGroup>
<Reference Include="Caseless, Version=0.0.0.0, Culture=neutral, PublicKeyToken=409b3227471b0f0d, processorArchitecture=MSIL">
<HintPath>3rd\Caseless.Fody.1.7.3\lib\net452\Caseless.dll</HintPath>
</Reference>
<Reference Include="Costura, Version=1.6.2.0, Culture=neutral, PublicKeyToken=9919ef960d84173d, processorArchitecture=MSIL">
<HintPath>3rd\Costura.Fody.1.6.2\lib\dotnet\Costura.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="GlobalHotKey, Version=1.1.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>3rd\GlobalHotKey.1.1.0\lib\GlobalHotKey.dll</HintPath>
<Private>True</Private>
@@ -73,7 +80,7 @@
<Reference Include="Microsoft.CSharp" />
<Reference Include="Microsoft.VisualBasic" />
<Reference Include="Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>3rd\Newtonsoft.Json.10.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
<HintPath>3rd\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Data" />
@@ -85,17 +92,18 @@
<Reference Include="System.Windows.Forms.DataVisualization" />
<Reference Include="System.XML" />
<Reference Include="WindowsBase" />
<Reference Include="zxing, Version=0.15.0.0, Culture=neutral, PublicKeyToken=4e88037ac681fe60, processorArchitecture=MSIL">
<HintPath>3rd\ZXing.Net.0.15.0\lib\net461\zxing.dll</HintPath>
<Reference Include="zxing, Version=0.16.2.0, Culture=neutral, PublicKeyToken=4e88037ac681fe60, processorArchitecture=MSIL">
<HintPath>3rd\ZXing.Net.0.16.2\lib\net461\zxing.dll</HintPath>
</Reference>
<Reference Include="zxing.presentation, Version=0.15.0.0, Culture=neutral, PublicKeyToken=4e88037ac681fe60, processorArchitecture=MSIL">
<HintPath>3rd\ZXing.Net.0.15.0\lib\net461\zxing.presentation.dll</HintPath>
<Reference Include="zxing.presentation, Version=0.16.2.0, Culture=neutral, PublicKeyToken=4e88037ac681fe60, processorArchitecture=MSIL">
<HintPath>3rd\ZXing.Net.0.16.2\lib\net461\zxing.presentation.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Controller\System\Hotkeys\HotkeyCallbacks.cs" />
<Compile Include="Encryption\AEAD\AEADEncryptor.cs" />
<Compile Include="Encryption\AEAD\AEADMbedTLSEncryptor.cs" />
<Compile Include="Encryption\AEAD\AEADOpenSSLEncryptor.cs" />
<Compile Include="Encryption\AEAD\AEADSodiumEncryptor.cs" />
<Compile Include="Encryption\CircularBuffer\ByteCircularBuffer.cs" />
<Compile Include="Encryption\EncryptorBase.cs" />
@@ -103,10 +111,12 @@
<Compile Include="Encryption\Exception\CryptoException.cs" />
<Compile Include="Encryption\IEncryptor.cs" />
<Compile Include="Encryption\MbedTLS.cs" />
<Compile Include="Encryption\OpenSSL.cs" />
<Compile Include="Encryption\RNG.cs" />
<Compile Include="Encryption\Sodium.cs" />
<Compile Include="Encryption\Stream\StreamEncryptor.cs" />
<Compile Include="Encryption\Stream\StreamMbedTLSEncryptor.cs" />
<Compile Include="Encryption\Stream\StreamOpenSSLEncryptor.cs" />
<Compile Include="Encryption\Stream\StreamSodiumEncryptor.cs" />
<Compile Include="Model\HotKeyConfig.cs" />
<Compile Include="Model\ProxyConfig.cs" />
@@ -342,13 +352,15 @@ foreach (var item in filesToCleanup)
<Target Name="CleanReferenceCopyLocalPaths" AfterTargets="AfterBuild;NonWinFodyTarget">
<CosturaCleanup Config="FodyWeavers.xml" Files="@(ReferenceCopyLocalPaths->'$(OutDir)%(DestinationSubDirectory)%(Filename)%(Extension)')" />
</Target>
<Import Project="3rd\Fody.2.0.9\build\netstandard1.4\Fody.targets" Condition="Exists('3rd\Fody.2.0.9\build\netstandard1.4\Fody.targets')" />
<Import Project="3rd\Fody.2.3.23\build\Fody.targets" Condition="Exists('3rd\Fody.2.3.23\build\Fody.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>此项目引用这台计算机上缺少的 NuGet 程序包。使用 NuGet 程序包还原可下载这些程序包。有关详细信息,请参阅 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。</ErrorText>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('3rd\Fody.2.0.9\build\netstandard1.4\Fody.targets')" Text="$([System.String]::Format('$(ErrorText)', '3rd\Fody.2.0.9\build\netstandard1.4\Fody.targets'))" />
<Error Condition="!Exists('3rd\Fody.2.3.23\build\Fody.targets')" Text="$([System.String]::Format('$(ErrorText)', '3rd\Fody.2.3.23\build\Fody.targets'))" />
<Error Condition="!Exists('3rd\Costura.Fody.1.6.2\build\dotnet\Costura.Fody.targets')" Text="$([System.String]::Format('$(ErrorText)', '3rd\Costura.Fody.1.6.2\build\dotnet\Costura.Fody.targets'))" />
</Target>
<Import Project="3rd\Costura.Fody.1.6.2\build\dotnet\Costura.Fody.targets" Condition="Exists('3rd\Costura.Fody.1.6.2\build\dotnet\Costura.Fody.targets')" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
+41
View File
@@ -227,6 +227,47 @@ namespace test
}
}
[TestMethod]
public void TestOpenSSLEncryption()
{
// run it once before the multi-threading test to initialize global tables
RunSingleOpenSSLEncryptionThread();
List<Thread> threads = new List<Thread>();
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()
{
try
{
for (int i = 0; i < 100; i++)
{
var random = new Random();
IEncryptor encryptor;
IEncryptor decryptor;
encryptor = new StreamOpenSSLEncryptor("aes-256-cfb", "barfoo!");
decryptor = new StreamOpenSSLEncryptor("aes-256-cfb", "barfoo!");
RunEncryptionRound(encryptor, decryptor);
}
}
catch
{
encryptionFailed = true;
throw;
}
}
[TestMethod]
public void ParseAndGenerateShadowsocksUrl()
{