Compare commits

...

16 Commits
main ... v4

Author SHA1 Message Date
  Max Lv 99871884bc
Merge pull request #3281 from shadowsocks/feature/plain-cipher 3 years ago
  Max Lv 3f6baa4102 cipher: add plain/none ciphers 3 years ago
  Bruce Wayne 1155ac546f
Update privoxy to 3.0.31 4 years ago
  database64128 dd6edbc7b4
💭 PAC: display message when geosite already latest 4 years ago
  database64128 ac0fcdfc8c
⚠ Warn when importing from legacy ss:// links 4 years ago
  database64128 a28efeee4b
🆙 Update docs and bump version to 4.4.0.0 4 years ago
  database64128 70a88b5794
🚱 Remove infrastructure of stream ciphers 4 years ago
  database64128 78915d805f
🔀 Merge pull request #3048 from studentmain/patch-1 4 years ago
  Student Main 5fa4ada43b
Update ShadowsocksTest.csproj 4 years ago
  Student Main ff37258c7f
Delete CryptographyTest.cs 4 years ago
  Student Main f2414a9e8e
Update EncryptorFactory.cs 4 years ago
  database64128 d79ba8fbcc
🎍 Clean some leftover stuff 4 years ago
  database64128 da568ad047
🆙 Update docs and bump version to 4.3.3.0 4 years ago
  database64128 38bee0888f
🎱 Update to .NET Framework 4.8 4 years ago
  database64128 f029738f2b
🧂 Add option for custom sha256sum URL of custom geosite source 4 years ago
  database64128 0284f4e035
🕳 Update `.gitignore` 4 years ago
28 changed files with 618 additions and 977 deletions
Split View
  1. +363
    -9
      .gitignore
  2. +13
    -0
      CHANGES
  3. +2
    -5
      README.md
  4. +1
    -1
      appveyor.yml
  5. +42
    -26
      shadowsocks-csharp/Controller/Service/GeositeUpdater.cs
  6. +1
    -1
      shadowsocks-csharp/Controller/Service/UpdateChecker.cs
  7. +2
    -0
      shadowsocks-csharp/Controller/ShadowsocksController.cs
  8. +1
    -0
      shadowsocks-csharp/Data/i18n.csv
  9. BIN
      shadowsocks-csharp/Data/privoxy.exe.gz
  10. +18
    -2
      shadowsocks-csharp/Encryption/AEAD/AEADEncryptor.cs
  11. +9
    -21
      shadowsocks-csharp/Encryption/EncryptorFactory.cs
  12. +98
    -0
      shadowsocks-csharp/Encryption/Stream/PlainEncryptor.cs
  13. +0
    -182
      shadowsocks-csharp/Encryption/Stream/StreamEncryptor.cs
  14. +0
    -155
      shadowsocks-csharp/Encryption/Stream/StreamMbedTLSEncryptor.cs
  15. +0
    -159
      shadowsocks-csharp/Encryption/Stream/StreamOpenSSLEncryptor.cs
  16. +0
    -107
      shadowsocks-csharp/Encryption/Stream/StreamSodiumEncryptor.cs
  17. +2
    -0
      shadowsocks-csharp/Model/Configuration.cs
  18. +4
    -4
      shadowsocks-csharp/Model/Server.cs
  19. +2
    -2
      shadowsocks-csharp/Program.cs
  20. +3
    -2
      shadowsocks-csharp/Properties/Resources.Designer.cs
  21. +1
    -1
      shadowsocks-csharp/Properties/Settings.Designer.cs
  22. +7
    -18
      shadowsocks-csharp/View/ConfigForm.cs
  23. +6
    -2
      shadowsocks-csharp/app.config
  24. +12
    -12
      shadowsocks-csharp/packages.config
  25. +27
    -30
      shadowsocks-csharp/shadowsocks-csharp.csproj
  26. +0
    -233
      test/CryptographyTest.cs
  27. +2
    -3
      test/ShadowsocksTest.csproj
  28. +2
    -2
      test/app.config

+ 363
- 9
.gitignore View File

@@ -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

+ 13
- 0
CHANGES View File

@@ -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)


+ 2
- 5
README.md View File

@@ -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

+ 1
- 1
appveyor.yml View File

@@ -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:


+ 42
- 26
shadowsocks-csharp/Controller/Service/GeositeUpdater.cs View File

@@ -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


+ 1
- 1
shadowsocks-csharp/Controller/Service/UpdateChecker.cs View 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()


+ 2
- 0
shadowsocks-csharp/Controller/ShadowsocksController.cs View File

@@ -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);


+ 1
- 0
shadowsocks-csharp/Data/i18n.csv View File

@@ -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 à


BIN
shadowsocks-csharp/Data/privoxy.exe.gz View File


+ 18
- 2
shadowsocks-csharp/Encryption/AEAD/AEADEncryptor.cs View File

@@ -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)


+ 9
- 21
shadowsocks-csharp/Encryption/EncryptorFactory.cs View File

@@ -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();
}
}
}
}

+ 98
- 0
shadowsocks-csharp/Encryption/Stream/PlainEncryptor.cs View File

@@ -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

}
}

+ 0
- 182
shadowsocks-csharp/Encryption/Stream/StreamEncryptor.cs View File

@@ -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
}
}

+ 0
- 155
shadowsocks-csharp/Encryption/Stream/StreamMbedTLSEncryptor.cs View File

@@ -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
}
}

+ 0
- 159
shadowsocks-csharp/Encryption/Stream/StreamOpenSSLEncryptor.cs View File

@@ -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
}
}

+ 0
- 107
shadowsocks-csharp/Encryption/Stream/StreamSodiumEncryptor.cs View File

@@ -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()
{
}
}
}

+ 2
- 0
shadowsocks-csharp/Model/Configuration.cs View File

@@ -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",


+ 4
- 4
shadowsocks-csharp/Model/Server.cs View File

@@ -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;
}


+ 2
- 2
shadowsocks-csharp/Program.cs View File

@@ -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;
}


+ 3
- 2
shadowsocks-csharp/Properties/Resources.Designer.cs View File

@@ -73,13 +73,14 @@ namespace Shadowsocks.Properties {
///var rules = [];
///
///// convert to abp grammar
///var re = /^(@@)?\|\|.*?[^\^]$/;
///for (var i = 0; i &lt; __RULES__.length; i++) {
/// var s = __RULES__[i];
/// if (s.substring(0, 2) == &quot;||&quot;) s += &quot;^&quot;;
/// if (s.match(re)) s += &quot;^&quot;;
/// rules.push(s);
///}
///
///for (var i = 0; i &lt; [rest of string was truncated]&quot;;.
/// [rest of string was truncated]&quot;;.
/// </summary>
public static string abp_js {
get {


+ 1
- 1
shadowsocks-csharp/Properties/Settings.Designer.cs View File

@@ -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())));


+ 7
- 18
shadowsocks-csharp/View/ConfigForm.cs View File

@@ -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
- 2
shadowsocks-csharp/app.config View File

@@ -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>


+ 12
- 12
shadowsocks-csharp/packages.config View File

@@ -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" />


+ 27
- 30
shadowsocks-csharp/shadowsocks-csharp.csproj View File

@@ -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.


+ 0
- 233
test/CryptographyTest.cs View File

@@ -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;
}
}
}
}

+ 2
- 3
test/ShadowsocksTest.csproj View File

@@ -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>

+ 2
- 2
test/app.config View File

@@ -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>

Loading…
Cancel
Save