Browse Source

use less RAM

tags/2.3
clowwindy 10 years ago
parent
commit
a5fbcb18a2
5 changed files with 184 additions and 186 deletions
  1. +31
    -29
      shadowsocks-csharp/Encrypt/EncryptorBase.cs
  2. +4
    -4
      shadowsocks-csharp/Encrypt/IEncryptor.cs
  3. +26
    -43
      shadowsocks-csharp/Encrypt/OpensslEncryptor.cs
  4. +102
    -96
      shadowsocks-csharp/Encrypt/TableEncryptor.cs
  5. +21
    -14
      shadowsocks-csharp/Local.cs

+ 31
- 29
shadowsocks-csharp/Encrypt/EncryptorBase.cs View File

@@ -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
- 4
shadowsocks-csharp/Encrypt/IEncryptor.cs View File

@@ -4,9 +4,9 @@ using System.Text;


namespace shadowsocks_csharp.Encrypt 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
- 43
shadowsocks-csharp/Encrypt/OpensslEncryptor.cs View File

@@ -26,59 +26,42 @@ namespace shadowsocks_csharp.Encrypt
: base(method, password) : base(method, password)
{ {
InitKey(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) 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 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) 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;
{
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
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;
outlength = length;
OpenSSL.EVP_CipherUpdate(_decryptCtx, outbuf, out outlength, buf, length);
} }
} }


@@ -146,7 +129,7 @@ namespace shadowsocks_csharp.Encrypt
#region IDisposable #region IDisposable
private bool _disposed; private bool _disposed;


public void Dispose()
public override void Dispose()
{ {
Dispose(true); Dispose(true);
GC.SuppressFinalize(this); GC.SuppressFinalize(this);


+ 102
- 96
shadowsocks-csharp/Encrypt/TableEncryptor.cs View File

@@ -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
shadowsocks-csharp/Local.cs View File

@@ -100,11 +100,16 @@ namespace shadowsocks_csharp
public Socket remote; public Socket remote;
public Socket connection; public Socket connection;
// Size of receive buffer. // Size of receive buffer.
public const int BufferSize = 1500;
public const int RecvSize = 16384;
public const int BufferSize = RecvSize + 32;
// remote receive buffer // 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 // 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. // Received data string.
public StringBuilder sb = new StringBuilder(); public StringBuilder sb = new StringBuilder();
@@ -151,7 +156,7 @@ namespace shadowsocks_csharp
Console.WriteLine(e.ToString()); Console.WriteLine(e.ToString());
} }
} }
//encryptor.Dispose();
((IDisposable)encryptor).Dispose();
} }
private void connectCallback(IAsyncResult ar) private void connectCallback(IAsyncResult ar)
@@ -177,7 +182,7 @@ namespace shadowsocks_csharp
{ {
try try
{ {
connection.BeginReceive(new byte[256], 0, 256, 0,
connection.BeginReceive(connetionRecvBuffer, 0, 256, 0,
new AsyncCallback(handshakeReceiveCallback), null); new AsyncCallback(handshakeReceiveCallback), null);
} }
catch (Exception e) catch (Exception e)
@@ -223,7 +228,7 @@ namespace shadowsocks_csharp
// +----+-----+-------+------+----------+----------+ // +----+-----+-------+------+----------+----------+
// Skip first 3 bytes // Skip first 3 bytes
// TODO validate // TODO validate
connection.BeginReceive(new byte[3], 0, 3, 0,
connection.BeginReceive(connetionRecvBuffer, 0, 3, 0,
new AsyncCallback(handshakeReceive2Callback), null); new AsyncCallback(handshakeReceive2Callback), null);
} }
catch (Exception e) catch (Exception e)
@@ -262,9 +267,9 @@ namespace shadowsocks_csharp
try try
{ {
connection.EndReceive(ar); connection.EndReceive(ar);
remote.BeginReceive(remoteBuffer, 0, BufferSize, 0,
remote.BeginReceive(remoteRecvBuffer, 0, RecvSize, 0,
new AsyncCallback(pipeRemoteReceiveCallback), null); new AsyncCallback(pipeRemoteReceiveCallback), null);
connection.BeginReceive(connetionBuffer, 0, BufferSize, 0,
connection.BeginReceive(connetionRecvBuffer, 0, RecvSize, 0,
new AsyncCallback(pipeConnectionReceiveCallback), null); new AsyncCallback(pipeConnectionReceiveCallback), null);
} }
catch (Exception e) catch (Exception e)
@@ -283,8 +288,9 @@ namespace shadowsocks_csharp
if (bytesRead > 0) 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 else
{ {
@@ -308,8 +314,9 @@ namespace shadowsocks_csharp
if (bytesRead > 0) 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 else
{ {
@@ -329,7 +336,7 @@ namespace shadowsocks_csharp
try try
{ {
remote.EndSend(ar); remote.EndSend(ar);
connection.BeginReceive(this.connetionBuffer, 0, BufferSize, 0,
connection.BeginReceive(this.connetionRecvBuffer, 0, RecvSize, 0,
new AsyncCallback(pipeConnectionReceiveCallback), null); new AsyncCallback(pipeConnectionReceiveCallback), null);
} }
catch (Exception e) catch (Exception e)
@@ -344,7 +351,7 @@ namespace shadowsocks_csharp
try try
{ {
connection.EndSend(ar); connection.EndSend(ar);
remote.BeginReceive(this.remoteBuffer, 0, BufferSize, 0,
remote.BeginReceive(this.remoteRecvBuffer, 0, RecvSize, 0,
new AsyncCallback(pipeRemoteReceiveCallback), null); new AsyncCallback(pipeRemoteReceiveCallback), null);
} }
catch (Exception e) catch (Exception e)


Loading…
Cancel
Save