Files
shadowsocks-windows/shadowsocks-csharp/Encryptor.cs
T
2013-05-10 14:54:51 +08:00

123 lines
4.0 KiB
C#
Executable File

using System;
using System.Collections.Generic;
using System.Text;
using System.Security.Cryptography;
namespace shadowsocks_csharp
{
class Encryptor
{
public const int TYPE_TABLE = 1;
public const int TYPE_RC4 = 2;
public byte[] encryptTable = new byte[256];
public byte[] decryptTable = new byte[256];
public int method = TYPE_TABLE;
public RC4 rc4 = null;
private 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 Encryptor(string method, string password)
{
MD5 md5 = System.Security.Cryptography.MD5.Create();
byte[] inputBytes = System.Text.Encoding.UTF8.GetBytes(password);
byte[] hash = md5.ComputeHash(inputBytes);
if (method != null && method.ToLowerInvariant().Equals("rc4")) {
Console.WriteLine("init rc4");
this.method = TYPE_RC4;
rc4 = new RC4();
encryptTable = rc4.EncryptInitalize(hash);
decryptTable = rc4.EncryptInitalize(hash);
} else {
Console.WriteLine("init table");
this.method = TYPE_TABLE;
// TODO endian
var 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 void Encrypt(byte[] buf, int length)
{
switch (method)
{
case TYPE_TABLE:
for (int i = 0; i < length; i++)
buf[i] = encryptTable[buf[i]];
break;
case TYPE_RC4:
rc4.Encrypt(encryptTable, buf, length);
break;
}
}
public void Decrypt(byte[] buf, int length)
{
switch (method)
{
case TYPE_TABLE:
for (int i = 0; i < length; i++)
buf[i] = decryptTable[buf[i]];
break;
case TYPE_RC4:
rc4.Decrypt(decryptTable, buf, length);
break;
}
}
}
}