82 lines
2.1 KiB
C#
82 lines
2.1 KiB
C#
|
|
namespace shadowsocks_csharp.Encrypt
|
|
{
|
|
public class Rc4Encryptor
|
|
: EncryptorBase
|
|
{
|
|
public Rc4Encryptor(string method, string password)
|
|
: base(method, password)
|
|
{
|
|
byte[] hash = GetPasswordHash();
|
|
_encryptTable = EncryptInitalize(hash);
|
|
_decryptTable = EncryptInitalize(hash);
|
|
}
|
|
|
|
public override byte[] Encrypt(byte[] buf, int length)
|
|
{
|
|
return EncryptOutput(enc_ctx, _encryptTable, buf, length);
|
|
}
|
|
|
|
public override byte[] Decrypt(byte[] buf, int length)
|
|
{
|
|
return EncryptOutput(dec_ctx, _decryptTable, buf, length);
|
|
}
|
|
|
|
private readonly byte[] _encryptTable = new byte[256];
|
|
private readonly byte[] _decryptTable = new byte[256];
|
|
|
|
private Context enc_ctx = new Context();
|
|
private Context dec_ctx = new Context();
|
|
|
|
private byte[] EncryptOutput(Context ctx, byte[] s, byte[] data, int length)
|
|
{
|
|
byte[] result = new byte[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);
|
|
|
|
result[n] = (byte)(b ^ s[(s[ctx.Index1] + s[ctx.Index2]) & 255]);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
private byte[] EncryptInitalize(byte[] key)
|
|
{
|
|
var 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 static void Swap(byte[] s, int i, int j)
|
|
{
|
|
byte c = s[i];
|
|
|
|
s[i] = s[j];
|
|
s[j] = c;
|
|
}
|
|
|
|
class Context
|
|
{
|
|
public int Index1;
|
|
public int Index2;
|
|
}
|
|
}
|
|
}
|