| @@ -1,12 +1,366 @@ | |||
| /.vs/ | |||
| Backup/ | |||
| bin/ | |||
| obj/ | |||
| shadowsocks-csharp/shadowsocks-csharp.csproj.user | |||
| TestResults | |||
| ## Ignore Visual Studio and VSCode temporary files, build results, and | |||
| ## files generated by popular Visual Studio add-ons. | |||
| ## | |||
| ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore | |||
| ## and https://github.com/github/gitignore/blob/master/Global/VisualStudioCode.gitignore | |||
| # User-specific files | |||
| *.rsuser | |||
| *.suo | |||
| *.user | |||
| *.userosscache | |||
| *.sln.docstates | |||
| # User-specific files (MonoDevelop/Xamarin Studio) | |||
| *.userprefs | |||
| # Mono auto generated files | |||
| mono_crash.* | |||
| # Build results | |||
| [Dd]ebug/ | |||
| [Dd]ebugPublic/ | |||
| [Rr]elease/ | |||
| [Rr]eleases/ | |||
| x64/ | |||
| x86/ | |||
| [Ww][Ii][Nn]32/ | |||
| [Aa][Rr][Mm]/ | |||
| [Aa][Rr][Mm]64/ | |||
| bld/ | |||
| [Bb]in/ | |||
| [Oo]bj/ | |||
| [Ll]og/ | |||
| [Ll]ogs/ | |||
| # Visual Studio 2015/2017 cache/options directory | |||
| .vs/ | |||
| # Uncomment if you have tasks that create the project's static files in wwwroot | |||
| #wwwroot/ | |||
| # Visual Studio 2017 auto generated files | |||
| Generated\ Files/ | |||
| # MSTest test Results | |||
| [Tt]est[Rr]esult*/ | |||
| [Bb]uild[Ll]og.* | |||
| # NUnit | |||
| *.VisualState.xml | |||
| TestResult.xml | |||
| nunit-*.xml | |||
| # Build Results of an ATL Project | |||
| [Dd]ebugPS/ | |||
| [Rr]eleasePS/ | |||
| dlldata.c | |||
| # Benchmark Results | |||
| BenchmarkDotNet.Artifacts/ | |||
| # .NET Core | |||
| project.lock.json | |||
| project.fragment.lock.json | |||
| artifacts/ | |||
| # ASP.NET Scaffolding | |||
| ScaffoldingReadMe.txt | |||
| # StyleCop | |||
| StyleCopReport.xml | |||
| # Files built by Visual Studio | |||
| *_i.c | |||
| *_p.c | |||
| *_h.h | |||
| *.ilk | |||
| *.meta | |||
| *.obj | |||
| *.iobj | |||
| *.pch | |||
| *.pdb | |||
| *.ipdb | |||
| *.pgc | |||
| *.pgd | |||
| *.rsp | |||
| *.sbr | |||
| *.tlb | |||
| *.tli | |||
| *.tlh | |||
| *.tmp | |||
| *.tmp_proj | |||
| *_wpftmp.csproj | |||
| *.log | |||
| *.vspscc | |||
| *.vssscc | |||
| .builds | |||
| *.pidb | |||
| *.svclog | |||
| *.scc | |||
| # Chutzpah Test files | |||
| _Chutzpah* | |||
| # Visual C++ cache files | |||
| ipch/ | |||
| *.aps | |||
| *.ncb | |||
| *.opendb | |||
| *.opensdf | |||
| *.sdf | |||
| *.cachefile | |||
| *.VC.db | |||
| *.VC.VC.opendb | |||
| # Visual Studio profiler | |||
| *.psess | |||
| *.vsp | |||
| *.vspx | |||
| *.sap | |||
| # Visual Studio Trace Files | |||
| *.e2e | |||
| # TFS 2012 Local Workspace | |||
| $tf/ | |||
| # Guidance Automation Toolkit | |||
| *.gpState | |||
| # ReSharper is a .NET coding add-in | |||
| _ReSharper*/ | |||
| *.[Rr]e[Ss]harper | |||
| *.DotSettings.user | |||
| # TeamCity is a build add-in | |||
| _TeamCity* | |||
| # DotCover is a Code Coverage Tool | |||
| *.dotCover | |||
| # AxoCover is a Code Coverage Tool | |||
| .axoCover/* | |||
| !.axoCover/settings.json | |||
| # Coverlet is a free, cross platform Code Coverage Tool | |||
| coverage*[.json, .xml, .info] | |||
| # Visual Studio code coverage results | |||
| *.coverage | |||
| *.coveragexml | |||
| # NCrunch | |||
| _NCrunch_* | |||
| .*crunch*.local.xml | |||
| nCrunchTemp_* | |||
| # MightyMoose | |||
| *.mm.* | |||
| AutoTest.Net/ | |||
| # Web workbench (sass) | |||
| .sass-cache/ | |||
| # Installshield output folder | |||
| [Ee]xpress/ | |||
| # DocProject is a documentation generator add-in | |||
| DocProject/buildhelp/ | |||
| DocProject/Help/*.HxT | |||
| DocProject/Help/*.HxC | |||
| DocProject/Help/*.hhc | |||
| DocProject/Help/*.hhk | |||
| DocProject/Help/*.hhp | |||
| DocProject/Help/Html2 | |||
| DocProject/Help/html | |||
| # Click-Once directory | |||
| publish/ | |||
| # Publish Web Output | |||
| *.[Pp]ublish.xml | |||
| *.azurePubxml | |||
| # Note: Comment the next line if you want to checkin your web deploy settings, | |||
| # but database connection strings (with potential passwords) will be unencrypted | |||
| # *.pubxml | |||
| *.publishproj | |||
| # Microsoft Azure Web App publish settings. Comment the next line if you want to | |||
| # checkin your Azure Web App publish settings, but sensitive information contained | |||
| # in these scripts will be unencrypted | |||
| PublishScripts/ | |||
| # NuGet Packages | |||
| *.nupkg | |||
| # NuGet Symbol Packages | |||
| *.snupkg | |||
| # The packages folder can be ignored because of Package Restore | |||
| **/[Pp]ackages/* | |||
| # except build/, which is used as an MSBuild target. | |||
| !**/[Pp]ackages/build/ | |||
| # Uncomment if necessary however generally it will be regenerated when needed | |||
| #!**/[Pp]ackages/repositories.config | |||
| # NuGet v3's project.json files produces more ignorable files | |||
| *.nuget.props | |||
| *.nuget.targets | |||
| # Microsoft Azure Build Output | |||
| csx/ | |||
| *.build.csdef | |||
| # Microsoft Azure Emulator | |||
| ecf/ | |||
| rcf/ | |||
| # Windows Store app package directories and files | |||
| AppPackages/ | |||
| BundleArtifacts/ | |||
| Package.StoreAssociation.xml | |||
| _pkginfo.txt | |||
| *.appx | |||
| *.appxbundle | |||
| *.appxupload | |||
| # Visual Studio cache files | |||
| # files ending in .cache can be ignored | |||
| *.[Cc]ache | |||
| # but keep track of directories ending in .cache | |||
| !?*.[Cc]ache/ | |||
| # Others | |||
| ClientBin/ | |||
| ~$* | |||
| *~ | |||
| *.dbmdl | |||
| *.dbproj.schemaview | |||
| *.jfm | |||
| *.pfx | |||
| *.publishsettings | |||
| orleans.codegen.cs | |||
| # Including strong name files can present a security risk | |||
| # (https://github.com/github/gitignore/pull/2483#issue-259490424) | |||
| #*.snk | |||
| # Since there are multiple workflows, uncomment next line to ignore bower_components | |||
| # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) | |||
| #bower_components/ | |||
| # RIA/Silverlight projects | |||
| Generated_Code/ | |||
| # Backup & report files from converting an old project file | |||
| # to a newer Visual Studio version. Backup files are not needed, | |||
| # because we have git ;-) | |||
| _UpgradeReport_Files/ | |||
| Backup*/ | |||
| UpgradeLog*.XML | |||
| UpgradeLog*.htm | |||
| ServiceFabricBackup/ | |||
| *.rptproj.bak | |||
| # SQL Server files | |||
| *.mdf | |||
| *.ldf | |||
| *.ndf | |||
| # Business Intelligence projects | |||
| *.rdl.data | |||
| *.bim.layout | |||
| *.bim_*.settings | |||
| *.rptproj.rsuser | |||
| *- [Bb]ackup.rdl | |||
| *- [Bb]ackup ([0-9]).rdl | |||
| *- [Bb]ackup ([0-9][0-9]).rdl | |||
| # Microsoft Fakes | |||
| FakesAssemblies/ | |||
| # GhostDoc plugin setting file | |||
| *.GhostDoc.xml | |||
| # Node.js Tools for Visual Studio | |||
| .ntvs_analysis.dat | |||
| node_modules/ | |||
| # Visual Studio 6 build log | |||
| *.plg | |||
| # Visual Studio 6 workspace options file | |||
| *.opt | |||
| # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) | |||
| *.vbw | |||
| # Visual Studio LightSwitch build output | |||
| **/*.HTMLClient/GeneratedArtifacts | |||
| **/*.DesktopClient/GeneratedArtifacts | |||
| **/*.DesktopClient/ModelManifest.xml | |||
| **/*.Server/GeneratedArtifacts | |||
| **/*.Server/ModelManifest.xml | |||
| _Pvt_Extensions | |||
| # Paket dependency manager | |||
| .paket/paket.exe | |||
| paket-files/ | |||
| # FAKE - F# Make | |||
| .fake/ | |||
| # CodeRush personal settings | |||
| .cr/personal | |||
| # Python Tools for Visual Studio (PTVS) | |||
| __pycache__/ | |||
| *.pyc | |||
| # Cake - Uncomment if you are using it | |||
| # tools/** | |||
| # !tools/packages.config | |||
| # Tabs Studio | |||
| *.tss | |||
| # Telerik's JustMock configuration file | |||
| *.jmconfig | |||
| # BizTalk build output | |||
| *.btp.cs | |||
| *.btm.cs | |||
| *.odx.cs | |||
| *.xsd.cs | |||
| # OpenCover UI analysis results | |||
| OpenCover/ | |||
| # Azure Stream Analytics local run output | |||
| ASALocalRun/ | |||
| # MSBuild Binary and Structured Log | |||
| *.binlog | |||
| # NVidia Nsight GPU debugger configuration file | |||
| *.nvuser | |||
| # MFractors (Xamarin productivity tool) working folder | |||
| .mfractor/ | |||
| # Local History for Visual Studio | |||
| .localhistory/ | |||
| # BeatPulse healthcheck temp database | |||
| healthchecksdb | |||
| # Backup folder for Package Reference Convert tool in Visual Studio 2017 | |||
| MigrationBackup/ | |||
| shadowsocks-csharp/3rd/* | |||
| packages/* | |||
| # Ionide (cross platform F# VS Code tools) working folder | |||
| .ionide/ | |||
| shadowsocks-csharp.sln.DotSettings.user | |||
| # VSCode | |||
| .vscode/* | |||
| !.vscode/settings.json | |||
| !.vscode/tasks.json | |||
| !.vscode/launch.json | |||
| !.vscode/extensions.json | |||
| *.code-workspace | |||
| @@ -1,3 +1,16 @@ | |||
| 4.4.1.0 2022-02-08 | |||
| - Add plain/none ciphers | |||
| 4.4.0.0 2021-01-01 | |||
| - Security: remove infrastructure of stream ciphers (#3048) | |||
| - Show warning message when importing from deprecated legacy ss:// links. | |||
| - Other minor bug fixes and improvements | |||
| 4.3.3.0 2020-12-07 | |||
| - PAC: Add option for custom sha256sum URL of custom geosite source (#3026) | |||
| - Update to .NET Framework 4.8 | |||
| - Other minor bug fixes and improvements | |||
| 4.3.2.0 2020-11-05 | |||
| - PAC: direct connection for private IP ranges by @studentmain (#3008) | |||
| - Remove duplicate startup entries (#3012) | |||
| @@ -21,7 +21,7 @@ Download the latest release from [release page]. | |||
| ## Requirements | |||
| Microsoft [.NET Framework 4.7.2] or higher, Microsoft [Visual C++ 2015 Redistributable] (x86) . | |||
| .NET Framework 4.8 or higher, Microsoft [Visual C++ 2015 Redistributable] (x86) . | |||
| ## Basics | |||
| @@ -127,7 +127,7 @@ Please visit [Servers] for more information. | |||
| ## Development | |||
| 1. [Visual Studio 2019] & [.NET Framework 4.7.2 Developer Pack] are required. | |||
| 1. Visual Studio 2019 & .NET Framework 4.8 SDK are required. | |||
| 2. It is recommended to share your idea on the Issue Board before you start to work, | |||
| especially for feature development. | |||
| @@ -164,9 +164,6 @@ Sysproxy () https://github.com/Noisyfox/sysproxy | |||
| [GeoSite]: https://github.com/v2fly/domain-list-community | |||
| [Servers]: https://github.com/shadowsocks/shadowsocks/wiki/Ports-and-Clients#linux--server-side | |||
| [中文说明]: https://github.com/shadowsocks/shadowsocks-windows/wiki/Shadowsocks-Windows-%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E | |||
| [Visual Studio 2017]: https://www.visualstudio.com/downloads/ | |||
| [.NET Framework 4.7.2]: https://dotnet.microsoft.com/download/dotnet-framework/net472 | |||
| [.NET Framework 4.7.2 Developer Pack]: https://dotnet.microsoft.com/download/dotnet-framework/net472 | |||
| [Visual C++ 2015 Redistributable]: https://www.microsoft.com/en-us/download/details.aspx?id=53840 | |||
| [GPLv3]: https://github.com/shadowsocks/shadowsocks-windows/blob/master/LICENSE.txt | |||
| [Working with non SIP003 standard Plugin]: https://github.com/shadowsocks/shadowsocks-windows/wiki/Working-with-non-SIP003-standard-Plugin | |||
| @@ -11,7 +11,7 @@ | |||
| # version format | |||
| # Build version format is taken from UI if it is not set | |||
| version: 4.3.2.{build} | |||
| version: 4.4.1.{build} | |||
| # # branches to build | |||
| # branches: | |||
| @@ -75,52 +75,68 @@ namespace Shadowsocks.Controller | |||
| public static async Task UpdatePACFromGeosite() | |||
| { | |||
| string geositeUrl = GEOSITE_URL; | |||
| string geositeSha256sumUrl = GEOSITE_SHA256SUM_URL; | |||
| SHA256 mySHA256 = SHA256.Create(); | |||
| var geositeUrl = GEOSITE_URL; | |||
| var geositeSha256sumUrl = GEOSITE_SHA256SUM_URL; | |||
| var geositeVerifySha256 = true; | |||
| var geositeSha256sum = ""; | |||
| var mySHA256 = SHA256.Create(); | |||
| var config = Program.MainController.GetCurrentConfiguration(); | |||
| bool blacklist = config.geositePreferDirect; | |||
| var blacklist = config.geositePreferDirect; | |||
| var httpClient = Program.MainController.GetHttpClient(); | |||
| if (!string.IsNullOrWhiteSpace(config.geositeUrl)) | |||
| { | |||
| logger.Info("Found custom Geosite URL in config file"); | |||
| geositeUrl = config.geositeUrl; | |||
| geositeSha256sumUrl = config.geositeSha256sumUrl; | |||
| if (string.IsNullOrWhiteSpace(geositeSha256sumUrl)) | |||
| { | |||
| geositeVerifySha256 = false; | |||
| logger.Info("Geosite SHA256 verification is disabled."); | |||
| } | |||
| } | |||
| logger.Info($"Checking Geosite from {geositeUrl}"); | |||
| try | |||
| { | |||
| // download checksum first | |||
| var geositeSha256sum = await httpClient.GetStringAsync(geositeSha256sumUrl); | |||
| geositeSha256sum = geositeSha256sum.Substring(0, 64).ToUpper(); | |||
| logger.Info($"Got Sha256sum: {geositeSha256sum}"); | |||
| // compare downloaded checksum with local geositeDB | |||
| byte[] localDBHashBytes = mySHA256.ComputeHash(geositeDB); | |||
| string localDBHash = BitConverter.ToString(localDBHashBytes).Replace("-", String.Empty); | |||
| logger.Info($"Local Sha256sum: {localDBHash}"); | |||
| // if already latest | |||
| if (geositeSha256sum == localDBHash) | |||
| // Use sha256sum to check if local database is already latest. | |||
| if (geositeVerifySha256) | |||
| { | |||
| logger.Info("Local GeoSite DB is up to date."); | |||
| return; | |||
| // download checksum first | |||
| geositeSha256sum = await httpClient.GetStringAsync(geositeSha256sumUrl); | |||
| geositeSha256sum = geositeSha256sum.Substring(0, 64).ToUpper(); | |||
| logger.Info($"Got Sha256sum: {geositeSha256sum}"); | |||
| // compare downloaded checksum with local geositeDB | |||
| byte[] localDBHashBytes = mySHA256.ComputeHash(geositeDB); | |||
| string localDBHash = BitConverter.ToString(localDBHashBytes).Replace("-", String.Empty); | |||
| logger.Info($"Local Sha256sum: {localDBHash}"); | |||
| // if already latest | |||
| if (geositeSha256sum == localDBHash) | |||
| { | |||
| logger.Info("Local GeoSite DB is up to date."); | |||
| UpdateCompleted?.Invoke(null, new GeositeResultEventArgs(false)); | |||
| return; | |||
| } | |||
| } | |||
| // not latest. download new DB | |||
| var downloadedBytes = await httpClient.GetByteArrayAsync(geositeUrl); | |||
| // verify sha256sum | |||
| byte[] downloadedDBHashBytes = mySHA256.ComputeHash(downloadedBytes); | |||
| string downloadedDBHash = BitConverter.ToString(downloadedDBHashBytes).Replace("-", String.Empty); | |||
| logger.Info($"Actual Sha256sum: {downloadedDBHash}"); | |||
| if (geositeSha256sum != downloadedDBHash) | |||
| { | |||
| logger.Info("Sha256sum Verification: FAILED. Downloaded GeoSite DB is corrupted. Aborting the update."); | |||
| throw new Exception("Sha256sum mismatch"); | |||
| } | |||
| else | |||
| if (geositeVerifySha256) | |||
| { | |||
| logger.Info("Sha256sum Verification: PASSED. Applying to local GeoSite DB."); | |||
| byte[] downloadedDBHashBytes = mySHA256.ComputeHash(downloadedBytes); | |||
| string downloadedDBHash = BitConverter.ToString(downloadedDBHashBytes).Replace("-", String.Empty); | |||
| logger.Info($"Actual Sha256sum: {downloadedDBHash}"); | |||
| if (geositeSha256sum != downloadedDBHash) | |||
| { | |||
| logger.Info("Sha256sum Verification: FAILED. Downloaded GeoSite DB is corrupted. Aborting the update."); | |||
| throw new Exception("Sha256sum mismatch"); | |||
| } | |||
| else | |||
| { | |||
| logger.Info("Sha256sum Verification: PASSED. Applying to local GeoSite DB."); | |||
| } | |||
| } | |||
| // write to geosite file | |||
| @@ -33,7 +33,7 @@ namespace Shadowsocks.Controller | |||
| public event EventHandler CheckUpdateCompleted; | |||
| public const string Version = "4.3.2.0"; | |||
| public const string Version = "4.4.1.0"; | |||
| private readonly Version _version; | |||
| public UpdateChecker() | |||
| @@ -450,6 +450,8 @@ namespace Shadowsocks.Controller | |||
| foreach (var server in servers) | |||
| { | |||
| _config.configs.Add(server); | |||
| if (server.warnLegacyUrl) | |||
| MessageBox.Show(I18N.GetString("Warning: importing {0} from a legacy ss:// link. Support for legacy ss:// links will be dropped in version 5. Make sure to update your ss:// links.", server.ToString())); | |||
| } | |||
| _config.index = _config.configs.Count - 1; | |||
| SaveConfig(_config); | |||
| @@ -133,6 +133,7 @@ Failed to update registry,Не удалось обновить запись в | |||
| Import from URL: {0} ?,импортировать из адреса: {0} ?,从URL导入: {0} ?,從URL匯入: {0} ?,{0}:このURLからインポートしますか?,, | |||
| Successfully imported from {0},Успешно импортировано из {0},导入成功:{0},導入成功:{0},{0}:インポートしました。,, | |||
| Failed to import. Please check if the link is valid.,,导入失败,请检查链接是否有效。,導入失敗,請檢查鏈接是否有效。,インポートに失敗しました。リンクの有効性を確認してください。,, | |||
| Warning: importing {0} from a legacy ss:// link. Support for legacy ss:// links will be dropped in version 5. Make sure to update your ss:// links.,,警告: 正在从旧版 ss:// 链接导入 {0}。对旧版 ss:// 链接的支持将于 v5 移除,请及时更新你的链接。,,,, | |||
| System Proxy On: ,Системный прокси:,系统代理已启用:,系統 Proxy 已啟用:,システム プロキシが有効:,시스템 프록시 활성화됨: ,Proxy système activé: | |||
| Running: Port {0},Запущен на порту {0},正在运行:端口 {0},正在執行:連接埠號碼 {0},実行中:ポート {0},실행 중: 포트 {0}번,En cours d'exécution: port {0} | |||
| "Unexpected error, shadowsocks will exit. Please report to","Непредвиденная ошибка, пожалуйста сообщите на",非预期错误,Shadowsocks将退出。请提交此错误到,非預期錯誤,Shadowsocks 將結束。請報告此錯誤至,予想外のエラーが発生したため、Shadowsocks を終了します。詳しくは下記までお問い合わせ下さい:,알 수 없는 오류로 Shadowsocks가 종료될 것입니다. 오류를 여기로 제보해주세요:,Shadowsocks va quitter en présence d/érreur inattendue. Veuillez signaler à | |||
| @@ -7,7 +7,6 @@ using System.Text; | |||
| using Shadowsocks.Encryption.CircularBuffer; | |||
| using Shadowsocks.Controller; | |||
| using Shadowsocks.Encryption.Exception; | |||
| using Shadowsocks.Encryption.Stream; | |||
| namespace Shadowsocks.Encryption.AEAD | |||
| { | |||
| @@ -98,7 +97,24 @@ namespace Shadowsocks.Encryption.AEAD | |||
| public void DeriveKey(byte[] password, byte[] key, int keylen) | |||
| { | |||
| StreamEncryptor.LegacyDeriveKey(password, key, keylen); | |||
| byte[] result = new byte[password.Length + MD5_LEN]; | |||
| int i = 0; | |||
| byte[] md5sum = null; | |||
| while (i < keylen) | |||
| { | |||
| if (i == 0) | |||
| { | |||
| md5sum = MbedTLS.MD5(password); | |||
| } | |||
| else | |||
| { | |||
| Array.Copy(md5sum, 0, result, 0, MD5_LEN); | |||
| Array.Copy(password, 0, result, MD5_LEN, password.Length); | |||
| md5sum = MbedTLS.MD5(result); | |||
| } | |||
| Array.Copy(md5sum, 0, key, i, Math.Min(MD5_LEN, keylen - i)); | |||
| i += MD5_LEN; | |||
| } | |||
| } | |||
| public void DeriveSessionKey(byte[] salt, byte[] masterKey, byte[] sessionKey) | |||
| @@ -17,6 +17,8 @@ namespace Shadowsocks.Encryption | |||
| { | |||
| var AEADMbedTLSEncryptorSupportedCiphers = AEADMbedTLSEncryptor.SupportedCiphers(); | |||
| var AEADSodiumEncryptorSupportedCiphers = AEADSodiumEncryptor.SupportedCiphers(); | |||
| var PlainEncryptorSupportedCiphers = PlainEncryptor.SupportedCiphers(); | |||
| if (Sodium.AES256GCMAvailable) | |||
| { | |||
| // prefer to aes-256-gcm in libsodium | |||
| @@ -27,26 +29,6 @@ namespace Shadowsocks.Encryption | |||
| AEADSodiumEncryptorSupportedCiphers.Remove("aes-256-gcm"); | |||
| } | |||
| // XXX: sequence matters, OpenSSL > Sodium > MbedTLS | |||
| foreach (string method in StreamOpenSSLEncryptor.SupportedCiphers()) | |||
| { | |||
| if (!_registeredEncryptors.ContainsKey(method)) | |||
| _registeredEncryptors.Add(method, typeof(StreamOpenSSLEncryptor)); | |||
| } | |||
| foreach (string method in StreamSodiumEncryptor.SupportedCiphers()) | |||
| { | |||
| if (!_registeredEncryptors.ContainsKey(method)) | |||
| _registeredEncryptors.Add(method, typeof(StreamSodiumEncryptor)); | |||
| } | |||
| foreach (string method in StreamMbedTLSEncryptor.SupportedCiphers()) | |||
| { | |||
| if (!_registeredEncryptors.ContainsKey(method)) | |||
| _registeredEncryptors.Add(method, typeof(StreamMbedTLSEncryptor)); | |||
| } | |||
| foreach (string method in AEADOpenSSLEncryptor.SupportedCiphers()) | |||
| { | |||
| if (!_registeredEncryptors.ContainsKey(method)) | |||
| @@ -64,6 +46,12 @@ namespace Shadowsocks.Encryption | |||
| if (!_registeredEncryptors.ContainsKey(method)) | |||
| _registeredEncryptors.Add(method, typeof(AEADMbedTLSEncryptor)); | |||
| } | |||
| foreach (string method in PlainEncryptorSupportedCiphers) | |||
| { | |||
| if (!_registeredEncryptors.ContainsKey(method)) | |||
| _registeredEncryptors.Add(method, typeof(PlainEncryptor)); | |||
| } | |||
| } | |||
| public static IEncryptor GetEncryptor(string method, string password) | |||
| @@ -97,4 +85,4 @@ namespace Shadowsocks.Encryption | |||
| return sb.ToString(); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,98 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| namespace Shadowsocks.Encryption.Stream | |||
| { | |||
| class PlainEncryptor | |||
| : EncryptorBase, IDisposable | |||
| { | |||
| const int CIPHER_NONE = 1; | |||
| private static Dictionary<string, EncryptorInfo> _ciphers = new Dictionary<string, EncryptorInfo> { | |||
| { "plain", new EncryptorInfo("PLAIN", 0, 0, CIPHER_NONE) }, | |||
| { "none", new EncryptorInfo("PLAIN", 0, 0, CIPHER_NONE) } | |||
| }; | |||
| public PlainEncryptor(string method, string password) : base(method, password) | |||
| { | |||
| } | |||
| public static List<string> SupportedCiphers() | |||
| { | |||
| return new List<string>(_ciphers.Keys); | |||
| } | |||
| protected Dictionary<string, EncryptorInfo> getCiphers() | |||
| { | |||
| return _ciphers; | |||
| } | |||
| #region TCP | |||
| public override void Encrypt(byte[] buf, int length, byte[] outbuf, out int outlength) | |||
| { | |||
| Buffer.BlockCopy(buf, 0, outbuf, 0, length); | |||
| outlength = length; | |||
| } | |||
| public override void Decrypt(byte[] buf, int length, byte[] outbuf, out int outlength) | |||
| { | |||
| Buffer.BlockCopy(buf, 0, outbuf, 0, length); | |||
| outlength = length; | |||
| } | |||
| #endregion | |||
| #region UDP | |||
| public override void EncryptUDP(byte[] buf, int length, byte[] outbuf, out int outlength) | |||
| { | |||
| Buffer.BlockCopy(buf, 0, outbuf, 0, length); | |||
| outlength = length; | |||
| } | |||
| public override void DecryptUDP(byte[] buf, int length, byte[] outbuf, out int outlength) | |||
| { | |||
| Buffer.BlockCopy(buf, 0, outbuf, 0, length); | |||
| outlength = length; | |||
| } | |||
| #endregion | |||
| #region IDisposable | |||
| private bool _disposed; | |||
| // instance based lock | |||
| private readonly object _lock = new object(); | |||
| public override void Dispose() | |||
| { | |||
| Dispose(true); | |||
| GC.SuppressFinalize(this); | |||
| } | |||
| ~PlainEncryptor() | |||
| { | |||
| Dispose(false); | |||
| } | |||
| protected virtual void Dispose(bool disposing) | |||
| { | |||
| lock (_lock) | |||
| { | |||
| if (_disposed) return; | |||
| _disposed = true; | |||
| } | |||
| if (disposing) | |||
| { | |||
| // free managed objects | |||
| } | |||
| } | |||
| #endregion | |||
| } | |||
| } | |||
| @@ -1,182 +0,0 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Diagnostics; | |||
| using System.Text; | |||
| using Shadowsocks.Encryption.CircularBuffer; | |||
| using Shadowsocks.Controller; | |||
| namespace Shadowsocks.Encryption.Stream | |||
| { | |||
| public abstract class StreamEncryptor | |||
| : EncryptorBase | |||
| { | |||
| // for UDP only | |||
| protected static byte[] _udpTmpBuf = new byte[65536]; | |||
| // every connection should create its own buffer | |||
| private ByteCircularBuffer _encCircularBuffer = new ByteCircularBuffer(TCPHandler.BufferSize * 2); | |||
| private ByteCircularBuffer _decCircularBuffer = new ByteCircularBuffer(TCPHandler.BufferSize * 2); | |||
| protected Dictionary<string, EncryptorInfo> ciphers; | |||
| protected byte[] _encryptIV; | |||
| protected byte[] _decryptIV; | |||
| // Is first packet | |||
| protected bool _decryptIVReceived; | |||
| protected bool _encryptIVSent; | |||
| protected string _method; | |||
| protected int _cipher; | |||
| // internal name in the crypto library | |||
| protected string _innerLibName; | |||
| protected EncryptorInfo CipherInfo; | |||
| // long-time master key | |||
| protected static byte[] _key = null; | |||
| protected int keyLen; | |||
| protected int ivLen; | |||
| public StreamEncryptor(string method, string password) | |||
| : base(method, password) | |||
| { | |||
| InitEncryptorInfo(method); | |||
| InitKey(password); | |||
| } | |||
| protected abstract Dictionary<string, EncryptorInfo> getCiphers(); | |||
| private void InitEncryptorInfo(string method) | |||
| { | |||
| method = method.ToLower(); | |||
| _method = method; | |||
| ciphers = getCiphers(); | |||
| CipherInfo = ciphers[_method]; | |||
| _innerLibName = CipherInfo.InnerLibName; | |||
| _cipher = CipherInfo.Type; | |||
| if (_cipher == 0) { | |||
| throw new System.Exception("method not found"); | |||
| } | |||
| keyLen = CipherInfo.KeySize; | |||
| ivLen = CipherInfo.IvSize; | |||
| } | |||
| private void InitKey(string password) | |||
| { | |||
| byte[] passbuf = Encoding.UTF8.GetBytes(password); | |||
| if (_key == null) _key = new byte[keyLen]; | |||
| if (_key.Length != keyLen) Array.Resize(ref _key, keyLen); | |||
| LegacyDeriveKey(passbuf, _key, keyLen); | |||
| } | |||
| public static void LegacyDeriveKey(byte[] password, byte[] key, int keylen) | |||
| { | |||
| byte[] result = new byte[password.Length + MD5_LEN]; | |||
| int i = 0; | |||
| byte[] md5sum = null; | |||
| while (i < keylen) { | |||
| if (i == 0) { | |||
| md5sum = MbedTLS.MD5(password); | |||
| } else { | |||
| Array.Copy(md5sum, 0, result, 0, MD5_LEN); | |||
| Array.Copy(password, 0, result, MD5_LEN, password.Length); | |||
| md5sum = MbedTLS.MD5(result); | |||
| } | |||
| Array.Copy(md5sum, 0, key, i, Math.Min(MD5_LEN, keylen - i)); | |||
| i += MD5_LEN; | |||
| } | |||
| } | |||
| protected virtual void initCipher(byte[] iv, bool isEncrypt) | |||
| { | |||
| if (isEncrypt) { | |||
| _encryptIV = new byte[ivLen]; | |||
| Array.Copy(iv, _encryptIV, ivLen); | |||
| } else { | |||
| _decryptIV = new byte[ivLen]; | |||
| Array.Copy(iv, _decryptIV, ivLen); | |||
| } | |||
| } | |||
| protected abstract void cipherUpdate(bool isEncrypt, int length, byte[] buf, byte[] outbuf); | |||
| protected static void randBytes(byte[] buf, int length) { RNG.GetBytes(buf, length); } | |||
| #region TCP | |||
| public override void Encrypt(byte[] buf, int length, byte[] outbuf, out int outlength) | |||
| { | |||
| int cipherOffset = 0; | |||
| Debug.Assert(_encCircularBuffer != null, "_encCircularBuffer != null"); | |||
| _encCircularBuffer.Put(buf, 0, length); | |||
| if (! _encryptIVSent) { | |||
| // Generate IV | |||
| byte[] ivBytes = new byte[ivLen]; | |||
| randBytes(ivBytes, ivLen); | |||
| initCipher(ivBytes, true); | |||
| Array.Copy(ivBytes, 0, outbuf, 0, ivLen); | |||
| cipherOffset = ivLen; | |||
| _encryptIVSent = true; | |||
| } | |||
| int size = _encCircularBuffer.Size; | |||
| byte[] plain = _encCircularBuffer.Get(size); | |||
| byte[] cipher = new byte[size]; | |||
| cipherUpdate(true, size, plain, cipher); | |||
| Buffer.BlockCopy(cipher, 0, outbuf, cipherOffset, size); | |||
| outlength = size + cipherOffset; | |||
| } | |||
| public override void Decrypt(byte[] buf, int length, byte[] outbuf, out int outlength) | |||
| { | |||
| Debug.Assert(_decCircularBuffer != null, "_circularBuffer != null"); | |||
| _decCircularBuffer.Put(buf, 0, length); | |||
| if (! _decryptIVReceived) { | |||
| if (_decCircularBuffer.Size <= ivLen) { | |||
| // we need more data | |||
| outlength = 0; | |||
| return; | |||
| } | |||
| // start decryption | |||
| _decryptIVReceived = true; | |||
| byte[] iv = _decCircularBuffer.Get(ivLen); | |||
| initCipher(iv, false); | |||
| } | |||
| byte[] cipher = _decCircularBuffer.ToArray(); | |||
| cipherUpdate(false, cipher.Length, cipher, outbuf); | |||
| // move pointer only | |||
| _decCircularBuffer.Skip(_decCircularBuffer.Size); | |||
| outlength = cipher.Length; | |||
| // done the decryption | |||
| } | |||
| #endregion | |||
| #region UDP | |||
| public override void EncryptUDP(byte[] buf, int length, byte[] outbuf, out int outlength) | |||
| { | |||
| // Generate IV | |||
| randBytes(outbuf, ivLen); | |||
| initCipher(outbuf, true); | |||
| lock (_udpTmpBuf) { | |||
| cipherUpdate(true, length, buf, _udpTmpBuf); | |||
| outlength = length + ivLen; | |||
| Buffer.BlockCopy(_udpTmpBuf, 0, outbuf, ivLen, length); | |||
| } | |||
| } | |||
| public override void DecryptUDP(byte[] buf, int length, byte[] outbuf, out int outlength) | |||
| { | |||
| // Get IV from first pos | |||
| initCipher(buf, false); | |||
| outlength = length - ivLen; | |||
| lock (_udpTmpBuf) { | |||
| // C# could be multi-threaded | |||
| Buffer.BlockCopy(buf, ivLen, _udpTmpBuf, 0, length - ivLen); | |||
| cipherUpdate(false, length - ivLen, _udpTmpBuf, outbuf); | |||
| } | |||
| } | |||
| #endregion | |||
| } | |||
| } | |||
| @@ -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<string, EncryptorInfo> _ciphers = new Dictionary<string, EncryptorInfo> { | |||
| { "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<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 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 | |||
| } | |||
| } | |||
| @@ -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<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]; | |||
| 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 | |||
| } | |||
| } | |||
| @@ -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<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) } | |||
| }; | |||
| protected override Dictionary<string, EncryptorInfo> getCiphers() | |||
| { | |||
| return _ciphers; | |||
| } | |||
| public static List<string> SupportedCiphers() | |||
| { | |||
| return new List<string>(_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() | |||
| { | |||
| } | |||
| } | |||
| } | |||
| @@ -46,6 +46,7 @@ namespace Shadowsocks.Model | |||
| public bool isIPv6Enabled; // for experimental ipv6 support | |||
| public bool generateLegacyUrl; // for pre-sip002 url compatibility | |||
| public string geositeUrl; // for custom geosite source (and rule group) | |||
| public string geositeSha256sumUrl; // optional custom sha256sum url, leave empty to disable checksum verification for your custom geosite source | |||
| public List<string> geositeDirectGroups; // groups of domains that we connect without the proxy | |||
| public List<string> geositeProxiedGroups; // groups of domains that we connect via the proxy | |||
| public bool geositePreferDirect; // a.k.a blacklist mode | |||
| @@ -84,6 +85,7 @@ namespace Shadowsocks.Model | |||
| isIPv6Enabled = false; | |||
| generateLegacyUrl = false; | |||
| geositeUrl = ""; | |||
| geositeSha256sumUrl = ""; | |||
| geositeDirectGroups = new List<string>() | |||
| { | |||
| "private", | |||
| @@ -29,10 +29,6 @@ namespace Shadowsocks.Model | |||
| public int server_port; | |||
| public string password; | |||
| public string method; | |||
| // optional fields | |||
| [DefaultValue("")] | |||
| [JsonProperty(NullValueHandling = NullValueHandling.Ignore, DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] | |||
| @@ -53,6 +49,9 @@ namespace Shadowsocks.Model | |||
| public int timeout; | |||
| // Set to true when imported from a legacy ss:// URL. | |||
| public bool warnLegacyUrl; | |||
| public override int GetHashCode() | |||
| { | |||
| return server.GetHashCode() ^ server_port; | |||
| @@ -177,6 +176,7 @@ namespace Shadowsocks.Model | |||
| server.password = details.Groups["password"].Value; | |||
| server.server = details.Groups["hostname"].Value; | |||
| server.server_port = int.Parse(details.Groups["port"].Value); | |||
| server.warnLegacyUrl = true; | |||
| return server; | |||
| } | |||
| @@ -91,10 +91,10 @@ namespace Shadowsocks | |||
| // Check .NET Framework version | |||
| if (!Utils.IsSupportedRuntimeVersion()) | |||
| { | |||
| if (DialogResult.OK == MessageBox.Show(I18N.GetString("Unsupported .NET Framework, please update to {0} or later.", "4.7.2"), | |||
| if (DialogResult.OK == MessageBox.Show(I18N.GetString("Unsupported .NET Framework, please update to {0} or later.", "4.8"), | |||
| "Shadowsocks Error", MessageBoxButtons.OKCancel, MessageBoxIcon.Error)) | |||
| { | |||
| Process.Start("https://dotnet.microsoft.com/download/dotnet-framework/net472"); | |||
| Process.Start("https://dotnet.microsoft.com/download/dotnet-framework/net48"); | |||
| } | |||
| return; | |||
| } | |||
| @@ -73,13 +73,14 @@ namespace Shadowsocks.Properties { | |||
| ///var rules = []; | |||
| /// | |||
| ///// convert to abp grammar | |||
| ///var re = /^(@@)?\|\|.*?[^\^]$/; | |||
| ///for (var i = 0; i < __RULES__.length; i++) { | |||
| /// var s = __RULES__[i]; | |||
| /// if (s.substring(0, 2) == "||") s += "^"; | |||
| /// if (s.match(re)) s += "^"; | |||
| /// rules.push(s); | |||
| ///} | |||
| /// | |||
| ///for (var i = 0; i < [rest of string was truncated]";. | |||
| /// [rest of string was truncated]";. | |||
| /// </summary> | |||
| public static string abp_js { | |||
| get { | |||
| @@ -12,7 +12,7 @@ namespace Shadowsocks.Properties { | |||
| [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] | |||
| [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.1.0.0")] | |||
| [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.8.1.0")] | |||
| internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { | |||
| private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); | |||
| @@ -25,25 +25,10 @@ namespace Shadowsocks.View | |||
| public readonly bool deprecated; | |||
| // Edit here to add/delete encryption method displayed in UI | |||
| private static string[] deprecatedMethod = new string[] | |||
| { | |||
| "rc4-md5", | |||
| "salsa20", | |||
| "chacha20", | |||
| "bf-cfb", | |||
| "chacha20-ietf", | |||
| "aes-256-cfb", | |||
| "aes-192-cfb", | |||
| "aes-128-cfb", | |||
| "aes-256-ctr", | |||
| "aes-192-ctr", | |||
| "aes-128-ctr", | |||
| "camellia-256-cfb", | |||
| "camellia-192-cfb", | |||
| "camellia-128-cfb", | |||
| }; | |||
| private static string[] inuseMethod = new string[] | |||
| { | |||
| "none", | |||
| "plain", | |||
| "aes-256-gcm", | |||
| "aes-192-gcm", | |||
| "aes-128-gcm", | |||
| @@ -66,7 +51,6 @@ namespace Shadowsocks.View | |||
| var all = new List<EncryptionMethod>(); | |||
| all.AddRange(inuseMethod.Select(i => new EncryptionMethod(i, false))); | |||
| all.AddRange(deprecatedMethod.Select(d => new EncryptionMethod(d, true))); | |||
| allMethods = all.ToArray(); | |||
| foreach (var item in all) | |||
| @@ -629,5 +613,10 @@ namespace Shadowsocks.View | |||
| { | |||
| ShowHidePluginArgInput(NeedPluginArgCheckBox.Checked); | |||
| } | |||
| private void EncryptionSelect_SelectedIndexChanged(object sender, EventArgs e) | |||
| { | |||
| } | |||
| } | |||
| } | |||
| @@ -6,7 +6,7 @@ | |||
| </sectionGroup> | |||
| </configSections> | |||
| <startup> | |||
| <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" /> | |||
| <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" /> | |||
| </startup> | |||
| <runtime> | |||
| <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> | |||
| @@ -20,7 +20,7 @@ | |||
| </dependentAssembly> | |||
| <dependentAssembly> | |||
| <assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" /> | |||
| <bindingRedirect oldVersion="0.0.0.0-4.0.6.0" newVersion="4.0.6.0" /> | |||
| <bindingRedirect oldVersion="0.0.0.0-5.0.0.0" newVersion="5.0.0.0" /> | |||
| </dependentAssembly> | |||
| <dependentAssembly> | |||
| <assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" /> | |||
| @@ -30,6 +30,10 @@ | |||
| <assemblyIdentity name="ICSharpCode.AvalonEdit" publicKeyToken="9cc39be672370310" culture="neutral" /> | |||
| <bindingRedirect oldVersion="0.0.0.0-6.0.1.278" newVersion="6.0.1.278" /> | |||
| </dependentAssembly> | |||
| <dependentAssembly> | |||
| <assemblyIdentity name="System.Reactive" publicKeyToken="94bc3704cddfc263" culture="neutral" /> | |||
| <bindingRedirect oldVersion="0.0.0.0-5.0.0.0" newVersion="5.0.0.0" /> | |||
| </dependentAssembly> | |||
| </assemblyBinding> | |||
| </runtime> | |||
| <userSettings> | |||
| @@ -4,28 +4,28 @@ | |||
| <package id="Caseless.Fody" version="1.9.0" targetFramework="net472" /> | |||
| <package id="CommandLineParser" version="2.8.0" targetFramework="net472" /> | |||
| <package id="Costura.Fody" version="4.1.0" targetFramework="net472" /> | |||
| <package id="DynamicData" version="6.17.14" targetFramework="net472" /> | |||
| <package id="DynamicData" version="7.1.1" targetFramework="net48" /> | |||
| <package id="Fody" version="6.3.0" targetFramework="net472" developmentDependency="true" /> | |||
| <package id="GlobalHotKey" version="1.1.0" targetFramework="net472" /> | |||
| <package id="Google.Protobuf" version="3.13.0" targetFramework="net472" /> | |||
| <package id="Google.Protobuf" version="3.14.0" targetFramework="net48" /> | |||
| <package id="MdXaml" version="1.6.0" targetFramework="net472" /> | |||
| <package id="Newtonsoft.Json" version="12.0.3" targetFramework="net472" /> | |||
| <package id="NLog" version="4.7.5" targetFramework="net472" /> | |||
| <package id="Pharmacist.Common" version="1.8.1" targetFramework="net472" /> | |||
| <package id="ReactiveUI" version="11.5.35" targetFramework="net472" /> | |||
| <package id="ReactiveUI.Events.WPF" version="11.5.35" targetFramework="net472" /> | |||
| <package id="ReactiveUI.Fody" version="11.5.35" targetFramework="net472" /> | |||
| <package id="ReactiveUI.Validation" version="1.7.1" targetFramework="net472" /> | |||
| <package id="ReactiveUI.WPF" version="11.5.35" targetFramework="net472" /> | |||
| <package id="Splat" version="9.6.1" targetFramework="net472" /> | |||
| <package id="NLog" version="4.7.6" targetFramework="net48" /> | |||
| <package id="Pharmacist.Common" version="2.0.5" targetFramework="net48" /> | |||
| <package id="ReactiveUI" version="12.1.5" targetFramework="net48" /> | |||
| <package id="ReactiveUI.Events.WPF" version="12.1.5" targetFramework="net48" /> | |||
| <package id="ReactiveUI.Fody" version="12.1.5" targetFramework="net48" /> | |||
| <package id="ReactiveUI.Validation" version="1.8.6" targetFramework="net48" /> | |||
| <package id="ReactiveUI.WPF" version="12.1.5" targetFramework="net48" /> | |||
| <package id="Splat" version="9.8.1" targetFramework="net48" /> | |||
| <package id="System.Buffers" version="4.5.1" targetFramework="net472" /> | |||
| <package id="System.IO" version="4.3.0" targetFramework="net472" /> | |||
| <package id="System.Memory" version="4.5.4" targetFramework="net472" /> | |||
| <package id="System.Net.Http" version="4.3.4" targetFramework="net472" /> | |||
| <package id="System.Numerics.Vectors" version="4.5.0" targetFramework="net472" /> | |||
| <package id="System.Reactive" version="4.4.1" targetFramework="net472" /> | |||
| <package id="System.Reactive" version="5.0.0" targetFramework="net48" /> | |||
| <package id="System.Runtime" version="4.3.1" targetFramework="net472" /> | |||
| <package id="System.Runtime.CompilerServices.Unsafe" version="4.7.1" targetFramework="net472" /> | |||
| <package id="System.Runtime.CompilerServices.Unsafe" version="5.0.0" targetFramework="net48" /> | |||
| <package id="System.Security.Cryptography.Algorithms" version="4.3.1" targetFramework="net472" /> | |||
| <package id="System.Security.Cryptography.Encoding" version="4.3.0" targetFramework="net472" /> | |||
| <package id="System.Security.Cryptography.Primitives" version="4.3.0" targetFramework="net472" /> | |||
| @@ -1,6 +1,6 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | |||
| <Import Project="..\packages\ReactiveUI.Fody.11.5.35\build\ReactiveUI.Fody.props" Condition="Exists('..\packages\ReactiveUI.Fody.11.5.35\build\ReactiveUI.Fody.props')" /> | |||
| <Import Project="..\packages\ReactiveUI.Fody.12.1.5\build\ReactiveUI.Fody.props" Condition="Exists('..\packages\ReactiveUI.Fody.12.1.5\build\ReactiveUI.Fody.props')" /> | |||
| <Import Project="..\packages\Costura.Fody.4.1.0\build\Costura.Fody.props" Condition="Exists('..\packages\Costura.Fody.4.1.0\build\Costura.Fody.props')" /> | |||
| <Import Project="..\packages\Caseless.Fody.1.9.0\build\Caseless.Fody.props" Condition="Exists('..\packages\Caseless.Fody.1.9.0\build\Caseless.Fody.props')" /> | |||
| <PropertyGroup> | |||
| @@ -13,7 +13,7 @@ | |||
| <AppDesignerFolder>Properties</AppDesignerFolder> | |||
| <RootNamespace>Shadowsocks</RootNamespace> | |||
| <AssemblyName>Shadowsocks</AssemblyName> | |||
| <TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion> | |||
| <TargetFrameworkVersion>v4.8</TargetFrameworkVersion> | |||
| <FileAlignment>512</FileAlignment> | |||
| <StartupObject> | |||
| </StartupObject> | |||
| @@ -79,14 +79,14 @@ | |||
| <Reference Include="Costura, Version=4.1.0.0, Culture=neutral, PublicKeyToken=9919ef960d84173d, processorArchitecture=MSIL"> | |||
| <HintPath>..\packages\Costura.Fody.4.1.0\lib\net40\Costura.dll</HintPath> | |||
| </Reference> | |||
| <Reference Include="DynamicData, Version=6.17.0.0, Culture=neutral, processorArchitecture=MSIL"> | |||
| <HintPath>..\packages\DynamicData.6.17.14\lib\net461\DynamicData.dll</HintPath> | |||
| <Reference Include="DynamicData, Version=7.1.0.0, Culture=neutral, processorArchitecture=MSIL"> | |||
| <HintPath>..\packages\DynamicData.7.1.1\lib\net461\DynamicData.dll</HintPath> | |||
| </Reference> | |||
| <Reference Include="GlobalHotKey, Version=1.1.0.0, Culture=neutral, processorArchitecture=MSIL"> | |||
| <HintPath>..\packages\GlobalHotKey.1.1.0\lib\GlobalHotKey.dll</HintPath> | |||
| </Reference> | |||
| <Reference Include="Google.Protobuf, Version=3.13.0.0, Culture=neutral, PublicKeyToken=a7d26565bac4d604, processorArchitecture=MSIL"> | |||
| <HintPath>..\packages\Google.Protobuf.3.13.0\lib\net45\Google.Protobuf.dll</HintPath> | |||
| <Reference Include="Google.Protobuf, Version=3.14.0.0, Culture=neutral, PublicKeyToken=a7d26565bac4d604, processorArchitecture=MSIL"> | |||
| <HintPath>..\packages\Google.Protobuf.3.14.0\lib\net45\Google.Protobuf.dll</HintPath> | |||
| </Reference> | |||
| <Reference Include="ICSharpCode.AvalonEdit, Version=6.0.1.278, Culture=neutral, PublicKeyToken=9cc39be672370310, processorArchitecture=MSIL"> | |||
| <HintPath>..\packages\AvalonEdit.6.0.1\lib\net45\ICSharpCode.AvalonEdit.dll</HintPath> | |||
| @@ -100,31 +100,31 @@ | |||
| <HintPath>..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll</HintPath> | |||
| </Reference> | |||
| <Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL"> | |||
| <HintPath>..\packages\NLog.4.7.5\lib\net45\NLog.dll</HintPath> | |||
| <HintPath>..\packages\NLog.4.7.6\lib\net45\NLog.dll</HintPath> | |||
| </Reference> | |||
| <Reference Include="Pharmacist.Common, Version=1.8.0.0, Culture=neutral, processorArchitecture=MSIL"> | |||
| <HintPath>..\packages\Pharmacist.Common.1.8.1\lib\netstandard2.0\Pharmacist.Common.dll</HintPath> | |||
| <Reference Include="Pharmacist.Common, Version=2.0.0.0, Culture=neutral, processorArchitecture=MSIL"> | |||
| <HintPath>..\packages\Pharmacist.Common.2.0.5\lib\net472\Pharmacist.Common.dll</HintPath> | |||
| </Reference> | |||
| <Reference Include="PresentationCore" /> | |||
| <Reference Include="PresentationFramework" /> | |||
| <Reference Include="PresentationFramework.Aero" /> | |||
| <Reference Include="ReactiveUI, Version=11.5.0.0, Culture=neutral, processorArchitecture=MSIL"> | |||
| <HintPath>..\packages\ReactiveUI.11.5.35\lib\net461\ReactiveUI.dll</HintPath> | |||
| <Reference Include="ReactiveUI, Version=12.1.0.0, Culture=neutral, processorArchitecture=MSIL"> | |||
| <HintPath>..\packages\ReactiveUI.12.1.5\lib\net461\ReactiveUI.dll</HintPath> | |||
| </Reference> | |||
| <Reference Include="ReactiveUI.Events.WPF, Version=11.5.0.0, Culture=neutral, processorArchitecture=MSIL"> | |||
| <HintPath>..\packages\ReactiveUI.Events.WPF.11.5.35\lib\net472\ReactiveUI.Events.WPF.dll</HintPath> | |||
| <Reference Include="ReactiveUI.Events.WPF, Version=12.1.0.0, Culture=neutral, processorArchitecture=MSIL"> | |||
| <HintPath>..\packages\ReactiveUI.Events.WPF.12.1.5\lib\net472\ReactiveUI.Events.WPF.dll</HintPath> | |||
| </Reference> | |||
| <Reference Include="ReactiveUI.Fody.Helpers, Version=11.5.0.0, Culture=neutral, processorArchitecture=MSIL"> | |||
| <HintPath>..\packages\ReactiveUI.Fody.11.5.35\lib\net461\ReactiveUI.Fody.Helpers.dll</HintPath> | |||
| <Reference Include="ReactiveUI.Fody.Helpers, Version=12.1.0.0, Culture=neutral, processorArchitecture=MSIL"> | |||
| <HintPath>..\packages\ReactiveUI.Fody.12.1.5\lib\net461\ReactiveUI.Fody.Helpers.dll</HintPath> | |||
| </Reference> | |||
| <Reference Include="ReactiveUI.Validation, Version=1.7.0.0, Culture=neutral, processorArchitecture=MSIL"> | |||
| <HintPath>..\packages\ReactiveUI.Validation.1.7.1\lib\net461\ReactiveUI.Validation.dll</HintPath> | |||
| <Reference Include="ReactiveUI.Validation, Version=1.8.0.0, Culture=neutral, processorArchitecture=MSIL"> | |||
| <HintPath>..\packages\ReactiveUI.Validation.1.8.6\lib\net461\ReactiveUI.Validation.dll</HintPath> | |||
| </Reference> | |||
| <Reference Include="ReactiveUI.WPF, Version=11.5.0.0, Culture=neutral, processorArchitecture=MSIL"> | |||
| <HintPath>..\packages\ReactiveUI.WPF.11.5.35\lib\net472\ReactiveUI.WPF.dll</HintPath> | |||
| <Reference Include="ReactiveUI.Wpf, Version=12.1.0.0, Culture=neutral, processorArchitecture=MSIL"> | |||
| <HintPath>..\packages\ReactiveUI.WPF.12.1.5\lib\net472\ReactiveUI.Wpf.dll</HintPath> | |||
| </Reference> | |||
| <Reference Include="Splat, Version=9.6.0.0, Culture=neutral, processorArchitecture=MSIL"> | |||
| <HintPath>..\packages\Splat.9.6.1\lib\net461\Splat.dll</HintPath> | |||
| <Reference Include="Splat, Version=9.8.0.0, Culture=neutral, processorArchitecture=MSIL"> | |||
| <HintPath>..\packages\Splat.9.8.1\lib\net461\Splat.dll</HintPath> | |||
| </Reference> | |||
| <Reference Include="System" /> | |||
| <Reference Include="System.Buffers, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL"> | |||
| @@ -155,16 +155,16 @@ | |||
| <Reference Include="System.Numerics.Vectors, Version=4.1.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> | |||
| <HintPath>..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll</HintPath> | |||
| </Reference> | |||
| <Reference Include="System.Reactive, Version=4.4.0.0, Culture=neutral, PublicKeyToken=94bc3704cddfc263, processorArchitecture=MSIL"> | |||
| <HintPath>..\packages\System.Reactive.4.4.1\lib\net46\System.Reactive.dll</HintPath> | |||
| <Reference Include="System.Reactive, Version=5.0.0.0, Culture=neutral, PublicKeyToken=94bc3704cddfc263, processorArchitecture=MSIL"> | |||
| <HintPath>..\packages\System.Reactive.5.0.0\lib\net472\System.Reactive.dll</HintPath> | |||
| </Reference> | |||
| <Reference Include="System.Runtime, Version=4.1.1.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> | |||
| <HintPath>..\packages\System.Runtime.4.3.1\lib\net462\System.Runtime.dll</HintPath> | |||
| <Private>True</Private> | |||
| <Private>True</Private> | |||
| </Reference> | |||
| <Reference Include="System.Runtime.CompilerServices.Unsafe, Version=4.0.6.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> | |||
| <HintPath>..\packages\System.Runtime.CompilerServices.Unsafe.4.7.1\lib\net461\System.Runtime.CompilerServices.Unsafe.dll</HintPath> | |||
| <Reference Include="System.Runtime.CompilerServices.Unsafe, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> | |||
| <HintPath>..\packages\System.Runtime.CompilerServices.Unsafe.5.0.0\lib\net45\System.Runtime.CompilerServices.Unsafe.dll</HintPath> | |||
| </Reference> | |||
| <Reference Include="System.Runtime.Serialization" /> | |||
| <Reference Include="System.Security.Cryptography.Algorithms, Version=4.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> | |||
| @@ -240,10 +240,7 @@ | |||
| <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="Encryption\Stream\PlainEncryptor.cs" /> | |||
| <Compile Include="Localization\LocalizationProvider.cs" /> | |||
| <Compile Include="Localization\Strings.Designer.cs"> | |||
| <AutoGen>True</AutoGen> | |||
| @@ -447,7 +444,7 @@ | |||
| <Error Condition="!Exists('..\packages\Caseless.Fody.1.9.0\build\Caseless.Fody.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Caseless.Fody.1.9.0\build\Caseless.Fody.props'))" /> | |||
| <Error Condition="!Exists('..\packages\Costura.Fody.4.1.0\build\Costura.Fody.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Costura.Fody.4.1.0\build\Costura.Fody.props'))" /> | |||
| <Error Condition="!Exists('..\packages\Fody.6.3.0\build\Fody.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Fody.6.3.0\build\Fody.targets'))" /> | |||
| <Error Condition="!Exists('..\packages\ReactiveUI.Fody.11.5.35\build\ReactiveUI.Fody.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\ReactiveUI.Fody.11.5.35\build\ReactiveUI.Fody.props'))" /> | |||
| <Error Condition="!Exists('..\packages\ReactiveUI.Fody.12.1.5\build\ReactiveUI.Fody.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\ReactiveUI.Fody.12.1.5\build\ReactiveUI.Fody.props'))" /> | |||
| </Target> | |||
| <Import Project="..\packages\Fody.6.3.0\build\Fody.targets" Condition="Exists('..\packages\Fody.6.3.0\build\Fody.targets')" /> | |||
| <!-- To modify your build process, add your task inside one of the targets below and uncomment it. | |||
| @@ -1,233 +0,0 @@ | |||
| using System; | |||
| using Microsoft.VisualStudio.TestTools.UnitTesting; | |||
| using Shadowsocks.Encryption; | |||
| using System.Threading; | |||
| using System.Collections.Generic; | |||
| using Shadowsocks.Encryption.Stream; | |||
| using System.Diagnostics; | |||
| namespace Shadowsocks.Test | |||
| { | |||
| [TestClass] | |||
| public class CryptographyTest | |||
| { | |||
| [TestMethod] | |||
| public void TestMD5() | |||
| { | |||
| for (int len = 1; len < 64; len++) | |||
| { | |||
| System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create(); | |||
| byte[] bytes = new byte[len]; | |||
| var random = new Random(); | |||
| random.NextBytes(bytes); | |||
| string md5str = Convert.ToBase64String(md5.ComputeHash(bytes)); | |||
| string md5str2 = Convert.ToBase64String(MbedTLS.MD5(bytes)); | |||
| Assert.IsTrue(md5str == md5str2); | |||
| } | |||
| } | |||
| private void RunEncryptionRound(IEncryptor encryptor, IEncryptor decryptor) | |||
| { | |||
| RNG.Reload(); | |||
| byte[] plain = new byte[16384]; | |||
| byte[] cipher = new byte[plain.Length + 16]; | |||
| byte[] plain2 = new byte[plain.Length + 16]; | |||
| int outLen = 0; | |||
| int outLen2 = 0; | |||
| var random = new Random(); | |||
| random.NextBytes(plain); | |||
| encryptor.Encrypt(plain, plain.Length, cipher, out outLen); | |||
| decryptor.Decrypt(cipher, outLen, plain2, out outLen2); | |||
| Assert.AreEqual(plain.Length, outLen2); | |||
| for (int j = 0; j < plain.Length; j++) | |||
| { | |||
| Assert.AreEqual(plain[j], plain2[j]); | |||
| } | |||
| encryptor.Encrypt(plain, 1000, cipher, out outLen); | |||
| decryptor.Decrypt(cipher, outLen, plain2, out outLen2); | |||
| Assert.AreEqual(1000, outLen2); | |||
| for (int j = 0; j < outLen2; j++) | |||
| { | |||
| Assert.AreEqual(plain[j], plain2[j]); | |||
| } | |||
| encryptor.Encrypt(plain, 12333, cipher, out outLen); | |||
| decryptor.Decrypt(cipher, outLen, plain2, out outLen2); | |||
| Assert.AreEqual(12333, outLen2); | |||
| for (int j = 0; j < outLen2; j++) | |||
| { | |||
| Assert.AreEqual(plain[j], plain2[j]); | |||
| } | |||
| } | |||
| private static bool encryptionFailed = false; | |||
| 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<Thread> threads = new List<Thread>(); | |||
| 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() | |||
| { | |||
| encryptionFailed = false; | |||
| // run it once before the multi-threading test to initialize global tables | |||
| RunSingleRC4EncryptionThread(); | |||
| List<Thread> threads = new List<Thread>(); | |||
| for (int i = 0; i < 10; i++) | |||
| { | |||
| Thread t = new Thread(new ThreadStart(RunSingleRC4EncryptionThread)); | |||
| threads.Add(t); | |||
| t.Start(); | |||
| } | |||
| foreach (Thread t in threads) | |||
| { | |||
| t.Join(); | |||
| } | |||
| RNG.Close(); | |||
| 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() | |||
| { | |||
| encryptionFailed = false; | |||
| // run it once before the multi-threading test to initialize global tables | |||
| RunSingleSodiumEncryptionThread(); | |||
| List<Thread> threads = new List<Thread>(); | |||
| for (int i = 0; i < 10; i++) | |||
| { | |||
| Thread t = new Thread(new ThreadStart(RunSingleSodiumEncryptionThread)); | |||
| threads.Add(t); | |||
| t.Start(); | |||
| } | |||
| foreach (Thread t in threads) | |||
| { | |||
| t.Join(); | |||
| } | |||
| RNG.Close(); | |||
| Assert.IsFalse(encryptionFailed); | |||
| } | |||
| private void RunSingleSodiumEncryptionThread() | |||
| { | |||
| 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); | |||
| } | |||
| } | |||
| catch | |||
| { | |||
| encryptionFailed = true; | |||
| throw; | |||
| } | |||
| } | |||
| [TestMethod] | |||
| public void TestOpenSSLEncryption() | |||
| { | |||
| encryptionFailed = false; | |||
| // 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; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -8,7 +8,7 @@ | |||
| <AppDesignerFolder>Properties</AppDesignerFolder> | |||
| <RootNamespace>Shadowsocks.Test</RootNamespace> | |||
| <AssemblyName>Shadowsocks.Test</AssemblyName> | |||
| <TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion> | |||
| <TargetFrameworkVersion>v4.8</TargetFrameworkVersion> | |||
| <FileAlignment>512</FileAlignment> | |||
| <ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> | |||
| <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion> | |||
| @@ -56,7 +56,6 @@ | |||
| </Choose> | |||
| <ItemGroup> | |||
| <Compile Include="ProcessEnvironment.cs" /> | |||
| <Compile Include="CryptographyTest.cs" /> | |||
| <Compile Include="Sip003PluginTest.cs" /> | |||
| <Compile Include="UrlTest.cs" /> | |||
| <Compile Include="UnitTest.cs" /> | |||
| @@ -99,4 +98,4 @@ | |||
| <Target Name="AfterBuild"> | |||
| </Target> | |||
| --> | |||
| </Project> | |||
| </Project> | |||
| @@ -4,7 +4,7 @@ | |||
| <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> | |||
| <dependentAssembly> | |||
| <assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" /> | |||
| <bindingRedirect oldVersion="0.0.0.0-4.0.6.0" newVersion="4.0.6.0" /> | |||
| <bindingRedirect oldVersion="0.0.0.0-5.0.0.0" newVersion="5.0.0.0" /> | |||
| </dependentAssembly> | |||
| <dependentAssembly> | |||
| <assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" /> | |||
| @@ -16,4 +16,4 @@ | |||
| </dependentAssembly> | |||
| </assemblyBinding> | |||
| </runtime> | |||
| </configuration> | |||
| <startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" /></startup></configuration> | |||