Compare commits

...
5 Commits
Author SHA1 Message Date
Syrone Wong 44afefed71 Update CHANGES and bump version
Signed-off-by: Syrone Wong <wong.syrone@gmail.com>
2017-05-19 16:47:31 +08:00
Syrone Wong 2eeebc29d7 Replace circular buffer with the blockcopy variant
to get rid of deep copy

- update NuGet pkg

Signed-off-by: Syrone Wong <wong.syrone@gmail.com>
2017-05-19 15:56:13 +08:00
Ninedyz 0e01f8303c update Japanese translation (#1138)
* Update ja.txt

* Update ja.txt

* Update ja.txt

Sorry for the multiple posts(´・ω・`)

* Update ja.txt

* Update ja.txt
2017-05-19 06:20:30 +08:00
Syrone Wong 2fcf843bba libsodium: enable AVX2 for x86
Signed-off-by: Syrone Wong <wong.syrone@gmail.com>
2017-05-15 16:14:37 +08:00
Syrone Wong 3b3a8c9077 fix legacy key derivation 2017-04-21 12:39:53 +08:00
11 changed files with 637 additions and 123 deletions
+4
View File
@@ -1,3 +1,7 @@
4.0.2 2017-05-19
- Fix legacy key derivation
- Bug fixes and improvements
4.0.1 2017-04-08
- Fix UDP relay
- Allow to add multiple servers via Shadowsocks URL
@@ -24,7 +24,7 @@ namespace Shadowsocks.Controller
public string LatestVersionLocalName;
public event EventHandler CheckUpdateCompleted;
public const string Version = "4.0.1";
public const string Version = "4.0.2";
private class CheckUpdateTimer : System.Timers.Timer
{
+84 -84
View File
@@ -4,40 +4,40 @@ Shadowsocks=Shadowsocks
# Menu items
Enable System Proxy=システムの代理を有効にする
Enable System Proxy=システム プロキシを有効にする
Mode=モード
PAC=PAC
Global=全般
Servers=サーバ
Edit Servers...=サーバーを編集する...
Servers=サーバー
Edit Servers...=サーバーの編集...
Statistics Config...=統計情報の設定...
Start on Boot=システムと同時に起動
Forward Proxy...=代理を転送する...
Allow Clients from LAN=LANからのクライアントを許可する
Forward Proxy...=フォワードプロキシの設定...
Allow Clients from LAN=LAN からのアクセスを許可
Local PAC=ローカル PAC
Online PAC=オンライン PAC
Edit Local PAC File...=ローカル PAC ファイルを編集する...
Update Local PAC from GFWList=GFWList から、ローカル PACを更新する
Edit User Rule for GFWList...=利用者規則を編集する...
Secure Local PAC=安全なローカル PAC
Copy Local PAC URL=ローカルのPAC URLをコピー
Share Server Config...=サーバーの設定を共有する...
Scan QRCode from Screen...=画面からの QRコードをスキャン...
Import URL from Clipboard...=クリップボードからの URLを貼り付け...
Edit Local PAC File...=ローカル PAC ファイルの編集...
Update Local PAC from GFWList=GFWList からローカル PAC を更新
Edit User Rule for GFWList...=ユーザールールの編集...
Secure Local PAC=ローカル PAC を保護
Copy Local PAC URL=ローカル PAC URL をコピー
Share Server Config...=サーバーの設定を共有...
Scan QRCode from Screen...=画面から QR コードをスキャン...
Import URL from Clipboard...=クリップボードから URL をインポート...
Availability Statistics=可用性の統計
Show Logs...=ログを表示する...
Verbose Logging=詳細なログ
Show Logs...=ログの表示...
Verbose Logging=詳細なログを記録
Updates...=更新...
Check for Updates...=更新プログラムを確認しています...
Check for Updates at Startup=起動と同時に更新プログラムを確認しています
Check Pre-release Version=先行開発版の更新を確認しています...
Edit Hotkeys...=ホットキーを編集する...
About...=について...
Check for Updates...=更新プログラムの確認...
Check for Updates at Startup=起動時に更新プログラムを確認
Check Pre-release Version=先行開発版も確認
Edit Hotkeys...=ホットキーの編集...
About...=Shadowsocks について...
Help=ヘルプ
Quit=終了
Edit Servers=サーバを編集する
Load Balance=バランス
High Availability=高パフォーマンス
Edit Servers=サーバーの編集
Load Balance=負荷分散
High Availability=高可用性
Choose by statistics=統計で選ぶ
# Config Form
@@ -45,42 +45,42 @@ Choose by statistics=統計で選ぶ
&Add=新規 (&A)
&Delete=削除 (&D)
Dupli&cate=コピー (&C)
Server=サーバ
Server=サーバー
Server Addr=サーバーアドレス
Server Port=サーバポート
Password=暗証番号
Server Port=サーバーポート
Password=パスワード
Encryption=暗号化
Proxy Port=代理ポート
Remarks=短評する
Proxy Port=プロキシポート
Remarks=付記
Timeout(Sec)=タイムアウト (秒)
OK=はい
Cancel=いいえ
New server=新規サーバ
OK=OK
Cancel=キャンセル
New server=新規サーバー
Move &Up=上に移動 (&U)
Move D&own=下に移動 (&O)
# Proxy Form
Edit Proxy=代理を編集する
Use Proxy=代理を利用する
Proxy Type=代理類型
Proxy Addr=代理アドレス
Proxy Port=代理ポート
Edit Proxy=プロキシの編集
Use Proxy=プロキシを利用する
Proxy Type=プロキシの種類
Proxy Addr=プロキシアドレス
Proxy Port=プロキシポート
# Log Form
&File=ファイル (&F)
&Open Location=この場所を開く (&O)
&Open Location=ファイルの場所を開く (&O)
E&xit=終了 (&X)
&View=ビュー (&V)
&Clean Logs=ログを削除する (&C)
Change &Font=フォントを変更する (&F)
&Wrap Text=文字改行 (&W)
&Top Most=一番上 (&T)
&Show Toolbar=ツールバーを表示する (&S)
&View=表示 (&V)
&Clean Logs=ログの削除 (&C)
Change &Font=フォント (&F)
&Wrap Text=右端で折り返す (&W)
&Top Most=常に最前面に表示 (&T)
&Show Toolbar=ツールバーの表示 (&S)
Log Viewer=ログビューア
Inbound=輸入
Outbound=輸出
Inbound=受信
Outbound=送信
# QRCode Form
@@ -88,16 +88,16 @@ QRCode and URL=QR コードと URL
# PAC Url Form
Edit Online PAC URL=オンライン PAC URLを編集する
Edit Online PAC URL...=オンライン PAC URLを編集する...
Edit Online PAC URL=オンライン PAC URL の編集
Edit Online PAC URL...=オンライン PAC URL の編集...
Please input PAC Url=PAC URLを入力して下さい
# HotkeySettings Form
Switch system proxy=代理を切換える
Switch system proxy mode=代理モードを切換える
Switch share over LAN=LAN経由でシェアを切換える
Show Logs=ログを表示する
Switch system proxy=システム プロキシの状態を切り替える
Switch system proxy mode=プロキシモードを切り替える
Switch share over LAN=LAN からのアクセスの許可を切り替える
Show Logs=ログの表示
Switch to prev server=前のサーバーに切り替える
Switch to next server=次のサーバーに切り替える
Reg All=全部登録する
@@ -105,38 +105,38 @@ Reg All=全部登録する
# Messages
Shadowsocks Error: {0}=Shadowsocks エラー: {0}
Port already in use=既に使用中のポート
Invalid server address=違法なサーバアドレス
Illegal port number format=不法なポート番号形式
Illegal timeout format=不法なタイムアウト形式
Please add at least one server=少なくとも一つのサーバーを追加して下さい
Server IP can not be blank=サーバ IP は空欄にできない
Password can not be blank=暗証番号は空欄にできない
Port out of range=ポートが範囲外
Port can't be 8123=ポート8123できない
Shadowsocks {0} Update Found=Shadowsocks {0} 更新プログラムを利用できます
No update is available=お使いのソフトウェアは最新です
Click here to update=プログラムの更新
Shadowsocks is here=Shadowsocks 此処です
You can turn on/off Shadowsocks in the context menu=コンテキストメニューにshadowsocksを有効化または無効化
System Proxy Enabled=システム 代理を有効にする
System Proxy Disabled=システム 代理を無効にする
Failed to update PAC file =PAC の更新に失敗しました
PAC updated=PAC の更新に正しくインストールされました
No updates found. Please report to GFWList if you have problems with it.=お使いのソフトウェアは最新です。もし貴方は問題がある、GFWListに報告して下さい。
No QRCode found. Try to zoom in or move it to the center of the screen.=QR コードを探し当てていません。ズームインまたはそれが画面の中心に移動して下さい。
Shadowsocks is already running.=Shadowsocks 実行中。
Find Shadowsocks icon in your notify tray.=shadowsocks通知トレイにアイコンを見つけて下さい。
If you want to start multiple Shadowsocks, make a copy in another directory.=同時に起動したい場合は、別のディレクトリにコピーしてもいいと思ってます。
Failed to decode QRCode=QR コードの復号化に失敗しました
Failed to update registry=登錄の更新に失敗しました
System Proxy On: =システム代理をオンにする:
Port already in use=ポートは既に使用されています。
Invalid server address=サーバーアドレスが無効です。
Illegal port number format=ポート番号のフォーマットが無効です。
Illegal timeout format=タイムアウト値のフォーマットが無効です。
Please add at least one server=少なくとも一つのサーバーを指定して下さい。
Server IP can not be blank=サーバー IP が指定されていません。
Password can not be blank=パスワードが指定されていません。
Port out of range=ポート番号は範囲外です。
Port can't be 8123=8123 番以外のポート番号を指定して下さい。
Shadowsocks {0} Update Found=Shadowsocks バージョン {0} は利用できます。
No update is available=お使いのバージョンは最新です。
Click here to update=クリックしてアップデートします。
Shadowsocks is here=Shadowsocks はここです。
You can turn on/off Shadowsocks in the context menu=コンテキストメニューを使って、Shadowsocks を有効または無効にすることができます。
System Proxy Enabled=システム プロキシが有効です。
System Proxy Disabled=システム プロキシが無効です。
Failed to update PAC file =PAC の更新に失敗しました。
PAC updated=PAC を更新しました。
No updates found. Please report to GFWList if you have problems with it.=お使いのバージョンは最新です。問題がある場合は、GFWList に報告して下さい。
No QRCode found. Try to zoom in or move it to the center of the screen.=QR コードが見つかりませんでした。コードを大きくするか、画面の中央に移動して下さい。
Shadowsocks is already running.=Shadowsocks 実行中
Find Shadowsocks icon in your notify tray.=通知領域には Shadowsocks のアイコンがあります。
If you want to start multiple Shadowsocks, make a copy in another directory.=複数起動したい場合は、プログラムファイルを別のフォルダーにコピーしてから、もう一度実行して下さい。
Failed to decode QRCode=QR コードの読み取りに失敗しました。
Failed to update registry=レジストリの更新に失敗しました。
System Proxy On: =システム プロキシが有効:
Running: Port {0}=実行中:ポート {0}
Unexpected error, shadowsocks will exit. Please report to=予想外のエラー、Shadowsocks を終了する。この場所を報告して下さい。
Unsupported operating system, use Windows Vista at least.=サポートしていないのOS、Windows Vista 以降のOSを利用して下さい。
Unsupported .NET Framework, please update to 4.6.2 or later.=サポートしていないの .NET Framework、4.6.2 以降のバンジョーを利用して下さい。
Proxy request failed=代理要求が失敗した。
Proxy handshake failed=代理の握手に失敗しました
Register hotkey failed=ホットキーの登錄に失敗しました
Unexpected error, shadowsocks will exit. Please report to=予想外のエラーが発生したため、Shadowsocks を終了します。詳しくは下記までお問い合わせ下さい:
Unsupported operating system, use Windows Vista at least.=お使いの OS はサポートされていません。Windows Vista 以降の OS で実行して下さい。
Unsupported .NET Framework, please update to 4.6.2 or later.=お使いの .NET Framework はサポートされていません。4.6.2 以降のバンジョーをインストールして下さい。
Proxy request failed=プロキシ要求が失敗しました。
Proxy handshake failed=プロキシ ハンドシェイクに失敗しました。
Register hotkey failed=ホットキーの登錄に失敗しました。
Cannot parse hotkey: {0}=ホットキーを解析できません: {0}
Timeout is invalid, it should not exceed {0}=タイムアウトが無効であるか、それを超えてはならない {0}
Timeout is invalid, it should not exceed {0}=タイムアウト値が無効です。{0} 以下の値を指定して下さい。
Binary file not shown.
@@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.Net;
using System.Text;
using Cyotek.Collections.Generic;
using Shadowsocks.Encryption.CircularBuffer;
using Shadowsocks.Controller;
using Shadowsocks.Encryption.Exception;
using Shadowsocks.Encryption.Stream;
@@ -21,8 +21,8 @@ namespace Shadowsocks.Encryption.AEAD
protected static byte[] _udpTmpBuf = new byte[65536];
// every connection should create its own buffer
private CircularBuffer<byte> _encCircularBuffer = new CircularBuffer<byte>(MAX_INPUT_SIZE * 2, false);
private CircularBuffer<byte> _decCircularBuffer = new CircularBuffer<byte>(MAX_INPUT_SIZE * 2, false);
private ByteCircularBuffer _encCircularBuffer = new ByteCircularBuffer(MAX_INPUT_SIZE * 2);
private ByteCircularBuffer _decCircularBuffer = new ByteCircularBuffer(MAX_INPUT_SIZE * 2);
public const int CHUNK_LEN_BYTES = 2;
public const uint CHUNK_LEN_MASK = 0x3FFFu;
@@ -88,15 +88,15 @@ namespace Shadowsocks.Encryption.AEAD
byte[] passbuf = Encoding.UTF8.GetBytes(password);
// init master key
if (_Masterkey == null) _Masterkey = new byte[keyLen];
if (_Masterkey.Length < keyLen) Array.Resize(ref _Masterkey, keyLen);
DeriveKey(passbuf, _Masterkey);
if (_Masterkey.Length != keyLen) Array.Resize(ref _Masterkey, keyLen);
DeriveKey(passbuf, _Masterkey, keyLen);
// init session key
if (_sessionKey == null) _sessionKey = new byte[keyLen];
}
public void DeriveKey(byte[] password, byte[] key)
public void DeriveKey(byte[] password, byte[] key, int keylen)
{
StreamEncryptor.LegacyDeriveKey(password, key);
StreamEncryptor.LegacyDeriveKey(password, key, keylen);
}
public void DeriveSessionKey(byte[] salt, byte[] masterKey, byte[] sessionKey)
@@ -254,7 +254,7 @@ namespace Shadowsocks.Encryption.AEAD
// we have enough data to decrypt one chunk
// drop chunk len and its tag from buffer
_decCircularBuffer.Get(CHUNK_LEN_BYTES + tagLen);
_decCircularBuffer.Skip(CHUNK_LEN_BYTES + tagLen);
byte[] encChunkBytes = _decCircularBuffer.Get(chunkLen + tagLen);
byte[] decChunkBytes = new byte[chunkLen];
uint decChunkLen = 0;
@@ -0,0 +1,510 @@
#region Original License
//New BSD License(BSD)
//
//Copyright(c) 2014-2015 Cyotek Ltd
//Copyright(c) 2012, Alex Regueiro
//All rights reserved.
//
//Redistribution and use in source and binary forms, with or without
//modification, are permitted provided that the following conditions are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of Cyotek nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
//ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
//WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
//DISCLAIMED.IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
//DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
//(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
//ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
//(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion
using System;
using System.Collections.Generic;
namespace Shadowsocks.Encryption.CircularBuffer
{
/// <summary>
/// Represents a first-in, first-out collection of objects using a fixed buffer.
/// </summary>
/// <remarks>
/// <para>The capacity of a <see cref="ByteCircularBuffer" /> is the number of elements the <see cref="ByteCircularBuffer"/> can hold. </para>
/// <para>ByteCircularBuffer accepts <c>null</c> as a valid value for reference types and allows duplicate elements.</para>
/// <para>The <see cref="Get()"/> methods will remove the items that are returned from the ByteCircularBuffer. To view the contents of the ByteCircularBuffer without removing items, use the <see cref="Peek()"/> or <see cref="PeekLast"/> methods.</para>
/// </remarks>
public class ByteCircularBuffer
{
// based on http://circularbuffer.codeplex.com/
// http://en.wikipedia.org/wiki/Circular_buffer
// modified from https://github.com/cyotek/Cyotek.Collections.Generic.CircularBuffer
// some code taken from https://github.com/xorxornop/RingBuffer
// and https://github.com/xorxornop/PerfCopy
#region Instance Fields
private byte[] _buffer;
private int _capacity;
#endregion
#region Public Constructors
/// <summary>
/// Initializes a new instance of the <see cref="ByteCircularBuffer"/> class that is empty and has the specified initial capacity.
/// </summary>
/// <param name="capacity">The maximum capcity of the buffer.</param>
/// <exception cref="System.ArgumentException">Thown if the <paramref name="capacity"/> is less than zero.</exception>
public ByteCircularBuffer(int capacity)
{
if (capacity < 0)
{
throw new ArgumentException("The buffer capacity must be greater than or equal to zero.",
nameof(capacity));
}
_buffer = new byte[capacity];
this.Capacity = capacity;
this.Size = 0;
this.Head = 0;
this.Tail = 0;
}
#endregion
#region Public Properties
/// <summary>
/// Gets or sets the total number of elements the internal data structure can hold.
/// </summary>
/// <value>The total number of elements that the <see cref="ByteCircularBuffer"/> can contain.</value>
/// <exception cref="System.ArgumentOutOfRangeException">Thrown if the specified new capacity is smaller than the current contents of the buffer.</exception>
public int Capacity
{
get { return _capacity; }
set
{
if (value != _capacity)
{
if (value < this.Size)
{
throw new ArgumentOutOfRangeException(nameof(value), value,
"The new capacity must be greater than or equal to the buffer size.");
}
var newBuffer = new byte[value];
if (this.Size > 0)
{
this.CopyTo(newBuffer);
}
_buffer = newBuffer;
_capacity = value;
}
}
}
/// <summary>
/// Gets the index of the beginning of the buffer data.
/// </summary>
/// <value>The index of the first element in the buffer.</value>
public int Head { get; protected set; }
/// <summary>
/// Gets a value indicating whether the buffer is empty.
/// </summary>
/// <value><c>true</c> if buffer is empty; otherwise, <c>false</c>.</value>
public virtual bool IsEmpty => this.Size == 0;
/// <summary>
/// Gets a value indicating whether the buffer is full.
/// </summary>
/// <value><c>true</c> if the buffer is full; otherwise, <c>false</c>.</value>
/// <remarks>The <see cref="IsFull"/> property always returns <c>false</c> if the <see cref="AllowOverwrite"/> property is set to <c>true</c>.</remarks>
public virtual bool IsFull => this.Size == this.Capacity;
/// <summary>
/// Gets the number of elements contained in the <see cref="ByteCircularBuffer"/>.
/// </summary>
/// <value>The number of elements contained in the <see cref="ByteCircularBuffer"/>.</value>
public int Size { get; protected set; }
/// <summary>
/// Gets the index of the end of the buffer data.
/// </summary>
/// <value>The index of the last element in the buffer.</value>
public int Tail { get; protected set; }
#endregion
#region Public Members
/// <summary>
/// Removes all items from the <see cref="ByteCircularBuffer" />.
/// </summary>
public void Clear()
{
this.Size = 0;
this.Head = 0;
this.Tail = 0;
_buffer = new byte[this.Capacity];
}
/// <summary>
/// Determines whether the <see cref="ByteCircularBuffer" /> contains a specific value.
/// </summary>
/// <param name="item">The object to locate in the <see cref="ByteCircularBuffer" />.</param>
/// <returns><c>true</c> if <paramref name="item" /> is found in the <see cref="ByteCircularBuffer" />; otherwise, <c>false</c>.</returns>
public bool Contains(byte item)
{
var bufferIndex = this.Head;
var comparer = EqualityComparer<byte>.Default;
var result = false;
for (int i = 0; i < this.Size; i++, bufferIndex++)
{
if (bufferIndex == this.Capacity)
{
bufferIndex = 0;
}
if (comparer.Equals(_buffer[bufferIndex], item))
{
result = true;
break;
}
}
return result;
}
/// <summary>
/// Copies the entire <see cref="ByteCircularBuffer"/> to a compatible one-dimensional array, starting at the beginning of the target array.
/// </summary>
/// <param name="array">The one-dimensional <see cref="Array"/> that is the destination of the elements copied from <see cref="ByteCircularBuffer"/>. The <see cref="Array"/> must have zero-based indexing.</param>
public void CopyTo(byte[] array)
{
this.CopyTo(array, 0);
}
/// <summary>
/// Copies the entire <see cref="ByteCircularBuffer"/> to a compatible one-dimensional array, starting at the specified index of the target array.
/// </summary>
/// <param name="array">The one-dimensional <see cref="Array"/> that is the destination of the elements copied from <see cref="ByteCircularBuffer"/>. The <see cref="Array"/> must have zero-based indexing.</param>
/// <param name="arrayIndex">The zero-based index in <paramref name="array"/> at which copying begins.</param>
public void CopyTo(byte[] array, int arrayIndex)
{
this.CopyTo(this.Head, array, arrayIndex, Math.Min(this.Size, array.Length - arrayIndex));
}
/// <summary>
/// Copies a range of elements from the <see cref="ByteCircularBuffer"/> to a compatible one-dimensional array, starting at the specified index of the target array.
/// </summary>
/// <param name="index">The zero-based index in the source <see cref="ByteCircularBuffer"/> at which copying begins.</param>
/// <param name="array">The one-dimensional <see cref="Array"/> that is the destination of the elements copied from <see cref="ByteCircularBuffer"/>. The <see cref="Array"/> must have zero-based indexing.</param>
/// <param name="arrayIndex">The zero-based index in <paramref name="array"/> at which copying begins.</param>
/// <param name="count">The number of elements to copy.</param>
public virtual void CopyTo(int index, byte[] array, int arrayIndex, int count)
{
if (count > this.Size)
{
throw new ArgumentOutOfRangeException(nameof(count), count,
"The read count cannot be greater than the buffer size.");
}
var startAnchor = index;
var dstIndex = arrayIndex;
while (count > 0)
{
int chunk = Math.Min(Capacity - startAnchor, count);
Buffer.BlockCopy(_buffer, startAnchor, array, dstIndex, chunk);
startAnchor = (startAnchor + chunk == Capacity) ? 0 : startAnchor + chunk;
dstIndex += chunk;
count -= chunk;
}
}
/// <summary>
/// Removes and returns the specified number of objects from the beginning of the <see cref="ByteCircularBuffer"/>.
/// </summary>
/// <param name="count">The number of elements to remove and return from the <see cref="ByteCircularBuffer"/>.</param>
/// <returns>The objects that are removed from the beginning of the <see cref="ByteCircularBuffer"/>.</returns>
public byte[] Get(int count)
{
if (count <= 0) throw new ArgumentOutOfRangeException("should greater than 0");
var result = new byte[count];
this.Get(result);
return result;
}
/// <summary>
/// Copies and removes the specified number elements from the <see cref="ByteCircularBuffer"/> to a compatible one-dimensional array, starting at the beginning of the target array.
/// </summary>
/// <param name="array">The one-dimensional <see cref="Array"/> that is the destination of the elements copied from <see cref="ByteCircularBuffer"/>. The <see cref="Array"/> must have zero-based indexing.</param>
/// <returns>The actual number of elements copied into <paramref name="array"/>.</returns>
public int Get(byte[] array)
{
if (array.Length <= 0) throw new ArgumentOutOfRangeException("should greater than 0");
return this.Get(array, 0, array.Length);
}
/// <summary>
/// Copies and removes the specified number elements from the <see cref="ByteCircularBuffer"/> to a compatible one-dimensional array, starting at the specified index of the target array.
/// </summary>
/// <param name="array">The one-dimensional <see cref="Array"/> that is the destination of the elements copied from <see cref="ByteCircularBuffer"/>. The <see cref="Array"/> must have zero-based indexing.</param>
/// <param name="arrayIndex">The zero-based index in <paramref name="array"/> at which copying begins.</param>
/// <param name="count">The number of elements to copy.</param>
/// <returns>The actual number of elements copied into <paramref name="array"/>.</returns>
public virtual int Get(byte[] array, int arrayIndex, int count)
{
if (arrayIndex < 0)
{
throw new ArgumentOutOfRangeException(nameof(arrayIndex), "Negative offset specified. Offsets must be positive.");
}
if (count < 0)
{
throw new ArgumentOutOfRangeException(nameof(count), "Negative count specified. Count must be positive.");
}
if (count > this.Size)
{
throw new ArgumentException("Ringbuffer contents insufficient for take/read operation.", nameof(count));
}
if (array.Length < arrayIndex + count)
{
throw new ArgumentException("Destination array too small for requested output.");
}
var bytesCopied = 0;
var dstIndex = arrayIndex;
while (count > 0)
{
int chunk = Math.Min(Capacity - this.Head, count);
Buffer.BlockCopy(_buffer, this.Head, array, dstIndex, chunk);
this.Head = (this.Head + chunk == Capacity) ? 0 : this.Head + chunk;
this.Size -= chunk;
dstIndex += chunk;
bytesCopied += chunk;
count -= chunk;
}
return bytesCopied;
}
/// <summary>
/// Removes and returns the object at the beginning of the <see cref="ByteCircularBuffer"/>.
/// </summary>
/// <returns>The object that is removed from the beginning of the <see cref="ByteCircularBuffer"/>.</returns>
/// <exception cref="System.InvalidOperationException">Thrown if the buffer is empty.</exception>
/// <remarks>This method is similar to the <see cref="Peek()"/> method, but <c>Peek</c> does not modify the <see cref="ByteCircularBuffer"/>.</remarks>
public virtual byte Get()
{
if (this.IsEmpty)
{
throw new InvalidOperationException("The buffer is empty.");
}
var item = _buffer[this.Head];
if (++this.Head == this.Capacity)
{
this.Head = 0;
}
this.Size--;
return item;
}
/// <summary>
/// Returns the object at the beginning of the <see cref="ByteCircularBuffer"/> without removing it.
/// </summary>
/// <returns>The object at the beginning of the <see cref="ByteCircularBuffer"/>.</returns>
/// <exception cref="System.InvalidOperationException">Thrown if the buffer is empty.</exception>
public virtual byte Peek()
{
if (this.IsEmpty)
{
throw new InvalidOperationException("The buffer is empty.");
}
var item = _buffer[this.Head];
return item;
}
/// <summary>
/// Returns the specified number of objects from the beginning of the <see cref="ByteCircularBuffer"/>.
/// </summary>
/// <param name="count">The number of elements to return from the <see cref="ByteCircularBuffer"/>.</param>
/// <returns>The objects that from the beginning of the <see cref="ByteCircularBuffer"/>.</returns>
/// <exception cref="System.InvalidOperationException">Thrown if the buffer is empty.</exception>
public virtual byte[] Peek(int count)
{
if (this.IsEmpty)
{
throw new InvalidOperationException("The buffer is empty.");
}
var items = new byte[count];
this.CopyTo(items);
return items;
}
/// <summary>
/// Returns the object at the end of the <see cref="ByteCircularBuffer"/> without removing it.
/// </summary>
/// <returns>The object at the end of the <see cref="ByteCircularBuffer"/>.</returns>
/// <exception cref="System.InvalidOperationException">Thrown if the buffer is empty.</exception>
public virtual byte PeekLast()
{
int bufferIndex;
if (this.IsEmpty)
{
throw new InvalidOperationException("The buffer is empty.");
}
if (this.Tail == 0)
{
bufferIndex = this.Size - 1;
}
else
{
bufferIndex = this.Tail - 1;
}
var item = _buffer[bufferIndex];
return item;
}
/// <summary>
/// Copies an entire compatible one-dimensional array to the <see cref="ByteCircularBuffer"/>.
/// </summary>
/// <param name="array">The one-dimensional <see cref="Array"/> that is the source of the elements copied to <see cref="ByteCircularBuffer"/>. The <see cref="Array"/> must have zero-based indexing.</param>
/// <exception cref="System.InvalidOperationException">Thrown if buffer does not have sufficient capacity to put in new items.</exception>
/// <remarks>If <see cref="Size"/> plus the size of <paramref name="array"/> exceeds the capacity of the <see cref="ByteCircularBuffer"/> and the <see cref="AllowOverwrite"/> property is <c>true</c>, the oldest items in the <see cref="ByteCircularBuffer"/> are overwritten with <paramref name="array"/>.</remarks>
public int Put(byte[] array)
{
return this.Put(array, 0, array.Length);
}
/// <summary>
/// Copies a range of elements from a compatible one-dimensional array to the <see cref="ByteCircularBuffer"/>.
/// </summary>
/// <param name="array">The one-dimensional <see cref="Array"/> that is the source of the elements copied to <see cref="ByteCircularBuffer"/>. The <see cref="Array"/> must have zero-based indexing.</param>
/// <param name="arrayIndex">The zero-based index in <paramref name="array"/> at which copying begins.</param>
/// <param name="count">The number of elements to copy.</param>
/// <exception cref="System.InvalidOperationException">Thrown if buffer does not have sufficient capacity to put in new items.</exception>
/// <remarks>If <see cref="Size"/> plus <paramref name="count"/> exceeds the capacity of the <see cref="ByteCircularBuffer"/> and the <see cref="AllowOverwrite"/> property is <c>true</c>, the oldest items in the <see cref="ByteCircularBuffer"/> are overwritten with <paramref name="array"/>.</remarks>
public virtual int Put(byte[] array, int arrayIndex, int count)
{
if (count <= 0) throw new ArgumentOutOfRangeException(nameof(count), "Count must be positive.");
if (this.Size + count > this.Capacity)
{
throw new InvalidOperationException("The buffer does not have sufficient capacity to put new items.");
}
if (array.Length < arrayIndex + count)
{
throw new ArgumentException("Source array too small for requested input.");
}
var srcIndex = arrayIndex;
var bytesToProcess = count;
while (bytesToProcess > 0)
{
int chunk = Math.Min(Capacity - Tail, bytesToProcess);
Buffer.BlockCopy(array, srcIndex, _buffer, Tail, chunk);
Tail = (Tail + chunk == Capacity) ? 0 : Tail + chunk;
this.Size += chunk;
srcIndex += chunk;
bytesToProcess -= chunk;
}
return count;
}
/// <summary>
/// Adds a byte to the end of the <see cref="ByteCircularBuffer"/>.
/// </summary>
/// <param name="item">The byte to add to the <see cref="ByteCircularBuffer"/>. </param>
/// <exception cref="System.InvalidOperationException">Thrown if buffer does not have sufficient capacity to put in new items.</exception>
public virtual void Put(byte item)
{
if (IsFull)
{
throw new InvalidOperationException("The buffer does not have sufficient capacity to put new items.");
}
_buffer[this.Tail] = item;
this.Tail++;
if (this.Size == this.Capacity)
{
this.Head++;
if (this.Head >= this.Capacity)
{
this.Head -= this.Capacity;
}
}
if (this.Tail == this.Capacity)
{
this.Tail = 0;
}
if (this.Size != this.Capacity)
{
this.Size++;
}
}
/// <summary>
/// Increments the starting index of the data buffer in the <see cref="ByteCircularBuffer"/>.
/// </summary>
/// <param name="count">The number of elements to increment the data buffer start index by.</param>
public void Skip(int count)
{
if (count < 0)
{
throw new ArgumentOutOfRangeException(nameof(count), "Negative count specified. Count must be positive.");
}
if (count > this.Size)
{
throw new ArgumentException("Ringbuffer contents insufficient for operation.", nameof(count));
}
// Modular division gives new offset position
this.Head = (this.Head + count) % Capacity;
this.Size -= count;
}
/// <summary>
/// Copies the <see cref="ByteCircularBuffer"/> elements to a new array.
/// </summary>
/// <returns>A new array containing elements copied from the <see cref="ByteCircularBuffer"/>.</returns>
/// <remarks>The <see cref="ByteCircularBuffer"/> is not modified. The order of the elements in the new array is the same as the order of the elements from the beginning of the <see cref="ByteCircularBuffer"/> to its end.</remarks>
public byte[] ToArray()
{
var result = new byte[this.Size];
this.CopyTo(result);
return result;
}
#endregion
}
}
@@ -71,6 +71,8 @@
public const int ATYP_DOMAIN = 0x03;
public const int ATYP_IPv6 = 0x04;
public const int MD5_LEN = 16;
protected EncryptorBase(string method, string password)
{
Method = method;
@@ -2,7 +2,7 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using Cyotek.Collections.Generic;
using Shadowsocks.Encryption.CircularBuffer;
using Shadowsocks.Controller;
namespace Shadowsocks.Encryption.Stream
@@ -14,8 +14,8 @@ namespace Shadowsocks.Encryption.Stream
protected static byte[] _udpTmpBuf = new byte[65536];
// every connection should create its own buffer
private CircularBuffer<byte> _encCircularBuffer = new CircularBuffer<byte>(TCPHandler.BufferSize * 2, false);
private CircularBuffer<byte> _decCircularBuffer = new CircularBuffer<byte>(TCPHandler.BufferSize * 2, false);
private ByteCircularBuffer _encCircularBuffer = new ByteCircularBuffer(TCPHandler.BufferSize * 2);
private ByteCircularBuffer _decCircularBuffer = new ByteCircularBuffer(TCPHandler.BufferSize * 2);
protected Dictionary<string, EncryptorInfo> ciphers;
@@ -64,25 +64,25 @@ namespace Shadowsocks.Encryption.Stream
{
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);
if (_key.Length != keyLen) Array.Resize(ref _key, keyLen);
LegacyDeriveKey(passbuf, _key, keyLen);
}
public static void LegacyDeriveKey(byte[] password, byte[] key)
public static void LegacyDeriveKey(byte[] password, byte[] key, int keylen)
{
byte[] result = new byte[password.Length + 16];
byte[] result = new byte[password.Length + MD5_LEN];
int i = 0;
byte[] md5sum = null;
while (i < key.Length) {
while (i < keylen) {
if (i == 0) {
md5sum = MbedTLS.MD5(password);
} else {
md5sum.CopyTo(result, 0);
password.CopyTo(result, md5sum.Length);
Array.Copy(md5sum, 0, result, 0, MD5_LEN);
Array.Copy(password, 0, result, MD5_LEN, password.Length);
md5sum = MbedTLS.MD5(result);
}
md5sum.CopyTo(key, i);
i += md5sum.Length;
Array.Copy(md5sum, 0, key, i, Math.Min(MD5_LEN, keylen - i));
i += MD5_LEN;
}
}
@@ -143,7 +143,8 @@ namespace Shadowsocks.Encryption.Stream
}
byte[] cipher = _decCircularBuffer.ToArray();
cipherUpdate(false, cipher.Length, cipher, outbuf);
_decCircularBuffer.Clear();
// move pointer only
_decCircularBuffer.Skip(_decCircularBuffer.Size);
outlength = cipher.Length;
// done the decryption
}
+3 -3
View File
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Weavers>
<Caseless StringComparison="Ordinal"/>
<Costura/>
<Caseless StringComparison="Ordinal" />
<Costura />
</Weavers>
+4 -5
View File
@@ -1,11 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Caseless.Fody" version="1.4.2" targetFramework="net462" developmentDependency="true" />
<package id="Costura.Fody" version="1.3.3.0" targetFramework="net462" developmentDependency="true" />
<package id="Cyotek.CircularBuffer" version="1.0.2" targetFramework="net462" />
<package id="Fody" version="1.29.4" targetFramework="net462" developmentDependency="true" />
<package id="Caseless.Fody" version="1.5.0" targetFramework="net462" developmentDependency="true" />
<package id="Costura.Fody" version="1.4.1" targetFramework="net462" developmentDependency="true" />
<package id="Fody" version="2.0.9" targetFramework="net462" developmentDependency="true" />
<package id="GlobalHotKey" version="1.1.0" targetFramework="net462" />
<package id="Newtonsoft.Json" version="10.0.1" targetFramework="net462" />
<package id="Newtonsoft.Json" version="10.0.2" targetFramework="net462" />
<package id="StringEx.CS" version="0.3.1" targetFramework="net462" developmentDependency="true" />
<package id="ZXing.Net" version="0.15.0" targetFramework="net462" />
</packages>
+7 -9
View File
@@ -66,9 +66,6 @@
<ApplicationManifest>app.manifest</ApplicationManifest>
</PropertyGroup>
<ItemGroup>
<Reference Include="Cyotek.Collections.Generic.CircularBuffer, Version=1.0.0.0, Culture=neutral, PublicKeyToken=58daa28b0b2de221, processorArchitecture=MSIL">
<HintPath>3rd\Cyotek.CircularBuffer.1.0.2\lib\net20\Cyotek.Collections.Generic.CircularBuffer.dll</HintPath>
</Reference>
<Reference Include="GlobalHotKey, Version=1.1.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>3rd\GlobalHotKey.1.1.0\lib\GlobalHotKey.dll</HintPath>
<Private>True</Private>
@@ -76,7 +73,7 @@
<Reference Include="Microsoft.CSharp" />
<Reference Include="Microsoft.VisualBasic" />
<Reference Include="Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>3rd\Newtonsoft.Json.10.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
<HintPath>3rd\Newtonsoft.Json.10.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Data" />
@@ -100,6 +97,7 @@
<Compile Include="Encryption\AEAD\AEADEncryptor.cs" />
<Compile Include="Encryption\AEAD\AEADMbedTLSEncryptor.cs" />
<Compile Include="Encryption\AEAD\AEADSodiumEncryptor.cs" />
<Compile Include="Encryption\CircularBuffer\ByteCircularBuffer.cs" />
<Compile Include="Encryption\EncryptorBase.cs" />
<Compile Include="Encryption\EncryptorFactory.cs" />
<Compile Include="Encryption\Exception\CryptoException.cs" />
@@ -266,9 +264,9 @@
<Content Include="Data\ja.txt" />
<Content Include="Data\privoxy_conf.txt" />
<Content Include="Data\user-rule.txt" />
<Content Include="FodyWeavers.xml">
<None Include="FodyWeavers.xml">
<SubType>Designer</SubType>
</Content>
</None>
<Content Include="Resources\ssIn24.png" />
<Content Include="Resources\ssOut24.png" />
<Content Include="shadowsocks.ico" />
@@ -342,12 +340,12 @@ foreach (var item in filesToCleanup)
<Target Name="CleanReferenceCopyLocalPaths" AfterTargets="AfterBuild;NonWinFodyTarget">
<CosturaCleanup Config="FodyWeavers.xml" Files="@(ReferenceCopyLocalPaths->'$(OutDir)%(DestinationSubDirectory)%(Filename)%(Extension)')" />
</Target>
<Import Project="3rd\Fody.1.29.4\build\dotnet\Fody.targets" Condition="Exists('3rd\Fody.1.29.4\build\dotnet\Fody.targets')" />
<Import Project="3rd\Fody.2.0.9\build\netstandard1.4\Fody.targets" Condition="Exists('3rd\Fody.2.0.9\build\netstandard1.4\Fody.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>这台计算机上缺少此项目引用的 NuGet 程序包。使用“NuGet 程序包还原”可下载这些程序包。有关更多信息,请参见 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。</ErrorText>
<ErrorText>此项目引用这台计算机上缺少的 NuGet 程序包。使用 NuGet 程序包还原可下载这些程序包。有关详细信息,请参阅 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('3rd\Fody.1.29.4\build\dotnet\Fody.targets')" Text="$([System.String]::Format('$(ErrorText)', '3rd\Fody.1.29.4\build\dotnet\Fody.targets'))" />
<Error Condition="!Exists('3rd\Fody.2.0.9\build\netstandard1.4\Fody.targets')" Text="$([System.String]::Format('$(ErrorText)', '3rd\Fody.2.0.9\build\netstandard1.4\Fody.targets'))" />
</Target>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.