Compare commits

...
3 Commits
Author SHA1 Message Date
Syrone Wong bbfc5d332d Update CHANGES and bump version
Signed-off-by: Syrone Wong <wong.syrone@gmail.com>
2017-06-01 15:55:55 +08:00
Syrone Wong 5d75e19c26 prefer to use aes-256-gcm in libsodium
which is hardware accelerated compared to AES-GCM in mbedtls

We have to drop this commit when mbedtls support hw-accelerated GCM
when compiling with MSVC

Signed-off-by: Syrone Wong <wong.syrone@gmail.com>
2017-05-31 10:04:00 +08:00
Syrone Wong 816651ebdc Save user wininet settings as another config file 2017-05-25 17:18:20 +08:00
10 changed files with 142 additions and 49 deletions
+4
View File
@@ -1,3 +1,7 @@
4.0.4 2017-06-01
- Save user wininet settings as user-wininet.json
- Improve performance of aes-256-gcm
4.0.2 2017-05-19 4.0.2 2017-05-19
- Fix legacy key derivation - Fix legacy key derivation
- Bug fixes and improvements - Bug fixes and improvements
@@ -24,7 +24,7 @@ namespace Shadowsocks.Controller
public string LatestVersionLocalName; public string LatestVersionLocalName;
public event EventHandler CheckUpdateCompleted; public event EventHandler CheckUpdateCompleted;
public const string Version = "4.0.2"; public const string Version = "4.0.4";
private class CheckUpdateTimer : System.Timers.Timer private class CheckUpdateTimer : System.Timers.Timer
{ {
@@ -44,8 +44,6 @@ namespace Shadowsocks.Controller
private bool stopped = false; private bool stopped = false;
private bool _systemProxyIsDirty = false;
public class PathEventArgs : EventArgs public class PathEventArgs : EventArgs
{ {
public string Path; public string Path;
@@ -510,20 +508,7 @@ namespace Shadowsocks.Controller
private void UpdateSystemProxy() private void UpdateSystemProxy()
{ {
if (_config.enabled) SystemProxy.Update(_config, false, _pacServer);
{
SystemProxy.Update(_config, false, _pacServer);
_systemProxyIsDirty = true;
}
else
{
// only switch it off if we have switched it on
if (_systemProxyIsDirty)
{
SystemProxy.Update(_config, false, _pacServer);
_systemProxyIsDirty = false;
}
}
} }
private void pacServer_PACFileChanged(object sender, EventArgs e) private void pacServer_PACFileChanged(object sender, EventArgs e)
Binary file not shown.
@@ -10,6 +10,7 @@ namespace Shadowsocks.Encryption.AEAD
: AEADEncryptor, IDisposable : AEADEncryptor, IDisposable
{ {
private const int CIPHER_CHACHA20IETFPOLY1305 = 1; private const int CIPHER_CHACHA20IETFPOLY1305 = 1;
private const int CIPHER_AES256GCM = 2;
private byte[] _sodiumEncSubkey; private byte[] _sodiumEncSubkey;
private byte[] _sodiumDecSubkey; private byte[] _sodiumDecSubkey;
@@ -24,6 +25,7 @@ namespace Shadowsocks.Encryption.AEAD
private static Dictionary<string, EncryptorInfo> _ciphers = new Dictionary<string, EncryptorInfo> private static Dictionary<string, EncryptorInfo> _ciphers = new Dictionary<string, EncryptorInfo>
{ {
{"chacha20-ietf-poly1305", new EncryptorInfo(32, 32, 12, 16, CIPHER_CHACHA20IETFPOLY1305)}, {"chacha20-ietf-poly1305", new EncryptorInfo(32, 32, 12, 16, CIPHER_CHACHA20IETFPOLY1305)},
{"aes-256-gcm", new EncryptorInfo(32, 32, 12, 16, CIPHER_AES256GCM)},
}; };
public static List<string> SupportedCiphers() public static List<string> SupportedCiphers()
@@ -63,6 +65,13 @@ namespace Shadowsocks.Encryption.AEAD
null, _encNonce, null, _encNonce,
_sodiumEncSubkey); _sodiumEncSubkey);
break; break;
case CIPHER_AES256GCM:
ret = Sodium.crypto_aead_aes256gcm_encrypt(ciphertext, ref encClen,
plaintext, (ulong)plen,
null, 0,
null, _encNonce,
_sodiumEncSubkey);
break;
default: default:
throw new System.Exception("not implemented"); throw new System.Exception("not implemented");
} }
@@ -91,6 +100,13 @@ namespace Shadowsocks.Encryption.AEAD
null, 0, null, 0,
_decNonce, _sodiumDecSubkey); _decNonce, _sodiumDecSubkey);
break; break;
case CIPHER_AES256GCM:
ret = Sodium.crypto_aead_aes256gcm_decrypt(plaintext, ref decPlen,
null,
ciphertext, (ulong)clen,
null, 0,
_decNonce, _sodiumDecSubkey);
break;
default: default:
throw new System.Exception("not implemented"); throw new System.Exception("not implemented");
} }
@@ -14,6 +14,18 @@ namespace Shadowsocks.Encryption
static EncryptorFactory() 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");
}
foreach (string method in StreamMbedTLSEncryptor.SupportedCiphers()) foreach (string method in StreamMbedTLSEncryptor.SupportedCiphers())
{ {
_registeredEncryptors.Add(method, typeof(StreamMbedTLSEncryptor)); _registeredEncryptors.Add(method, typeof(StreamMbedTLSEncryptor));
@@ -22,11 +34,11 @@ namespace Shadowsocks.Encryption
{ {
_registeredEncryptors.Add(method, typeof(StreamSodiumEncryptor)); _registeredEncryptors.Add(method, typeof(StreamSodiumEncryptor));
} }
foreach (string method in AEADMbedTLSEncryptor.SupportedCiphers()) foreach (string method in AEADMbedTLSEncryptorSupportedCiphers)
{ {
_registeredEncryptors.Add(method, typeof(AEADMbedTLSEncryptor)); _registeredEncryptors.Add(method, typeof(AEADMbedTLSEncryptor));
} }
foreach (string method in AEADSodiumEncryptor.SupportedCiphers()) foreach (string method in AEADSodiumEncryptorSupportedCiphers)
{ {
_registeredEncryptors.Add(method, typeof(AEADSodiumEncryptor)); _registeredEncryptors.Add(method, typeof(AEADSodiumEncryptor));
} }
+16
View File
@@ -14,6 +14,8 @@ namespace Shadowsocks.Encryption
private static bool _initialized = false; private static bool _initialized = false;
private static readonly object _initLock = new object(); private static readonly object _initLock = new object();
public static bool AES256GCMAvailable { get; private set; } = false;
static Sodium() static Sodium()
{ {
string dllPath = Utils.GetTempPath(DLLNAME); string dllPath = Utils.GetTempPath(DLLNAME);
@@ -42,6 +44,9 @@ namespace Shadowsocks.Encryption
{ {
_initialized = true; _initialized = true;
} }
AES256GCMAvailable = crypto_aead_aes256gcm_is_available() == 1;
Logging.Debug($"sodium: AES256GCMAvailable is {AES256GCMAvailable}");
} }
} }
} }
@@ -52,6 +57,9 @@ namespace Shadowsocks.Encryption
[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
private static extern int sodium_init(); private static extern int sodium_init();
[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
private static extern int crypto_aead_aes256gcm_is_available();
#region AEAD #region AEAD
[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
@@ -65,6 +73,14 @@ namespace Shadowsocks.Encryption
public static extern int crypto_aead_chacha20poly1305_ietf_decrypt(byte[] m, ref ulong mlen_p, 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); 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 #endregion
#region Stream #region Stream
@@ -0,0 +1,27 @@
using System;
namespace Shadowsocks.Model
{
/*
* Data come from WinINET
*/
[Serializable]
public class SysproxyConfig
{
public bool UserSettingsRecorded;
public string Flags;
public string ProxyServer;
public string BypassList;
public string PacUrl;
public SysproxyConfig()
{
UserSettingsRecorded = false;
Flags = "1";
ProxyServer = "";
BypassList = "";
PacUrl = "";
}
}
}
+62 -30
View File
@@ -1,15 +1,19 @@
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Text;
using Shadowsocks.Controller; using Shadowsocks.Controller;
using Shadowsocks.Properties; using Shadowsocks.Properties;
using Shadowsocks.Model;
using System.Text;
using Newtonsoft.Json;
namespace Shadowsocks.Util.SystemProxy namespace Shadowsocks.Util.SystemProxy
{ {
public static class Sysproxy public static class Sysproxy
{ {
private static bool _userSettingsRecorded = false; private const string _userWininetConfigFile = "user-wininet.json";
private static string _queryStr;
// In general, this won't change // In general, this won't change
// format: // format:
@@ -17,7 +21,7 @@ namespace Shadowsocks.Util.SystemProxy
// <proxy-server><CR-LF> // <proxy-server><CR-LF>
// <bypass-list><CR-LF> // <bypass-list><CR-LF>
// <pac-url> // <pac-url>
private static string[] _userSettings = new string[4]; private static SysproxyConfig _userSettings = null;
enum RET_ERRORS : int enum RET_ERRORS : int
{ {
@@ -31,8 +35,7 @@ namespace Shadowsocks.Util.SystemProxy
static Sysproxy() static Sysproxy()
{ {
try try {
{
FileManager.UncompressFile(Utils.GetTempPath("sysproxy.exe"), FileManager.UncompressFile(Utils.GetTempPath("sysproxy.exe"),
Environment.Is64BitOperatingSystem ? Resources.sysproxy64_exe : Resources.sysproxy_exe); Environment.Is64BitOperatingSystem ? Resources.sysproxy64_exe : Resources.sysproxy_exe);
} }
@@ -44,13 +47,12 @@ namespace Shadowsocks.Util.SystemProxy
public static void SetIEProxy(bool enable, bool global, string proxyServer, string pacURL) public static void SetIEProxy(bool enable, bool global, string proxyServer, string pacURL)
{ {
string str; Read();
if (_userSettingsRecorded == false) if (!_userSettings.UserSettingsRecorded)
{ {
// record user settings // record user settings
ExecSysproxy("query", out str); ExecSysproxy("query");
ParseQueryStr(str); ParseQueryStr(_queryStr);
_userSettingsRecorded = true;
} }
string arguments; string arguments;
@@ -63,20 +65,21 @@ namespace Shadowsocks.Util.SystemProxy
else else
{ {
// restore user settings // restore user settings
var flags = _userSettings[0]; var flags = _userSettings.Flags;
var proxy_server = _userSettings[1] ?? "-"; var proxy_server = _userSettings.ProxyServer ?? "-";
var bypass_list = _userSettings[2] ?? "-"; var bypass_list = _userSettings.BypassList ?? "-";
var pac_url = _userSettings[3] ?? "-"; var pac_url = _userSettings.PacUrl ?? "-";
arguments = $"set {flags} {proxy_server} {bypass_list} {pac_url}"; arguments = $"set {flags} {proxy_server} {bypass_list} {pac_url}";
// have to get new settings // have to get new settings
_userSettingsRecorded = false; _userSettings.UserSettingsRecorded = false;
} }
ExecSysproxy(arguments, out str); Save();
ExecSysproxy(arguments);
} }
private static void ExecSysproxy(string arguments, out string queryStr) private static void ExecSysproxy(string arguments)
{ {
using (var process = new Process()) using (var process = new Process())
{ {
@@ -107,24 +110,53 @@ namespace Shadowsocks.Util.SystemProxy
throw new ProxyException(stderr); throw new ProxyException(stderr);
} }
if (arguments == "query" && stdout.IsNullOrWhiteSpace()) if (arguments == "query") {
{ if (stdout.IsNullOrWhiteSpace() || stdout.IsNullOrEmpty()) {
// we cannot get user settings // we cannot get user settings
throw new ProxyException("failed to query wininet settings"); throw new ProxyException("failed to query wininet settings");
}
_queryStr = stdout;
} }
queryStr = stdout; }
}
private static void Save()
{
try {
using (StreamWriter sw = new StreamWriter(File.Open(_userWininetConfigFile, FileMode.Create))) {
string jsonString = JsonConvert.SerializeObject(_userSettings, Formatting.Indented);
sw.Write(jsonString);
sw.Flush();
}
} catch (IOException e) {
Logging.LogUsefulException(e);
}
}
private static void Read()
{
try {
string configContent = File.ReadAllText(_userWininetConfigFile);
_userSettings = JsonConvert.DeserializeObject<SysproxyConfig>(configContent);
} catch (FileNotFoundException) {
_userSettings = new SysproxyConfig();
} }
} }
private static void ParseQueryStr(string str) private static void ParseQueryStr(string str)
{ {
_userSettings = str.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries); string[] userSettingsArr = str.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
for (var i = 0; i < 4; i++) _userSettings.Flags = userSettingsArr[0];
{
// handle output from WinINET // handle output from WinINET
if (_userSettings[i] == "(null)") if (userSettingsArr[1] == "(null)") _userSettings.ProxyServer = null;
_userSettings[i] = null; else _userSettings.ProxyServer = userSettingsArr[1];
} if (userSettingsArr[2] == "(null)") _userSettings.BypassList = null;
else _userSettings.BypassList = userSettingsArr[2];
if (userSettingsArr[3] == "(null)") _userSettings.PacUrl = null;
else _userSettings.PacUrl = userSettingsArr[3];
_userSettings.UserSettingsRecorded = true;
} }
} }
} }
@@ -110,6 +110,7 @@
<Compile Include="Encryption\Stream\StreamSodiumEncryptor.cs" /> <Compile Include="Encryption\Stream\StreamSodiumEncryptor.cs" />
<Compile Include="Model\HotKeyConfig.cs" /> <Compile Include="Model\HotKeyConfig.cs" />
<Compile Include="Model\ProxyConfig.cs" /> <Compile Include="Model\ProxyConfig.cs" />
<Compile Include="Model\SysproxyConfig.cs" />
<Compile Include="Properties\Settings.Designer.cs"> <Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen> <AutoGen>True</AutoGen>
<DesignTimeSharedInput>True</DesignTimeSharedInput> <DesignTimeSharedInput>True</DesignTimeSharedInput>