Browse Source

bring native rc4 back, along with rc4-md5

partially revert 421554f8ec
pull/2865/head
Student Main 5 years ago
parent
commit
5d658fc841
3 changed files with 161 additions and 1 deletions
  1. +111
    -0
      shadowsocks-csharp/Encryption/Stream/StreamNativeEncryptor.cs
  2. +1
    -0
      shadowsocks-csharp/shadowsocks-csharp.csproj
  3. +49
    -1
      test/CryptographyTest.cs

+ 111
- 0
shadowsocks-csharp/Encryption/Stream/StreamNativeEncryptor.cs View File

@@ -0,0 +1,111 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Shadowsocks.Encryption.Stream
{
public class StreamNativeEncryptor : StreamEncryptor
{
bool md5;
byte[] realkey;
byte[] sbox;
public StreamNativeEncryptor(string method, string password) : base(method, password)
{
md5 = method.ToLowerInvariant().IndexOf("md5") >= 0;
}

public override void Dispose()
{
return;
}

protected override void initCipher(byte[] iv, bool isEncrypt)
{
base.initCipher(iv, isEncrypt);
if (md5)
{
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 = EncryptInitalize(realkey);
}

protected override void cipherUpdate(bool isEncrypt, int length, byte[] buf, byte[] outbuf)
{
var ctx = isEncrypt ? enc_ctx : dec_ctx;

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

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

protected override Dictionary<string, EncryptorInfo> getCiphers()
{
return new Dictionary<string, EncryptorInfo>()
{
{ "rc4-md5", new EncryptorInfo("rc4", 16, 16, 1) }
};
}

class Context
{
public int index1 = 0;
public int index2 = 0;
}

private Context enc_ctx = new Context();
private Context dec_ctx = new Context();

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

for (int i = 0; i < 256; i++)
{
s[i] = (byte)i;
}

for (int i = 0, j = 0; i < 256; i++)
{
j = (j + key[i % key.Length] + s[i]) & 255;

Swap(s, i, j);
}

return s;
}

private void EncryptOutput(Context ctx, byte[] s, byte[] data, int length)
{
for (int n = 0; n < length; n++)
{
byte b = data[n];

ctx.index1 = (ctx.index1 + 1) & 255;
ctx.index2 = (ctx.index2 + s[ctx.index1]) & 255;

Swap(s, ctx.index1, ctx.index2);

data[n] = (byte)(b ^ s[(s[ctx.index1] + s[ctx.index2]) & 255]);
}
}

private static void Swap(byte[] s, int i, int j)
{
byte c = s[i];

s[i] = s[j];
s[j] = c;
}
}
}

+ 1
- 0
shadowsocks-csharp/shadowsocks-csharp.csproj View File

@@ -129,6 +129,7 @@
<Compile Include="Encryption\Sodium.cs" /> <Compile Include="Encryption\Sodium.cs" />
<Compile Include="Encryption\Stream\StreamEncryptor.cs" /> <Compile Include="Encryption\Stream\StreamEncryptor.cs" />
<Compile Include="Encryption\Stream\StreamMbedTLSEncryptor.cs" /> <Compile Include="Encryption\Stream\StreamMbedTLSEncryptor.cs" />
<Compile Include="Encryption\Stream\StreamNativeEncryptor.cs" />
<Compile Include="Encryption\Stream\StreamOpenSSLEncryptor.cs" /> <Compile Include="Encryption\Stream\StreamOpenSSLEncryptor.cs" />
<Compile Include="Encryption\Stream\StreamSodiumEncryptor.cs" /> <Compile Include="Encryption\Stream\StreamSodiumEncryptor.cs" />
<Compile Include="Model\HotKeyConfig.cs" /> <Compile Include="Model\HotKeyConfig.cs" />


+ 49
- 1
test/CryptographyTest.cs View File

@@ -229,5 +229,53 @@ namespace Shadowsocks.Test
throw; throw;
} }
} }
[TestMethod]
public void TestNativeEncryption()
{
encryptionFailed = false;
// run it once before the multi-threading test to initialize global tables
RunSingleNativeEncryptionThread();
List<Thread> threads = new List<Thread>();
for (int i = 0; i < 10; i++)
{
Thread t = new Thread(new ThreadStart(RunSingleNativeEncryptionThread));
threads.Add(t);
t.Start();
}
foreach (Thread t in threads)
{
t.Join();
}
RNG.Close();
Assert.IsFalse(encryptionFailed);
}
private void RunSingleNativeEncryptionThread()
{
try
{
for (int i = 0; i < 100; i++)
{
var random = new Random();
IEncryptor encryptorO, encryptorN, encryptorN2;
IEncryptor decryptorO, decryptorN, decryptorN2;
encryptorO = new StreamOpenSSLEncryptor("rc4-md5", "barfoo!");
decryptorO = new StreamOpenSSLEncryptor("rc4-md5", "barfoo!");
encryptorN = new StreamNativeEncryptor("rc4-md5", "barfoo!");
encryptorN2 = new StreamNativeEncryptor("rc4-md5", "barfoo!");
decryptorN = new StreamNativeEncryptor("rc4-md5", "barfoo!");
decryptorN2 = new StreamNativeEncryptor("rc4-md5", "barfoo!");
RunEncryptionRound(encryptorN, decryptorN);
RunEncryptionRound(encryptorO, decryptorN2);
RunEncryptionRound(encryptorN2, decryptorO);
}
}
catch
{
encryptionFailed = true;
throw;
}
}
} }
}
}

Loading…
Cancel
Save