Browse Source

bring back table, add plain

revert d24548a04f
pull/2865/head
Student Main 5 years ago
parent
commit
695716cd29
2 changed files with 117 additions and 21 deletions
  1. +113
    -21
      shadowsocks-csharp/Encryption/Stream/StreamNativeEncryptor.cs
  2. +4
    -0
      shadowsocks-csharp/View/ConfigForm.cs

+ 113
- 21
shadowsocks-csharp/Encryption/Stream/StreamNativeEncryptor.cs View File

@@ -8,12 +8,18 @@ namespace Shadowsocks.Encryption.Stream
{
public class StreamNativeEncryptor : StreamEncryptor
{
bool md5;
const int Plain = 0;
const int Table = 1;
const int Rc4 = 2;
const int Rc4Md5 = 3;

string _password;

byte[] realkey;
byte[] sbox;
public StreamNativeEncryptor(string method, string password) : base(method, password)
{
md5 = method.ToLowerInvariant().IndexOf("md5") >= 0;
_password = password;
}

public override void Dispose()
@@ -24,37 +30,71 @@ namespace Shadowsocks.Encryption.Stream
protected override void initCipher(byte[] iv, bool isEncrypt)
{
base.initCipher(iv, isEncrypt);
if (md5)
if (_cipher >= Rc4)
{
byte[] temp = new byte[keyLen + ivLen];
Array.Copy(_key, 0, temp, 0, keyLen);
Array.Copy(iv, 0, temp, keyLen, ivLen);
realkey = MbedTLS.MD5(temp);
if (_cipher == Rc4Md5)
{
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;
}
sbox = SBox(realkey);
}
else
else if (_cipher == Table)
{
realkey = _key;
ulong a = BitConverter.ToUInt64(MbedTLS.MD5(Encoding.UTF8.GetBytes(_password)), 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;
}
}
sbox = EncryptInitalize(realkey);
}

protected override void cipherUpdate(bool isEncrypt, int length, byte[] buf, byte[] outbuf)
{
var ctx = isEncrypt ? enc_ctx : dec_ctx;
if (_cipher == Table)
{
var table = isEncrypt ? _encryptTable : _decryptTable;
for (int i = 0; i < length; i++)
{
outbuf[i] = table[buf[i]];
}
}
else if (_cipher == Plain)
{
Array.Copy(buf, outbuf, length);
}
else
{
var ctx = isEncrypt ? enc_ctx : dec_ctx;

byte[] t = new byte[length];
Array.Copy(buf, t, length);
byte[] t = new byte[length];
Array.Copy(buf, t, length);

EncryptOutput(ctx, sbox, t, length);
Array.Copy(t, outbuf, length);
RC4(ctx, sbox, t, length);
Array.Copy(t, outbuf, length);
}
}

private static readonly Dictionary<string, EncryptorInfo> _ciphers = new Dictionary<string, EncryptorInfo>
{
{ "rc4", new EncryptorInfo("RC4", 16, 16, 1) },
{ "rc4-md5", new EncryptorInfo("RC4", 16, 16, 1) },
// it's using ivLen=16, not compatible
//{ "chacha20-ietf", new EncryptorInfo("chacha20", 32, 12, CIPHER_CHACHA20_IETF) }
{"plain", new EncryptorInfo("PLAIN", 0, 0, Plain) },
{"table", new EncryptorInfo("TABLE", 0, 0, Table) },
{ "rc4", new EncryptorInfo("RC4", 16, 16, Rc4) },
{ "rc4-md5", new EncryptorInfo("RC4", 16, 16, Rc4Md5) },
};

public static IEnumerable<string> SupportedCiphers()
@@ -67,6 +107,57 @@ namespace Shadowsocks.Encryption.Stream
return _ciphers;
}

#region Table
private byte[] _encryptTable = new byte[256];
private 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;
}
#endregion

#region RC4
class Context
{
public int index1 = 0;
@@ -76,7 +167,7 @@ namespace Shadowsocks.Encryption.Stream
private Context enc_ctx = new Context();
private Context dec_ctx = new Context();

private byte[] EncryptInitalize(byte[] key)
private byte[] SBox(byte[] key)
{
byte[] s = new byte[256];

@@ -95,7 +186,7 @@ namespace Shadowsocks.Encryption.Stream
return s;
}

private void EncryptOutput(Context ctx, byte[] s, byte[] data, int length)
private void RC4(Context ctx, byte[] s, byte[] data, int length)
{
for (int n = 0; n < length; n++)
{
@@ -117,5 +208,6 @@ namespace Shadowsocks.Encryption.Stream
s[i] = s[j];
s[j] = c;
}
#endregion
}
}

+ 4
- 0
shadowsocks-csharp/View/ConfigForm.cs View File

@@ -31,6 +31,10 @@ namespace Shadowsocks.View
"salsa20",
"chacha20",
"bf-cfb",
"rc4",
"plain",
"table",
};
private static string[] inuseMethod = new string[]
{


Loading…
Cancel
Save