@@ -125,7 +125,7 @@ namespace Shadowsocks.Controller | |||
{ | |||
throw new ArgumentException("No server configured"); | |||
} | |||
this.encryptor = EncryptorFactory.GetEncryptor(server.method, server.password, server.one_time_auth); | |||
this.encryptor = EncryptorFactory.GetEncryptor(server.method, server.password, server.one_time_auth, false); | |||
this.server = server; | |||
} | |||
@@ -586,7 +586,7 @@ namespace Shadowsocks.Controller | |||
{ | |||
return; | |||
} | |||
encryptor.Encrypt(connetionRecvBuffer, bytesRead, connetionSendBuffer, out bytesToSend, false); | |||
encryptor.Encrypt(connetionRecvBuffer, bytesRead, connetionSendBuffer, out bytesToSend); | |||
} | |||
remote.BeginSend(connetionSendBuffer, 0, bytesToSend, 0, new AsyncCallback(PipeRemoteSendCallback), null); | |||
@@ -74,12 +74,12 @@ namespace Shadowsocks.Controller | |||
} | |||
public void Send(byte[] data, int length) | |||
{ | |||
IEncryptor encryptor = EncryptorFactory.GetEncryptor(_server.method, _server.password, _server.one_time_auth); | |||
IEncryptor encryptor = EncryptorFactory.GetEncryptor(_server.method, _server.password, _server.one_time_auth, true); | |||
byte[] dataIn = new byte[length - 3 + IVEncryptor.ONETIMEAUTH_BYTES]; | |||
Array.Copy(data, 3, dataIn, 0, length - 3); | |||
byte[] dataOut = new byte[length - 3 + 16 + IVEncryptor.ONETIMEAUTH_BYTES]; | |||
int outlen; | |||
encryptor.Encrypt(dataIn, length - 3, dataOut, out outlen, true); | |||
encryptor.Encrypt(dataIn, length - 3, dataOut, out outlen); | |||
_remote.SendTo(dataOut, outlen, SocketFlags.None, _remoteEndPoint); | |||
} | |||
public void Receive() | |||
@@ -97,7 +97,7 @@ namespace Shadowsocks.Controller | |||
byte[] dataOut = new byte[bytesRead]; | |||
int outlen; | |||
IEncryptor encryptor = EncryptorFactory.GetEncryptor(_server.method, _server.password, _server.one_time_auth); | |||
IEncryptor encryptor = EncryptorFactory.GetEncryptor(_server.method, _server.password, _server.one_time_auth, true); | |||
encryptor.Decrypt(_buffer, bytesRead, dataOut, out outlen); | |||
byte[] sendBuf = new byte[outlen + 3]; | |||
@@ -8,16 +8,18 @@ namespace Shadowsocks.Encryption | |||
{ | |||
public const int MAX_INPUT_SIZE = 32768; | |||
protected EncryptorBase(string method, string password, bool onetimeauth) | |||
protected EncryptorBase(string method, string password, bool onetimeauth, bool isudp) | |||
{ | |||
Method = method; | |||
Password = password; | |||
OnetimeAuth = onetimeauth; | |||
IsUDP = isudp; | |||
} | |||
protected string Method; | |||
protected string Password; | |||
protected bool OnetimeAuth; | |||
protected bool IsUDP; | |||
protected byte[] GetPasswordHash() | |||
{ | |||
@@ -26,7 +28,7 @@ namespace Shadowsocks.Encryption | |||
return hash; | |||
} | |||
public abstract void Encrypt(byte[] buf, int length, byte[] outbuf, out int outlength, bool udp); | |||
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); | |||
@@ -8,7 +8,7 @@ namespace Shadowsocks.Encryption | |||
{ | |||
private static Dictionary<string, Type> _registeredEncryptors; | |||
private static Type[] _constructorTypes = new Type[] { typeof(string), typeof(string), typeof(bool) }; | |||
private static Type[] _constructorTypes = new Type[] { typeof(string), typeof(string), typeof(bool), typeof(bool) }; | |||
static EncryptorFactory() | |||
{ | |||
@@ -27,7 +27,7 @@ namespace Shadowsocks.Encryption | |||
} | |||
} | |||
public static IEncryptor GetEncryptor(string method, string password, bool onetimeauth) | |||
public static IEncryptor GetEncryptor(string method, string password, bool onetimeauth, bool isudp) | |||
{ | |||
if (string.IsNullOrEmpty(method)) | |||
{ | |||
@@ -36,7 +36,7 @@ namespace Shadowsocks.Encryption | |||
method = method.ToLowerInvariant(); | |||
Type t = _registeredEncryptors[method]; | |||
ConstructorInfo c = t.GetConstructor(_constructorTypes); | |||
IEncryptor result = (IEncryptor)c.Invoke(new object[] { method, password, onetimeauth }); | |||
IEncryptor result = (IEncryptor)c.Invoke(new object[] { method, password, onetimeauth, isudp }); | |||
return result; | |||
} | |||
} | |||
@@ -6,7 +6,7 @@ namespace Shadowsocks.Encryption | |||
{ | |||
public interface IEncryptor : IDisposable | |||
{ | |||
void Encrypt(byte[] buf, int length, byte[] outbuf, out int outlength, bool udp); | |||
void Encrypt(byte[] buf, int length, byte[] outbuf, out int outlength); | |||
void Decrypt(byte[] buf, int length, byte[] outbuf, out int outlength); | |||
} | |||
} |
@@ -40,8 +40,8 @@ namespace Shadowsocks.Encryption | |||
protected uint counter = 0; | |||
protected byte[] _keyBuffer = null; | |||
public IVEncryptor(string method, string password, bool onetimeauth) | |||
: base(method, password, onetimeauth) | |||
public IVEncryptor(string method, string password, bool onetimeauth, bool isudp) | |||
: base(method, password, onetimeauth, isudp) | |||
{ | |||
InitKey(method, password); | |||
} | |||
@@ -183,38 +183,65 @@ namespace Shadowsocks.Encryption | |||
return hash; | |||
} | |||
public override void Encrypt(byte[] buf, int length, byte[] outbuf, out int outlength, bool udp) | |||
protected void reactBuffer4TCP(byte[] buf, ref int length) | |||
{ | |||
if (!_encryptIVSent) | |||
{ | |||
int headLen = getHeadLen(buf, length); | |||
int dataLen = length - headLen; | |||
buf[0] |= ONETIMEAUTH_FLAG; | |||
byte[] hash = genOnetimeAuthHash(buf, headLen); | |||
Buffer.BlockCopy(buf, headLen, buf, headLen + ONETIMEAUTH_BYTES + AUTH_BYTES, dataLen); | |||
Buffer.BlockCopy(hash, 0, buf, headLen, ONETIMEAUTH_BYTES); | |||
hash = genHash(buf, headLen + ONETIMEAUTH_BYTES + AUTH_BYTES, dataLen); | |||
Buffer.BlockCopy(hash, 0, buf, headLen + ONETIMEAUTH_BYTES + CLEN_BYTES, ONETIMEAUTH_BYTES); | |||
byte[] lenBytes = BitConverter.GetBytes((ushort)IPAddress.HostToNetworkOrder((short)dataLen)); | |||
Buffer.BlockCopy(lenBytes, 0, buf, headLen + ONETIMEAUTH_BYTES, CLEN_BYTES); | |||
length = headLen + ONETIMEAUTH_BYTES + AUTH_BYTES + dataLen; | |||
} | |||
else | |||
{ | |||
byte[] hash = genHash(buf, 0, length); | |||
Buffer.BlockCopy(buf, 0, buf, AUTH_BYTES, length); | |||
byte[] lenBytes = BitConverter.GetBytes((ushort)IPAddress.HostToNetworkOrder((short)length)); | |||
Buffer.BlockCopy(lenBytes, 0, buf, 0, CLEN_BYTES); | |||
Buffer.BlockCopy(hash, 0, buf, CLEN_BYTES, ONETIMEAUTH_BYTES); | |||
length += AUTH_BYTES; | |||
} | |||
} | |||
protected void reactBuffer4UDP(byte[] buf, ref int length) | |||
{ | |||
buf[0] |= ONETIMEAUTH_FLAG; | |||
byte[] hash = genOnetimeAuthHash(buf, length); | |||
Buffer.BlockCopy(hash, 0, buf, length, ONETIMEAUTH_BYTES); | |||
length += ONETIMEAUTH_BYTES; | |||
} | |||
protected void reactBuffer(byte[] buf, ref int length) | |||
{ | |||
if (OnetimeAuth && ivLen > 0) | |||
{ | |||
if (!IsUDP) | |||
{ | |||
reactBuffer4TCP(buf, ref length); | |||
} | |||
else | |||
{ | |||
reactBuffer4UDP(buf, ref length); | |||
} | |||
} | |||
} | |||
public override void Encrypt(byte[] buf, int length, byte[] outbuf, out int outlength) | |||
{ | |||
if (!_encryptIVSent) | |||
{ | |||
_encryptIVSent = true; | |||
randBytes(outbuf, ivLen); | |||
initCipher(outbuf, true); | |||
outlength = length + ivLen; | |||
if (OnetimeAuth && ivLen > 0) | |||
{ | |||
if(!udp) | |||
{ | |||
int headLen = getHeadLen(buf, length); | |||
int dataLen = length - headLen; | |||
buf[0] |= ONETIMEAUTH_FLAG; | |||
byte[] hash = genOnetimeAuthHash(buf, headLen); | |||
Buffer.BlockCopy(buf, headLen, buf, headLen + ONETIMEAUTH_BYTES + AUTH_BYTES, dataLen); | |||
Buffer.BlockCopy(hash, 0, buf, headLen, ONETIMEAUTH_BYTES); | |||
hash = genHash(buf, headLen + ONETIMEAUTH_BYTES + AUTH_BYTES, dataLen); | |||
Buffer.BlockCopy(hash, 0, buf, headLen + ONETIMEAUTH_BYTES + CLEN_BYTES, ONETIMEAUTH_BYTES); | |||
byte[] lenBytes = BitConverter.GetBytes((ushort)IPAddress.HostToNetworkOrder((short)dataLen)); | |||
Buffer.BlockCopy(lenBytes, 0, buf, headLen + ONETIMEAUTH_BYTES, CLEN_BYTES); | |||
length = headLen + ONETIMEAUTH_BYTES + AUTH_BYTES + dataLen; | |||
} | |||
else | |||
{ | |||
buf[0] |= ONETIMEAUTH_FLAG; | |||
byte[] hash = genOnetimeAuthHash(buf, length); | |||
Buffer.BlockCopy(hash, 0, buf, length, ONETIMEAUTH_BYTES); | |||
length += ONETIMEAUTH_BYTES; | |||
} | |||
} | |||
reactBuffer(buf, ref length); | |||
_encryptIVSent = true; | |||
lock (tempbuf) | |||
{ | |||
cipherUpdate(true, length, buf, tempbuf); | |||
@@ -224,15 +251,7 @@ namespace Shadowsocks.Encryption | |||
} | |||
else | |||
{ | |||
if (OnetimeAuth && ivLen > 0) | |||
{ | |||
byte[] hash = genHash(buf, 0, length); | |||
Buffer.BlockCopy(buf, 0, buf, AUTH_BYTES, length); | |||
byte[] lenBytes = BitConverter.GetBytes((ushort)IPAddress.HostToNetworkOrder((short)length)); | |||
Buffer.BlockCopy(lenBytes, 0, buf, 0, CLEN_BYTES); | |||
Buffer.BlockCopy(hash, 0, buf, CLEN_BYTES, ONETIMEAUTH_BYTES); | |||
length += AUTH_BYTES; | |||
} | |||
reactBuffer(buf, ref length); | |||
outlength = length; | |||
cipherUpdate(true, length, buf, outbuf); | |||
} | |||
@@ -16,8 +16,8 @@ namespace Shadowsocks.Encryption | |||
private IntPtr _encryptCtx = IntPtr.Zero; | |||
private IntPtr _decryptCtx = IntPtr.Zero; | |||
public PolarSSLEncryptor(string method, string password, bool onetimeauth) | |||
: base(method, password, onetimeauth) | |||
public PolarSSLEncryptor(string method, string password, bool onetimeauth, bool isudp) | |||
: base(method, password, onetimeauth, isudp) | |||
{ | |||
InitKey(method, password); | |||
} | |||
@@ -20,8 +20,8 @@ namespace Shadowsocks.Encryption | |||
protected ulong _encryptIC; | |||
protected ulong _decryptIC; | |||
public SodiumEncryptor(string method, string password, bool onetimeauth) | |||
: base(method, password, onetimeauth) | |||
public SodiumEncryptor(string method, string password, bool onetimeauth, bool isudp) | |||
: base(method, password, onetimeauth, isudp) | |||
{ | |||
InitKey(method, password); | |||
} | |||
@@ -6,8 +6,8 @@ namespace Shadowsocks.Encryption | |||
public class TableEncryptor | |||
: EncryptorBase | |||
{ | |||
public TableEncryptor(string method, string password, bool onetimeauth) | |||
: base(method, password, onetimeauth) | |||
public TableEncryptor(string method, string password, bool onetimeauth, bool isudp) | |||
: base(method, password, onetimeauth, isudp) | |||
{ | |||
byte[] hash = GetPasswordHash(); | |||
// TODO endian | |||
@@ -31,7 +31,7 @@ namespace Shadowsocks.Encryption | |||
return new List<string>(new string[]{"table"}); | |||
} | |||
public override void Encrypt(byte[] buf, int length, byte[] outbuf, out int outlength, bool udp) | |||
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++) | |||
@@ -31,21 +31,21 @@ namespace test | |||
int outLen2 = 0; | |||
var random = new Random(); | |||
random.NextBytes(plain); | |||
encryptor.Encrypt(plain, plain.Length, cipher, out outLen, false); | |||
encryptor.Encrypt(plain, plain.Length, cipher, out outLen); | |||
decryptor.Decrypt(cipher, outLen, plain2, out outLen2); | |||
Assert.AreEqual(plain.Length, outLen2); | |||
for (int j = 0; j < plain.Length; j++) | |||
{ | |||
Assert.AreEqual(plain[j], plain2[j]); | |||
} | |||
encryptor.Encrypt(plain, 1000, cipher, out outLen, false); | |||
encryptor.Encrypt(plain, 1000, cipher, out outLen); | |||
decryptor.Decrypt(cipher, outLen, plain2, out outLen2); | |||
Assert.AreEqual(1000, outLen2); | |||
for (int j = 0; j < outLen2; j++) | |||
{ | |||
Assert.AreEqual(plain[j], plain2[j]); | |||
} | |||
encryptor.Encrypt(plain, 12333, cipher, out outLen, false); | |||
encryptor.Encrypt(plain, 12333, cipher, out outLen); | |||
decryptor.Decrypt(cipher, outLen, plain2, out outLen2); | |||
Assert.AreEqual(12333, outLen2); | |||
for (int j = 0; j < outLen2; j++) | |||
@@ -84,8 +84,8 @@ namespace test | |||
{ | |||
IEncryptor encryptor; | |||
IEncryptor decryptor; | |||
encryptor = new PolarSSLEncryptor("aes-256-cfb", "barfoo!", false); | |||
decryptor = new PolarSSLEncryptor("aes-256-cfb", "barfoo!", false); | |||
encryptor = new PolarSSLEncryptor("aes-256-cfb", "barfoo!", false, false); | |||
decryptor = new PolarSSLEncryptor("aes-256-cfb", "barfoo!", false, false); | |||
RunEncryptionRound(encryptor, decryptor); | |||
} | |||
} | |||
@@ -124,8 +124,8 @@ namespace test | |||
var random = new Random(); | |||
IEncryptor encryptor; | |||
IEncryptor decryptor; | |||
encryptor = new PolarSSLEncryptor("rc4-md5", "barfoo!", false); | |||
decryptor = new PolarSSLEncryptor("rc4-md5", "barfoo!", false); | |||
encryptor = new PolarSSLEncryptor("rc4-md5", "barfoo!", false, false); | |||
decryptor = new PolarSSLEncryptor("rc4-md5", "barfoo!", false, false); | |||
RunEncryptionRound(encryptor, decryptor); | |||
} | |||
} | |||
@@ -164,8 +164,8 @@ namespace test | |||
var random = new Random(); | |||
IEncryptor encryptor; | |||
IEncryptor decryptor; | |||
encryptor = new SodiumEncryptor("salsa20", "barfoo!", false); | |||
decryptor = new SodiumEncryptor("salsa20", "barfoo!", false); | |||
encryptor = new SodiumEncryptor("salsa20", "barfoo!", false, false); | |||
decryptor = new SodiumEncryptor("salsa20", "barfoo!", false, false); | |||
RunEncryptionRound(encryptor, decryptor); | |||
} | |||
} | |||