use less RAM
This commit is contained in:
@@ -1,29 +1,31 @@
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
namespace shadowsocks_csharp.Encrypt
|
||||
{
|
||||
public abstract class EncryptorBase
|
||||
: IEncryptor
|
||||
{
|
||||
protected EncryptorBase(string method, string password)
|
||||
{
|
||||
Method = method;
|
||||
Password = password;
|
||||
}
|
||||
|
||||
protected string Method;
|
||||
protected string Password;
|
||||
|
||||
protected byte[] GetPasswordHash()
|
||||
{
|
||||
byte[] inputBytes = Encoding.UTF8.GetBytes(Password);
|
||||
byte[] hash = MD5.Create().ComputeHash(inputBytes);
|
||||
return hash;
|
||||
}
|
||||
|
||||
public abstract byte[] Encrypt(byte[] buf, int length);
|
||||
|
||||
public abstract byte[] Decrypt(byte[] buf, int length);
|
||||
}
|
||||
}
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
namespace shadowsocks_csharp.Encrypt
|
||||
{
|
||||
public abstract class EncryptorBase
|
||||
: IEncryptor
|
||||
{
|
||||
protected EncryptorBase(string method, string password)
|
||||
{
|
||||
Method = method;
|
||||
Password = password;
|
||||
}
|
||||
|
||||
protected string Method;
|
||||
protected string Password;
|
||||
|
||||
protected byte[] GetPasswordHash()
|
||||
{
|
||||
byte[] inputBytes = Encoding.UTF8.GetBytes(Password);
|
||||
byte[] hash = MD5.Create().ComputeHash(inputBytes);
|
||||
return hash;
|
||||
}
|
||||
|
||||
public abstract void Encrypt(byte[] buf, int length, byte[] outbuf, out int outlength);
|
||||
|
||||
public abstract void Decrypt(byte[] buf, int length, byte[] outbuf, out int outlength);
|
||||
|
||||
public abstract void Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,9 +4,9 @@ using System.Text;
|
||||
|
||||
namespace shadowsocks_csharp.Encrypt
|
||||
{
|
||||
public interface IEncryptor
|
||||
{
|
||||
byte[] Encrypt(byte[] buf, int length);
|
||||
byte[] Decrypt(byte[] buf, int length);
|
||||
public interface IEncryptor : IDisposable
|
||||
{
|
||||
void Encrypt(byte[] buf, int length, byte[] outbuf, out int outlength);
|
||||
void Decrypt(byte[] buf, int length, byte[] outbuf, out int outlength);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,59 +26,42 @@ namespace shadowsocks_csharp.Encrypt
|
||||
: base(method, password)
|
||||
{
|
||||
InitKey(method, password);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static byte[] tempbuf = new byte[32768];
|
||||
|
||||
public override byte[] Encrypt(byte[] buf, int length)
|
||||
public override void Encrypt(byte[] buf, int length, byte[] outbuf, out int outlength)
|
||||
{
|
||||
if (_encryptCtx == IntPtr.Zero)
|
||||
{
|
||||
byte[] iv = new byte[ivLen];
|
||||
OpenSSL.RAND_bytes(iv, iv.Length);
|
||||
InitCipher(ref _encryptCtx, iv, true);
|
||||
int outLen = length + ivLen;
|
||||
byte[] cipherText = new byte[outLen];
|
||||
OpenSSL.EVP_CipherUpdate(_encryptCtx, cipherText, out outLen, buf, length);
|
||||
byte[] result = new byte[outLen + ivLen];
|
||||
Buffer.BlockCopy(iv, 0, result, 0, ivLen);
|
||||
Buffer.BlockCopy(cipherText, 0, result, ivLen, outLen);
|
||||
return result;
|
||||
{
|
||||
OpenSSL.RAND_bytes(outbuf, ivLen);
|
||||
InitCipher(ref _encryptCtx, outbuf, true);
|
||||
outlength = length + ivLen;
|
||||
OpenSSL.EVP_CipherUpdate(_encryptCtx, tempbuf, out outlength, buf, length);
|
||||
outlength = length + ivLen;
|
||||
Buffer.BlockCopy(tempbuf, 0, outbuf, ivLen, outlength);
|
||||
}
|
||||
else
|
||||
{
|
||||
int outLen = length + ivLen;
|
||||
byte[] cipherText = new byte[outLen];
|
||||
OpenSSL.EVP_CipherUpdate(_encryptCtx, cipherText, out outLen, buf, length);
|
||||
byte[] result = new byte[outLen];
|
||||
Buffer.BlockCopy(cipherText, 0, result, 0, outLen);
|
||||
return result;
|
||||
outlength = length;
|
||||
OpenSSL.EVP_CipherUpdate(_encryptCtx, outbuf, out outlength, buf, length);
|
||||
}
|
||||
}
|
||||
|
||||
public override byte[] Decrypt(byte[] buf, int length)
|
||||
}
|
||||
|
||||
public override void Decrypt(byte[] buf, int length, byte[] outbuf, out int outlength)
|
||||
{
|
||||
if (_decryptCtx == IntPtr.Zero)
|
||||
{
|
||||
byte[] iv = new byte[ivLen];
|
||||
Buffer.BlockCopy(buf, 0, iv, 0, ivLen);
|
||||
InitCipher(ref _decryptCtx, iv, false);
|
||||
int outLen = length + ivLen;
|
||||
outLen -= ivLen;
|
||||
byte[] cipherText = new byte[outLen];
|
||||
byte[] subset = new byte[length - ivLen];
|
||||
Buffer.BlockCopy(buf, ivLen, subset, 0, length - ivLen);
|
||||
OpenSSL.EVP_CipherUpdate(_decryptCtx, cipherText, out outLen, subset, length - ivLen);
|
||||
byte[] result = new byte[outLen];
|
||||
Buffer.BlockCopy(cipherText, 0, result, 0, outLen);
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
int outLen = length + ivLen;
|
||||
byte[] cipherText = new byte[outLen];
|
||||
OpenSSL.EVP_CipherUpdate(_decryptCtx, cipherText, out outLen, buf, length);
|
||||
byte[] result = new byte[outLen];
|
||||
Buffer.BlockCopy(cipherText, 0, result, 0, outLen);
|
||||
return result;
|
||||
InitCipher(ref _decryptCtx, buf, false);
|
||||
outlength = length - ivLen;
|
||||
Buffer.BlockCopy(buf, ivLen, tempbuf, 0, length - ivLen);
|
||||
OpenSSL.EVP_CipherUpdate(_decryptCtx, outbuf, out outlength, tempbuf, length - ivLen);
|
||||
}
|
||||
else
|
||||
{
|
||||
outlength = length;
|
||||
OpenSSL.EVP_CipherUpdate(_decryptCtx, outbuf, out outlength, buf, length);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,7 +129,7 @@ namespace shadowsocks_csharp.Encrypt
|
||||
#region IDisposable
|
||||
private bool _disposed;
|
||||
|
||||
public void Dispose()
|
||||
public override void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
|
||||
@@ -1,96 +1,102 @@
|
||||
using System;
|
||||
|
||||
namespace shadowsocks_csharp.Encrypt
|
||||
{
|
||||
public class TableEncryptor
|
||||
: EncryptorBase
|
||||
{
|
||||
public TableEncryptor(string method, string password)
|
||||
: base(method, password)
|
||||
{
|
||||
byte[] hash = GetPasswordHash();
|
||||
// TODO endian
|
||||
ulong a = BitConverter.ToUInt64(hash, 0);
|
||||
for (int i = 0; i < 256; i++)
|
||||
{
|
||||
_encryptTable[i] = (byte)i;
|
||||
}
|
||||
for (int i = 1; i < 1024; i++)
|
||||
{
|
||||
_encryptTable = MergeSort(_encryptTable, a, i);
|
||||
}
|
||||
for (int i = 0; i < 256; i++)
|
||||
{
|
||||
_decryptTable[_encryptTable[i]] = (byte)i;
|
||||
}
|
||||
}
|
||||
|
||||
public override byte[] Encrypt(byte[] buf, int length)
|
||||
{
|
||||
byte[] result = new byte[length];
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
result[i] = _encryptTable[buf[i]];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public override byte[] Decrypt(byte[] buf, int length)
|
||||
{
|
||||
byte[] result = new byte[length];
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
result[i] = _decryptTable[buf[i]];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private readonly byte[] _encryptTable = new byte[256];
|
||||
private readonly byte[] _decryptTable = new byte[256];
|
||||
|
||||
private static long Compare(byte x, byte y, ulong a, int i)
|
||||
{
|
||||
return (long)(a % (ulong)(x + i)) - (long)(a % (ulong)(y + i));
|
||||
}
|
||||
|
||||
private byte[] MergeSort(byte[] array, ulong a, int j)
|
||||
{
|
||||
if (array.Length == 1)
|
||||
{
|
||||
return array;
|
||||
}
|
||||
int middle = array.Length / 2;
|
||||
byte[] left = new byte[middle];
|
||||
for (int i = 0; i < middle; i++)
|
||||
{
|
||||
left[i] = array[i];
|
||||
}
|
||||
byte[] right = new byte[array.Length - middle];
|
||||
for (int i = 0; i < array.Length - middle; i++)
|
||||
{
|
||||
right[i] = array[i + middle];
|
||||
}
|
||||
left = MergeSort(left, a, j);
|
||||
right = MergeSort(right, a, j);
|
||||
|
||||
int leftptr = 0;
|
||||
int rightptr = 0;
|
||||
|
||||
byte[] sorted = new byte[array.Length];
|
||||
for (int k = 0; k < array.Length; k++)
|
||||
{
|
||||
if (rightptr == right.Length || ((leftptr < left.Length) && (Compare(left[leftptr], right[rightptr], a, j) <= 0)))
|
||||
{
|
||||
sorted[k] = left[leftptr];
|
||||
leftptr++;
|
||||
}
|
||||
else if (leftptr == left.Length || ((rightptr < right.Length) && (Compare(right[rightptr], left[leftptr], a, j)) <= 0))
|
||||
{
|
||||
sorted[k] = right[rightptr];
|
||||
rightptr++;
|
||||
}
|
||||
}
|
||||
return sorted;
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
|
||||
namespace shadowsocks_csharp.Encrypt
|
||||
{
|
||||
public class TableEncryptor
|
||||
: EncryptorBase
|
||||
{
|
||||
public TableEncryptor(string method, string password)
|
||||
: base(method, password)
|
||||
{
|
||||
byte[] hash = GetPasswordHash();
|
||||
// TODO endian
|
||||
ulong a = BitConverter.ToUInt64(hash, 0);
|
||||
for (int i = 0; i < 256; i++)
|
||||
{
|
||||
_encryptTable[i] = (byte)i;
|
||||
}
|
||||
for (int i = 1; i < 1024; i++)
|
||||
{
|
||||
_encryptTable = MergeSort(_encryptTable, a, i);
|
||||
}
|
||||
for (int i = 0; i < 256; i++)
|
||||
{
|
||||
_decryptTable[_encryptTable[i]] = (byte)i;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Encrypt(byte[] buf, int length, byte[] outbuf, out int outlength)
|
||||
{
|
||||
byte[] result = new byte[length];
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
outbuf[i] = _encryptTable[buf[i]];
|
||||
}
|
||||
outlength = length;
|
||||
}
|
||||
|
||||
|
||||
public override void Decrypt(byte[] buf, int length, byte[] outbuf, out int outlength)
|
||||
{
|
||||
byte[] result = new byte[length];
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
outbuf[i] = _decryptTable[buf[i]];
|
||||
}
|
||||
outlength = length;
|
||||
}
|
||||
|
||||
private readonly byte[] _encryptTable = new byte[256];
|
||||
private readonly byte[] _decryptTable = new byte[256];
|
||||
|
||||
private static long Compare(byte x, byte y, ulong a, int i)
|
||||
{
|
||||
return (long)(a % (ulong)(x + i)) - (long)(a % (ulong)(y + i));
|
||||
}
|
||||
|
||||
private byte[] MergeSort(byte[] array, ulong a, int j)
|
||||
{
|
||||
if (array.Length == 1)
|
||||
{
|
||||
return array;
|
||||
}
|
||||
int middle = array.Length / 2;
|
||||
byte[] left = new byte[middle];
|
||||
for (int i = 0; i < middle; i++)
|
||||
{
|
||||
left[i] = array[i];
|
||||
}
|
||||
byte[] right = new byte[array.Length - middle];
|
||||
for (int i = 0; i < array.Length - middle; i++)
|
||||
{
|
||||
right[i] = array[i + middle];
|
||||
}
|
||||
left = MergeSort(left, a, j);
|
||||
right = MergeSort(right, a, j);
|
||||
|
||||
int leftptr = 0;
|
||||
int rightptr = 0;
|
||||
|
||||
byte[] sorted = new byte[array.Length];
|
||||
for (int k = 0; k < array.Length; k++)
|
||||
{
|
||||
if (rightptr == right.Length || ((leftptr < left.Length) && (Compare(left[leftptr], right[rightptr], a, j) <= 0)))
|
||||
{
|
||||
sorted[k] = left[leftptr];
|
||||
leftptr++;
|
||||
}
|
||||
else if (leftptr == left.Length || ((rightptr < right.Length) && (Compare(right[rightptr], left[leftptr], a, j)) <= 0))
|
||||
{
|
||||
sorted[k] = right[rightptr];
|
||||
rightptr++;
|
||||
}
|
||||
}
|
||||
return sorted;
|
||||
}
|
||||
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+21
-14
@@ -100,11 +100,16 @@ namespace shadowsocks_csharp
|
||||
public Socket remote;
|
||||
public Socket connection;
|
||||
// Size of receive buffer.
|
||||
public const int BufferSize = 1500;
|
||||
public const int RecvSize = 16384;
|
||||
public const int BufferSize = RecvSize + 32;
|
||||
// remote receive buffer
|
||||
public byte[] remoteBuffer = new byte[BufferSize];
|
||||
public byte[] remoteRecvBuffer = new byte[RecvSize];
|
||||
// remote send buffer
|
||||
public byte[] remoteSendBuffer = new byte[BufferSize];
|
||||
// connection receive buffer
|
||||
public byte[] connetionBuffer = new byte[BufferSize];
|
||||
public byte[] connetionRecvBuffer = new byte[RecvSize];
|
||||
// connection send buffer
|
||||
public byte[] connetionSendBuffer = new byte[BufferSize];
|
||||
// Received data string.
|
||||
public StringBuilder sb = new StringBuilder();
|
||||
|
||||
@@ -151,7 +156,7 @@ namespace shadowsocks_csharp
|
||||
Console.WriteLine(e.ToString());
|
||||
}
|
||||
}
|
||||
//encryptor.Dispose();
|
||||
((IDisposable)encryptor).Dispose();
|
||||
}
|
||||
|
||||
private void connectCallback(IAsyncResult ar)
|
||||
@@ -177,7 +182,7 @@ namespace shadowsocks_csharp
|
||||
{
|
||||
try
|
||||
{
|
||||
connection.BeginReceive(new byte[256], 0, 256, 0,
|
||||
connection.BeginReceive(connetionRecvBuffer, 0, 256, 0,
|
||||
new AsyncCallback(handshakeReceiveCallback), null);
|
||||
}
|
||||
catch (Exception e)
|
||||
@@ -223,7 +228,7 @@ namespace shadowsocks_csharp
|
||||
// +----+-----+-------+------+----------+----------+
|
||||
// Skip first 3 bytes
|
||||
// TODO validate
|
||||
connection.BeginReceive(new byte[3], 0, 3, 0,
|
||||
connection.BeginReceive(connetionRecvBuffer, 0, 3, 0,
|
||||
new AsyncCallback(handshakeReceive2Callback), null);
|
||||
}
|
||||
catch (Exception e)
|
||||
@@ -262,9 +267,9 @@ namespace shadowsocks_csharp
|
||||
try
|
||||
{
|
||||
connection.EndReceive(ar);
|
||||
remote.BeginReceive(remoteBuffer, 0, BufferSize, 0,
|
||||
remote.BeginReceive(remoteRecvBuffer, 0, RecvSize, 0,
|
||||
new AsyncCallback(pipeRemoteReceiveCallback), null);
|
||||
connection.BeginReceive(connetionBuffer, 0, BufferSize, 0,
|
||||
connection.BeginReceive(connetionRecvBuffer, 0, RecvSize, 0,
|
||||
new AsyncCallback(pipeConnectionReceiveCallback), null);
|
||||
}
|
||||
catch (Exception e)
|
||||
@@ -283,8 +288,9 @@ namespace shadowsocks_csharp
|
||||
|
||||
if (bytesRead > 0)
|
||||
{
|
||||
byte[] buf = encryptor.Decrypt(remoteBuffer, bytesRead);
|
||||
connection.BeginSend(buf, 0, buf.Length, 0, new AsyncCallback(pipeConnectionSendCallback), null);
|
||||
int bytesToSend;
|
||||
encryptor.Decrypt(remoteRecvBuffer, bytesRead, remoteSendBuffer, out bytesToSend);
|
||||
connection.BeginSend(remoteSendBuffer, 0, bytesToSend, 0, new AsyncCallback(pipeConnectionSendCallback), null);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -308,8 +314,9 @@ namespace shadowsocks_csharp
|
||||
|
||||
if (bytesRead > 0)
|
||||
{
|
||||
byte[] buf = encryptor.Encrypt(connetionBuffer, bytesRead);
|
||||
remote.BeginSend(buf, 0, buf.Length, 0, new AsyncCallback(pipeRemoteSendCallback), null);
|
||||
int bytesToSend;
|
||||
encryptor.Encrypt(connetionRecvBuffer, bytesRead, connetionSendBuffer, out bytesToSend);
|
||||
remote.BeginSend(connetionSendBuffer, 0, bytesToSend, 0, new AsyncCallback(pipeRemoteSendCallback), null);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -329,7 +336,7 @@ namespace shadowsocks_csharp
|
||||
try
|
||||
{
|
||||
remote.EndSend(ar);
|
||||
connection.BeginReceive(this.connetionBuffer, 0, BufferSize, 0,
|
||||
connection.BeginReceive(this.connetionRecvBuffer, 0, RecvSize, 0,
|
||||
new AsyncCallback(pipeConnectionReceiveCallback), null);
|
||||
}
|
||||
catch (Exception e)
|
||||
@@ -344,7 +351,7 @@ namespace shadowsocks_csharp
|
||||
try
|
||||
{
|
||||
connection.EndSend(ar);
|
||||
remote.BeginReceive(this.remoteBuffer, 0, BufferSize, 0,
|
||||
remote.BeginReceive(this.remoteRecvBuffer, 0, RecvSize, 0,
|
||||
new AsyncCallback(pipeRemoteReceiveCallback), null);
|
||||
}
|
||||
catch (Exception e)
|
||||
|
||||
Reference in New Issue
Block a user