@@ -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 | *.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 | 4.3.2.0 2020-11-05 | ||||
- PAC: direct connection for private IP ranges by @studentmain (#3008) | - PAC: direct connection for private IP ranges by @studentmain (#3008) | ||||
- Remove duplicate startup entries (#3012) | - Remove duplicate startup entries (#3012) | ||||
@@ -21,7 +21,7 @@ Download the latest release from [release page]. | |||||
## Requirements | ## 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 | ## Basics | ||||
@@ -127,7 +127,7 @@ Please visit [Servers] for more information. | |||||
## Development | ## 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, | 2. It is recommended to share your idea on the Issue Board before you start to work, | ||||
especially for feature development. | especially for feature development. | ||||
@@ -164,9 +164,6 @@ Sysproxy () https://github.com/Noisyfox/sysproxy | |||||
[GeoSite]: https://github.com/v2fly/domain-list-community | [GeoSite]: https://github.com/v2fly/domain-list-community | ||||
[Servers]: https://github.com/shadowsocks/shadowsocks/wiki/Ports-and-Clients#linux--server-side | [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 | [中文说明]: 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 | [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 | [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 | [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 | # version format | ||||
# Build version format is taken from UI if it is not set | # 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 to build | ||||
# branches: | # branches: | ||||
@@ -75,52 +75,68 @@ namespace Shadowsocks.Controller | |||||
public static async Task UpdatePACFromGeosite() | 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(); | var config = Program.MainController.GetCurrentConfiguration(); | ||||
bool blacklist = config.geositePreferDirect; | |||||
var blacklist = config.geositePreferDirect; | |||||
var httpClient = Program.MainController.GetHttpClient(); | var httpClient = Program.MainController.GetHttpClient(); | ||||
if (!string.IsNullOrWhiteSpace(config.geositeUrl)) | if (!string.IsNullOrWhiteSpace(config.geositeUrl)) | ||||
{ | { | ||||
logger.Info("Found custom Geosite URL in config file"); | logger.Info("Found custom Geosite URL in config file"); | ||||
geositeUrl = config.geositeUrl; | 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}"); | logger.Info($"Checking Geosite from {geositeUrl}"); | ||||
try | 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 | // not latest. download new DB | ||||
var downloadedBytes = await httpClient.GetByteArrayAsync(geositeUrl); | var downloadedBytes = await httpClient.GetByteArrayAsync(geositeUrl); | ||||
// verify sha256sum | // 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 | // write to geosite file | ||||
@@ -33,7 +33,7 @@ namespace Shadowsocks.Controller | |||||
public event EventHandler CheckUpdateCompleted; | public event EventHandler CheckUpdateCompleted; | ||||
public const string Version = "4.3.2.0"; | |||||
public const string Version = "4.4.1.0"; | |||||
private readonly Version _version; | private readonly Version _version; | ||||
public UpdateChecker() | public UpdateChecker() | ||||
@@ -450,6 +450,8 @@ namespace Shadowsocks.Controller | |||||
foreach (var server in servers) | foreach (var server in servers) | ||||
{ | { | ||||
_config.configs.Add(server); | _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; | _config.index = _config.configs.Count - 1; | ||||
SaveConfig(_config); | SaveConfig(_config); | ||||
@@ -133,6 +133,7 @@ Failed to update registry,Не удалось обновить запись в | |||||
Import from URL: {0} ?,импортировать из адреса: {0} ?,从URL导入: {0} ?,從URL匯入: {0} ?,{0}:このURLからインポートしますか?,, | Import from URL: {0} ?,импортировать из адреса: {0} ?,从URL导入: {0} ?,從URL匯入: {0} ?,{0}:このURLからインポートしますか?,, | ||||
Successfully imported from {0},Успешно импортировано из {0},导入成功:{0},導入成功:{0},{0}:インポートしました。,, | Successfully imported from {0},Успешно импортировано из {0},导入成功:{0},導入成功:{0},{0}:インポートしました。,, | ||||
Failed to import. Please check if the link is valid.,,导入失败,请检查链接是否有效。,導入失敗,請檢查鏈接是否有效。,インポートに失敗しました。リンクの有効性を確認してください。,, | 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é: | System Proxy On: ,Системный прокси:,系统代理已启用:,系統 Proxy 已啟用:,システム プロキシが有効:,시스템 프록시 활성화됨: ,Proxy système activé: | ||||
Running: Port {0},Запущен на порту {0},正在运行:端口 {0},正在執行:連接埠號碼 {0},実行中:ポート {0},실행 중: 포트 {0}번,En cours d'exécution: port {0} | 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 à | "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.Encryption.CircularBuffer; | ||||
using Shadowsocks.Controller; | using Shadowsocks.Controller; | ||||
using Shadowsocks.Encryption.Exception; | using Shadowsocks.Encryption.Exception; | ||||
using Shadowsocks.Encryption.Stream; | |||||
namespace Shadowsocks.Encryption.AEAD | namespace Shadowsocks.Encryption.AEAD | ||||
{ | { | ||||
@@ -98,7 +97,24 @@ namespace Shadowsocks.Encryption.AEAD | |||||
public void DeriveKey(byte[] password, byte[] key, int keylen) | 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) | public void DeriveSessionKey(byte[] salt, byte[] masterKey, byte[] sessionKey) | ||||
@@ -17,6 +17,8 @@ namespace Shadowsocks.Encryption | |||||
{ | { | ||||
var AEADMbedTLSEncryptorSupportedCiphers = AEADMbedTLSEncryptor.SupportedCiphers(); | var AEADMbedTLSEncryptorSupportedCiphers = AEADMbedTLSEncryptor.SupportedCiphers(); | ||||
var AEADSodiumEncryptorSupportedCiphers = AEADSodiumEncryptor.SupportedCiphers(); | var AEADSodiumEncryptorSupportedCiphers = AEADSodiumEncryptor.SupportedCiphers(); | ||||
var PlainEncryptorSupportedCiphers = PlainEncryptor.SupportedCiphers(); | |||||
if (Sodium.AES256GCMAvailable) | if (Sodium.AES256GCMAvailable) | ||||
{ | { | ||||
// prefer to aes-256-gcm in libsodium | // prefer to aes-256-gcm in libsodium | ||||
@@ -27,26 +29,6 @@ namespace Shadowsocks.Encryption | |||||
AEADSodiumEncryptorSupportedCiphers.Remove("aes-256-gcm"); | 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()) | foreach (string method in AEADOpenSSLEncryptor.SupportedCiphers()) | ||||
{ | { | ||||
if (!_registeredEncryptors.ContainsKey(method)) | if (!_registeredEncryptors.ContainsKey(method)) | ||||
@@ -64,6 +46,12 @@ namespace Shadowsocks.Encryption | |||||
if (!_registeredEncryptors.ContainsKey(method)) | if (!_registeredEncryptors.ContainsKey(method)) | ||||
_registeredEncryptors.Add(method, typeof(AEADMbedTLSEncryptor)); | _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) | public static IEncryptor GetEncryptor(string method, string password) | ||||
@@ -97,4 +85,4 @@ namespace Shadowsocks.Encryption | |||||
return sb.ToString(); | 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 isIPv6Enabled; // for experimental ipv6 support | ||||
public bool generateLegacyUrl; // for pre-sip002 url compatibility | public bool generateLegacyUrl; // for pre-sip002 url compatibility | ||||
public string geositeUrl; // for custom geosite source (and rule group) | 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> geositeDirectGroups; // groups of domains that we connect without the proxy | ||||
public List<string> geositeProxiedGroups; // groups of domains that we connect via the proxy | public List<string> geositeProxiedGroups; // groups of domains that we connect via the proxy | ||||
public bool geositePreferDirect; // a.k.a blacklist mode | public bool geositePreferDirect; // a.k.a blacklist mode | ||||
@@ -84,6 +85,7 @@ namespace Shadowsocks.Model | |||||
isIPv6Enabled = false; | isIPv6Enabled = false; | ||||
generateLegacyUrl = false; | generateLegacyUrl = false; | ||||
geositeUrl = ""; | geositeUrl = ""; | ||||
geositeSha256sumUrl = ""; | |||||
geositeDirectGroups = new List<string>() | geositeDirectGroups = new List<string>() | ||||
{ | { | ||||
"private", | "private", | ||||
@@ -29,10 +29,6 @@ namespace Shadowsocks.Model | |||||
public int server_port; | public int server_port; | ||||
public string password; | public string password; | ||||
public string method; | public string method; | ||||
// optional fields | // optional fields | ||||
[DefaultValue("")] | [DefaultValue("")] | ||||
[JsonProperty(NullValueHandling = NullValueHandling.Ignore, DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] | [JsonProperty(NullValueHandling = NullValueHandling.Ignore, DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] | ||||
@@ -53,6 +49,9 @@ namespace Shadowsocks.Model | |||||
public int timeout; | public int timeout; | ||||
// Set to true when imported from a legacy ss:// URL. | |||||
public bool warnLegacyUrl; | |||||
public override int GetHashCode() | public override int GetHashCode() | ||||
{ | { | ||||
return server.GetHashCode() ^ server_port; | return server.GetHashCode() ^ server_port; | ||||
@@ -177,6 +176,7 @@ namespace Shadowsocks.Model | |||||
server.password = details.Groups["password"].Value; | server.password = details.Groups["password"].Value; | ||||
server.server = details.Groups["hostname"].Value; | server.server = details.Groups["hostname"].Value; | ||||
server.server_port = int.Parse(details.Groups["port"].Value); | server.server_port = int.Parse(details.Groups["port"].Value); | ||||
server.warnLegacyUrl = true; | |||||
return server; | return server; | ||||
} | } | ||||
@@ -91,10 +91,10 @@ namespace Shadowsocks | |||||
// Check .NET Framework version | // Check .NET Framework version | ||||
if (!Utils.IsSupportedRuntimeVersion()) | 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)) | "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; | return; | ||||
} | } | ||||
@@ -73,13 +73,14 @@ namespace Shadowsocks.Properties { | |||||
///var rules = []; | ///var rules = []; | ||||
/// | /// | ||||
///// convert to abp grammar | ///// convert to abp grammar | ||||
///var re = /^(@@)?\|\|.*?[^\^]$/; | |||||
///for (var i = 0; i < __RULES__.length; i++) { | ///for (var i = 0; i < __RULES__.length; i++) { | ||||
/// var s = __RULES__[i]; | /// var s = __RULES__[i]; | ||||
/// if (s.substring(0, 2) == "||") s += "^"; | |||||
/// if (s.match(re)) s += "^"; | |||||
/// rules.push(s); | /// rules.push(s); | ||||
///} | ///} | ||||
/// | /// | ||||
///for (var i = 0; i < [rest of string was truncated]";. | |||||
/// [rest of string was truncated]";. | |||||
/// </summary> | /// </summary> | ||||
public static string abp_js { | public static string abp_js { | ||||
get { | get { | ||||
@@ -12,7 +12,7 @@ namespace Shadowsocks.Properties { | |||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] | [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 { | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { | ||||
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); | ||||
@@ -25,25 +25,10 @@ namespace Shadowsocks.View | |||||
public readonly bool deprecated; | public readonly bool deprecated; | ||||
// Edit here to add/delete encryption method displayed in UI | // 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[] | private static string[] inuseMethod = new string[] | ||||
{ | { | ||||
"none", | |||||
"plain", | |||||
"aes-256-gcm", | "aes-256-gcm", | ||||
"aes-192-gcm", | "aes-192-gcm", | ||||
"aes-128-gcm", | "aes-128-gcm", | ||||
@@ -66,7 +51,6 @@ namespace Shadowsocks.View | |||||
var all = new List<EncryptionMethod>(); | var all = new List<EncryptionMethod>(); | ||||
all.AddRange(inuseMethod.Select(i => new EncryptionMethod(i, false))); | all.AddRange(inuseMethod.Select(i => new EncryptionMethod(i, false))); | ||||
all.AddRange(deprecatedMethod.Select(d => new EncryptionMethod(d, true))); | |||||
allMethods = all.ToArray(); | allMethods = all.ToArray(); | ||||
foreach (var item in all) | foreach (var item in all) | ||||
@@ -629,5 +613,10 @@ namespace Shadowsocks.View | |||||
{ | { | ||||
ShowHidePluginArgInput(NeedPluginArgCheckBox.Checked); | ShowHidePluginArgInput(NeedPluginArgCheckBox.Checked); | ||||
} | } | ||||
private void EncryptionSelect_SelectedIndexChanged(object sender, EventArgs e) | |||||
{ | |||||
} | |||||
} | } | ||||
} | } |
@@ -6,7 +6,7 @@ | |||||
</sectionGroup> | </sectionGroup> | ||||
</configSections> | </configSections> | ||||
<startup> | <startup> | ||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" /> | |||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" /> | |||||
</startup> | </startup> | ||||
<runtime> | <runtime> | ||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> | <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> | ||||
@@ -20,7 +20,7 @@ | |||||
</dependentAssembly> | </dependentAssembly> | ||||
<dependentAssembly> | <dependentAssembly> | ||||
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" /> | <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> | ||||
<dependentAssembly> | <dependentAssembly> | ||||
<assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" /> | <assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" /> | ||||
@@ -30,6 +30,10 @@ | |||||
<assemblyIdentity name="ICSharpCode.AvalonEdit" publicKeyToken="9cc39be672370310" culture="neutral" /> | <assemblyIdentity name="ICSharpCode.AvalonEdit" publicKeyToken="9cc39be672370310" culture="neutral" /> | ||||
<bindingRedirect oldVersion="0.0.0.0-6.0.1.278" newVersion="6.0.1.278" /> | <bindingRedirect oldVersion="0.0.0.0-6.0.1.278" newVersion="6.0.1.278" /> | ||||
</dependentAssembly> | </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> | </assemblyBinding> | ||||
</runtime> | </runtime> | ||||
<userSettings> | <userSettings> | ||||
@@ -4,28 +4,28 @@ | |||||
<package id="Caseless.Fody" version="1.9.0" targetFramework="net472" /> | <package id="Caseless.Fody" version="1.9.0" targetFramework="net472" /> | ||||
<package id="CommandLineParser" version="2.8.0" targetFramework="net472" /> | <package id="CommandLineParser" version="2.8.0" targetFramework="net472" /> | ||||
<package id="Costura.Fody" version="4.1.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="Fody" version="6.3.0" targetFramework="net472" developmentDependency="true" /> | ||||
<package id="GlobalHotKey" version="1.1.0" targetFramework="net472" /> | <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="MdXaml" version="1.6.0" targetFramework="net472" /> | ||||
<package id="Newtonsoft.Json" version="12.0.3" 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.Buffers" version="4.5.1" targetFramework="net472" /> | ||||
<package id="System.IO" version="4.3.0" 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.Memory" version="4.5.4" targetFramework="net472" /> | ||||
<package id="System.Net.Http" version="4.3.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.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" 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.Algorithms" version="4.3.1" targetFramework="net472" /> | ||||
<package id="System.Security.Cryptography.Encoding" version="4.3.0" 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" /> | <package id="System.Security.Cryptography.Primitives" version="4.3.0" targetFramework="net472" /> | ||||
@@ -1,6 +1,6 @@ | |||||
<?xml version="1.0" encoding="utf-8"?> | <?xml version="1.0" encoding="utf-8"?> | ||||
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | <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\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')" /> | <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> | <PropertyGroup> | ||||
@@ -13,7 +13,7 @@ | |||||
<AppDesignerFolder>Properties</AppDesignerFolder> | <AppDesignerFolder>Properties</AppDesignerFolder> | ||||
<RootNamespace>Shadowsocks</RootNamespace> | <RootNamespace>Shadowsocks</RootNamespace> | ||||
<AssemblyName>Shadowsocks</AssemblyName> | <AssemblyName>Shadowsocks</AssemblyName> | ||||
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion> | |||||
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion> | |||||
<FileAlignment>512</FileAlignment> | <FileAlignment>512</FileAlignment> | ||||
<StartupObject> | <StartupObject> | ||||
</StartupObject> | </StartupObject> | ||||
@@ -79,14 +79,14 @@ | |||||
<Reference Include="Costura, Version=4.1.0.0, Culture=neutral, PublicKeyToken=9919ef960d84173d, processorArchitecture=MSIL"> | <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> | <HintPath>..\packages\Costura.Fody.4.1.0\lib\net40\Costura.dll</HintPath> | ||||
</Reference> | </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> | ||||
<Reference Include="GlobalHotKey, Version=1.1.0.0, Culture=neutral, processorArchitecture=MSIL"> | <Reference Include="GlobalHotKey, Version=1.1.0.0, Culture=neutral, processorArchitecture=MSIL"> | ||||
<HintPath>..\packages\GlobalHotKey.1.1.0\lib\GlobalHotKey.dll</HintPath> | <HintPath>..\packages\GlobalHotKey.1.1.0\lib\GlobalHotKey.dll</HintPath> | ||||
</Reference> | </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> | ||||
<Reference Include="ICSharpCode.AvalonEdit, Version=6.0.1.278, Culture=neutral, PublicKeyToken=9cc39be672370310, processorArchitecture=MSIL"> | <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> | <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> | <HintPath>..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll</HintPath> | ||||
</Reference> | </Reference> | ||||
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL"> | <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> | ||||
<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> | ||||
<Reference Include="PresentationCore" /> | <Reference Include="PresentationCore" /> | ||||
<Reference Include="PresentationFramework" /> | <Reference Include="PresentationFramework" /> | ||||
<Reference Include="PresentationFramework.Aero" /> | <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> | ||||
<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> | ||||
<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> | ||||
<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> | ||||
<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> | ||||
<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> | ||||
<Reference Include="System" /> | <Reference Include="System" /> | ||||
<Reference Include="System.Buffers, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL"> | <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"> | <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> | <HintPath>..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll</HintPath> | ||||
</Reference> | </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> | ||||
<Reference Include="System.Runtime, Version=4.1.1.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> | <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> | <HintPath>..\packages\System.Runtime.4.3.1\lib\net462\System.Runtime.dll</HintPath> | ||||
<Private>True</Private> | <Private>True</Private> | ||||
<Private>True</Private> | <Private>True</Private> | ||||
</Reference> | </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> | ||||
<Reference Include="System.Runtime.Serialization" /> | <Reference Include="System.Runtime.Serialization" /> | ||||
<Reference Include="System.Security.Cryptography.Algorithms, Version=4.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> | <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\OpenSSL.cs" /> | ||||
<Compile Include="Encryption\RNG.cs" /> | <Compile Include="Encryption\RNG.cs" /> | ||||
<Compile Include="Encryption\Sodium.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\LocalizationProvider.cs" /> | ||||
<Compile Include="Localization\Strings.Designer.cs"> | <Compile Include="Localization\Strings.Designer.cs"> | ||||
<AutoGen>True</AutoGen> | <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\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\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\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> | </Target> | ||||
<Import Project="..\packages\Fody.6.3.0\build\Fody.targets" Condition="Exists('..\packages\Fody.6.3.0\build\Fody.targets')" /> | <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. | <!-- 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> | <AppDesignerFolder>Properties</AppDesignerFolder> | ||||
<RootNamespace>Shadowsocks.Test</RootNamespace> | <RootNamespace>Shadowsocks.Test</RootNamespace> | ||||
<AssemblyName>Shadowsocks.Test</AssemblyName> | <AssemblyName>Shadowsocks.Test</AssemblyName> | ||||
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion> | |||||
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion> | |||||
<FileAlignment>512</FileAlignment> | <FileAlignment>512</FileAlignment> | ||||
<ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> | <ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> | ||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion> | <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion> | ||||
@@ -56,7 +56,6 @@ | |||||
</Choose> | </Choose> | ||||
<ItemGroup> | <ItemGroup> | ||||
<Compile Include="ProcessEnvironment.cs" /> | <Compile Include="ProcessEnvironment.cs" /> | ||||
<Compile Include="CryptographyTest.cs" /> | |||||
<Compile Include="Sip003PluginTest.cs" /> | <Compile Include="Sip003PluginTest.cs" /> | ||||
<Compile Include="UrlTest.cs" /> | <Compile Include="UrlTest.cs" /> | ||||
<Compile Include="UnitTest.cs" /> | <Compile Include="UnitTest.cs" /> | ||||
@@ -99,4 +98,4 @@ | |||||
<Target Name="AfterBuild"> | <Target Name="AfterBuild"> | ||||
</Target> | </Target> | ||||
--> | --> | ||||
</Project> | |||||
</Project> |
@@ -4,7 +4,7 @@ | |||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> | <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> | ||||
<dependentAssembly> | <dependentAssembly> | ||||
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" /> | <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> | ||||
<dependentAssembly> | <dependentAssembly> | ||||
<assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" /> | <assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" /> | ||||
@@ -16,4 +16,4 @@ | |||||
</dependentAssembly> | </dependentAssembly> | ||||
</assemblyBinding> | </assemblyBinding> | ||||
</runtime> | </runtime> | ||||
</configuration> | |||||
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" /></startup></configuration> |