Browse Source

adjust test case, update EncryptorInfo API

pull/2865/head
Student Main 5 years ago
parent
commit
ac9eaaeb05
15 changed files with 239 additions and 276 deletions
  1. +2
    -11
      shadowsocks-csharp/Controller/Service/TCPRelay.cs
  2. +7
    -12
      shadowsocks-csharp/Encryption/AEAD/AEADAesGcmNativeEncryptor.cs
  3. +8
    -15
      shadowsocks-csharp/Encryption/AEAD/AEADBouncyCastleEncryptor.cs
  4. +14
    -19
      shadowsocks-csharp/Encryption/AEAD/AEADEncryptor.cs
  5. +11
    -15
      shadowsocks-csharp/Encryption/AEAD/AEADNaClEncryptor.cs
  6. +0
    -56
      shadowsocks-csharp/Encryption/AEAD/AEADNativeEncryptor.cs
  7. +85
    -0
      shadowsocks-csharp/Encryption/CipherInfo.cs
  8. +3
    -64
      shadowsocks-csharp/Encryption/EncryptorBase.cs
  9. +35
    -11
      shadowsocks-csharp/Encryption/EncryptorFactory.cs
  10. +3
    -2
      shadowsocks-csharp/Encryption/IEncryptor.cs
  11. +8
    -13
      shadowsocks-csharp/Encryption/Stream/StreamEncryptor.cs
  12. +9
    -20
      shadowsocks-csharp/Encryption/Stream/StreamRc4NativeEncryptor.cs
  13. +9
    -17
      shadowsocks-csharp/Encryption/Stream/StreamTableNativeEncryptor.cs
  14. +9
    -6
      shadowsocks-csharp/shadowsocks-csharp.csproj
  15. +36
    -15
      test/CryptographyTest.cs

+ 2
- 11
shadowsocks-csharp/Controller/Service/TCPRelay.cs View File

@@ -224,8 +224,8 @@ namespace Shadowsocks.Controller
/* prepare address buffer length for AEAD */
Logger.Debug($"_addrBufLength={_addrBufLength}");
encryptor.AddrBufLength = _addrBufLength;
decryptor.AddrBufLength = _addrBufLength;
encryptor.AddressBufferLength = _addrBufLength;
decryptor.AddressBufferLength = _addrBufLength;
}
public void Start(byte[] firstPacket, int length)
@@ -275,15 +275,6 @@ namespace Shadowsocks.Controller
Logger.LogUsefulException(e);
}
}
lock (_encryptionLock)
{
lock (_decryptionLock)
{
encryptor?.Dispose();
decryptor?.Dispose();
}
}
}
private void HandshakeReceive()


+ 7
- 12
shadowsocks-csharp/Encryption/AEAD/AEADAesGcmNativeEncryptor.cs View File

@@ -13,16 +13,15 @@ namespace Shadowsocks.Encryption.AEAD
public AEADAesGcmNativeEncryptor(string method, string password) : base(method, password)
{
}
static int CIPHER_AES = 1; // dummy

private static readonly Dictionary<string, EncryptorInfo> _ciphers = new Dictionary<string, EncryptorInfo>
private static readonly Dictionary<string, CipherInfo> _ciphers = new Dictionary<string, CipherInfo>
{
{"aes-128-gcm", new EncryptorInfo("AES-128-GCM", 16, 16, 12, 16, CIPHER_AES)},
{"aes-192-gcm", new EncryptorInfo("AES-192-GCM", 24, 24, 12, 16, CIPHER_AES)},
{"aes-256-gcm", new EncryptorInfo("AES-256-GCM", 32, 32, 12, 16, CIPHER_AES)},
{"aes-128-gcm", new CipherInfo("AES-128-GCM", 16, 16, 12, 16, CipherFamily.AesGcm)},
{"aes-192-gcm", new CipherInfo("AES-192-GCM", 24, 24, 12, 16, CipherFamily.AesGcm)},
{"aes-256-gcm", new CipherInfo("AES-256-GCM", 32, 32, 12, 16, CipherFamily.AesGcm)},
};

protected override Dictionary<string, EncryptorInfo> getCiphers()
protected override Dictionary<string, CipherInfo> getCiphers()
{
return _ciphers;
}
@@ -102,13 +101,9 @@ namespace Shadowsocks.Encryption.AEAD
return d.ToArray();
}

public static List<string> SupportedCiphers()
{
return new List<string>(_ciphers.Keys);
}

public override void Dispose()
public static Dictionary<string, CipherInfo> SupportedCiphers()
{
return _ciphers;
}
}
}

+ 8
- 15
shadowsocks-csharp/Encryption/AEAD/AEADBouncyCastleEncryptor.cs View File

@@ -11,22 +11,19 @@ namespace Shadowsocks.Encryption.AEAD
{
public class AEADBouncyCastleEncryptor : AEADEncryptor
{
static int CIPHER_AES = 1; // dummy
public AEADBouncyCastleEncryptor(string method, string password)
: base(method, password)
public AEADBouncyCastleEncryptor(string method, string password) : base(method, password)
{
}
private static readonly Dictionary<string, EncryptorInfo> _ciphers = new Dictionary<string, EncryptorInfo>
private static readonly Dictionary<string, CipherInfo> _ciphers = new Dictionary<string, CipherInfo>
{
{"aes-128-gcm", new EncryptorInfo("AES-128-GCM", 16, 16, 12, 16, CIPHER_AES)},
{"aes-192-gcm", new EncryptorInfo("AES-192-GCM", 24, 24, 12, 16, CIPHER_AES)},
{"aes-256-gcm", new EncryptorInfo("AES-256-GCM", 32, 32, 12, 16, CIPHER_AES)},
{"aes-128-gcm", new CipherInfo("aes-128-gcm", 16, 16, 12, 16, CipherFamily.AesGcm)},
{"aes-192-gcm", new CipherInfo("aes-192-gcm", 24, 24, 12, 16, CipherFamily.AesGcm)},
{"aes-256-gcm", new CipherInfo("aes-256-gcm", 32, 32, 12, 16, CipherFamily.AesGcm)},
};
protected override Dictionary<string, EncryptorInfo> getCiphers()
protected override Dictionary<string, CipherInfo> getCiphers()
{
return _ciphers;
}
@@ -90,14 +87,10 @@ namespace Shadowsocks.Encryption.AEAD
aes.DoFinal(cipher, len);
return cipher;
}
public static List<string> SupportedCiphers()
{
return new List<string>(_ciphers.Keys);
}
public override void Dispose()
public static Dictionary<string, CipherInfo> SupportedCiphers()
{
return _ciphers;
}
}
}

+ 14
- 19
shadowsocks-csharp/Encryption/AEAD/AEADEncryptor.cs View File

@@ -11,8 +11,7 @@ using Shadowsocks.Encryption.Stream;
namespace Shadowsocks.Encryption.AEAD
{
public abstract class AEADEncryptor
: EncryptorBase
public abstract class AEADEncryptor : EncryptorBase
{
private static Logger logger = LogManager.GetCurrentClassLogger();
// We are using the same saltLen and keyLen
@@ -29,13 +28,13 @@ namespace Shadowsocks.Encryption.AEAD
public const int CHUNK_LEN_BYTES = 2;
public const uint CHUNK_LEN_MASK = 0x3FFFu;
protected Dictionary<string, EncryptorInfo> ciphers;
protected Dictionary<string, CipherInfo> ciphers;
protected string _method;
protected int _cipher;
protected CipherFamily _cipher;
// internal name in the crypto library
protected string _innerLibName;
protected EncryptorInfo CipherInfo;
protected CipherInfo CipherInfo;
protected static byte[] _Masterkey = null;
protected byte[] sessionKey;
protected int keyLen;
@@ -67,7 +66,7 @@ namespace Shadowsocks.Encryption.AEAD
decNonce = new byte[nonceLen];
}
protected abstract Dictionary<string, EncryptorInfo> getCiphers();
protected abstract Dictionary<string, CipherInfo> getCiphers();
protected void InitEncryptorInfo(string method)
{
@@ -75,16 +74,12 @@ namespace Shadowsocks.Encryption.AEAD
_method = method;
ciphers = getCiphers();
CipherInfo = ciphers[_method];
_innerLibName = CipherInfo.InnerLibName;
_cipher = CipherInfo.Type;
if (_cipher == 0)
{
throw new System.Exception("method not found");
}
keyLen = CipherInfo.KeySize;
saltLen = CipherInfo.SaltSize;
tagLen = CipherInfo.TagSize;
nonceLen = CipherInfo.NonceSize;
var parameter = (AEADCipherParameter)CipherInfo.CipherParameter;
keyLen = parameter.KeySize;
saltLen = parameter.SaltSize;
tagLen = parameter.TagSize;
nonceLen = parameter.NonceSize;
}
protected void InitKey(string password)
@@ -196,10 +191,10 @@ namespace Shadowsocks.Encryption.AEAD
_tcpRequestSent = true;
// The first TCP request
int encAddrBufLength;
byte[] encAddrBufBytes = new byte[AddrBufLength + tagLen * 2 + CHUNK_LEN_BYTES];
byte[] addrBytes = _encCircularBuffer.Get(AddrBufLength);
ChunkEncrypt(addrBytes, AddrBufLength, encAddrBufBytes, out encAddrBufLength);
Debug.Assert(encAddrBufLength == AddrBufLength + tagLen * 2 + CHUNK_LEN_BYTES);
byte[] encAddrBufBytes = new byte[AddressBufferLength + tagLen * 2 + CHUNK_LEN_BYTES];
byte[] addrBytes = _encCircularBuffer.Get(AddressBufferLength);
ChunkEncrypt(addrBytes, AddressBufferLength, encAddrBufBytes, out encAddrBufLength);
Debug.Assert(encAddrBufLength == AddressBufferLength + tagLen * 2 + CHUNK_LEN_BYTES);
Array.Copy(encAddrBufBytes, 0, outbuf, outlength, encAddrBufLength);
outlength += encAddrBufLength;
logger.Debug($"_tcpRequestSent outlength {outlength}");


+ 11
- 15
shadowsocks-csharp/Encryption/AEAD/AEADNaClEncryptor.cs View File

@@ -15,7 +15,6 @@ namespace Shadowsocks.Encryption.AEAD
SnufflePoly1305 dec;
public AEADNaClEncryptor(string method, string password) : base(method, password)
{

}

public override void InitCipher(byte[] salt, bool isEncrypt, bool isUdp)
@@ -28,10 +27,10 @@ namespace Shadowsocks.Encryption.AEAD
switch (_cipher)
{
default:
case CipherChaCha20Poly1305:
case CipherFamily.Chacha20Poly1305:
tmp = new ChaCha20Poly1305(sessionKey);
break;
case CipherXChaCha20Poly1305:
case CipherFamily.XChacha20Poly1305:
tmp = new XChaCha20Poly1305(sessionKey);
break;
}
@@ -53,28 +52,25 @@ namespace Shadowsocks.Encryption.AEAD
clen = (uint)ct.Length;
}

public override void Dispose()
private static readonly Dictionary<string, CipherInfo> _ciphers = new Dictionary<string, CipherInfo>
{
}

const int CipherChaCha20Poly1305 = 1;
const int CipherXChaCha20Poly1305 = 2;
{"chacha20-ietf-poly1305", new CipherInfo("chacha20-ietf-poly1305",32, 32, 12, 16, CipherFamily.Chacha20Poly1305)},
{"xchacha20-ietf-poly1305", new CipherInfo("xchacha20-ietf-poly1305",32, 32, 24, 16, CipherFamily.XChacha20Poly1305)},
};

private static readonly Dictionary<string, EncryptorInfo> _ciphers = new Dictionary<string, EncryptorInfo>
protected override Dictionary<string, CipherInfo> getCiphers()
{
{"chacha20-ietf-poly1305", new EncryptorInfo(32, 32, 12, 16, 1)},
{"xchacha20-ietf-poly1305", new EncryptorInfo(32, 32, 24, 16, 2)},
//{"aes-256-gcm", new EncryptorInfo(32, 32, 12, 16, CIPHER_AES256GCM)},
};
return _ciphers;
}

protected override Dictionary<string, EncryptorInfo> getCiphers()
public static Dictionary<string, CipherInfo> SupportedCiphers()
{
return _ciphers;
}

public override byte[] CipherEncrypt2(byte[] plain)
{
return enc.Encrypt(plain, null, encNonce);
return enc.Encrypt(plain, null, encNonce);
}

public override byte[] CipherDecrypt2(byte[] cipher)


+ 0
- 56
shadowsocks-csharp/Encryption/AEAD/AEADNativeEncryptor.cs View File

@@ -1,56 +0,0 @@
using System;
using System.Collections.Generic;

namespace Shadowsocks.Encryption.AEAD
{
public class AEADNativeEncryptor : AEADEncryptor
{
public AEADNativeEncryptor(string method, string password)
: base(method, password)
{
}

public override void cipherDecrypt(byte[] ciphertext, uint clen, byte[] plaintext, ref uint plen)
{
Array.Copy(ciphertext, plaintext, 0);
plen = clen;

}

public override void cipherEncrypt(byte[] plaintext, uint plen, byte[] ciphertext, ref uint clen)
{
Array.Copy(plaintext, ciphertext, 0);
clen = plen;
}

public override void Dispose()
{
return;
}

private static Dictionary<string, EncryptorInfo> _ciphers = new Dictionary<string, EncryptorInfo>()
{
{"plain-fake-aead",new EncryptorInfo("PLAIN_AEAD",0,0,0,0,0) }
};

protected override Dictionary<string, EncryptorInfo> getCiphers()
{
return _ciphers;
}

public static IEnumerable<string> SupportedCiphers()
{
return _ciphers.Keys;
}

public override byte[] CipherEncrypt2(byte[] plain)
{
return plain;
}

public override byte[] CipherDecrypt2(byte[] cipher)
{
return cipher;
}
}
}

+ 85
- 0
shadowsocks-csharp/Encryption/CipherInfo.cs View File

@@ -0,0 +1,85 @@
using System;

namespace Shadowsocks.Encryption
{
public enum CipherFamily
{
Plain,
Table,

AesGcm,

AesCfb,
AesCtr,

Chacha20,
Chacha20Poly1305,
XChacha20Poly1305,

Rc4,
Rc4Md5,
}

public enum CipherStandardState
{
InUse,
Deprecated,
Hidden,
}

public class CipherParameter
{
public int KeySize;
}
public class StreamCipherParameter : CipherParameter
{
public int IvSize;
}

public class AEADCipherParameter : CipherParameter
{
public int SaltSize;
public int TagSize;
public int NonceSize;
}

public class CipherInfo
{
public string Name;
public CipherFamily Type;
public CipherParameter CipherParameter;

public CipherStandardState StandardState = CipherStandardState.InUse;

#region Stream ciphers
public CipherInfo(string name, int keySize, int ivSize, CipherFamily type)
{
Type = type;
Name = name;
StandardState = CipherStandardState.Hidden;
CipherParameter = new StreamCipherParameter
{
KeySize = keySize,
IvSize = ivSize,
};
}

#endregion

#region AEAD ciphers
public CipherInfo(string name, int keySize, int saltSize, int nonceSize, int tagSize, CipherFamily type)
{
Type = type;
Name = name;

CipherParameter = new AEADCipherParameter
{
KeySize = keySize,
SaltSize = saltSize,
NonceSize = nonceSize,
TagSize = tagSize,
};
}
#endregion
}
}

+ 3
- 64
shadowsocks-csharp/Encryption/EncryptorBase.cs View File

@@ -1,65 +1,6 @@
namespace Shadowsocks.Encryption
{
public class EncryptorInfo
{
public int KeySize;
public int IvSize;
public int SaltSize;
public int TagSize;
public int NonceSize;
public int Type;
public string InnerLibName;
// For those who make use of internal crypto method name
// e.g. mbed TLS
#region Stream ciphers
public EncryptorInfo(string innerLibName, int keySize, int ivSize, int type)
{
this.KeySize = keySize;
this.IvSize = ivSize;
this.Type = type;
this.InnerLibName = innerLibName;
}
public EncryptorInfo(int keySize, int ivSize, int type)
{
this.KeySize = keySize;
this.IvSize = ivSize;
this.Type = type;
this.InnerLibName = string.Empty;
}
#endregion
#region AEAD ciphers
public EncryptorInfo(string innerLibName, int keySize, int saltSize, int nonceSize, int tagSize, int type)
{
this.KeySize = keySize;
this.SaltSize = saltSize;
this.NonceSize = nonceSize;
this.TagSize = tagSize;
this.Type = type;
this.InnerLibName = innerLibName;
}
public EncryptorInfo(int keySize, int saltSize, int nonceSize, int tagSize, int type)
{
this.KeySize = keySize;
this.SaltSize = saltSize;
this.NonceSize = nonceSize;
this.TagSize = tagSize;
this.Type = type;
this.InnerLibName = string.Empty;
}
#endregion
}
public abstract class EncryptorBase
: IEncryptor
public abstract class EncryptorBase : IEncryptor
{
public const int MAX_INPUT_SIZE = 32768;
@@ -81,7 +22,7 @@
protected string Method;
protected string Password;
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);
@@ -90,8 +31,6 @@
public abstract void DecryptUDP(byte[] buf, int length, byte[] outbuf, out int outlength);
public abstract void Dispose();
public int AddrBufLength { get; set; } = - 1;
public int AddressBufferLength { get; set; } = -1;
}
}

+ 35
- 11
shadowsocks-csharp/Encryption/EncryptorFactory.cs View File

@@ -10,27 +10,51 @@ namespace Shadowsocks.Encryption
public static class EncryptorFactory
{
private static Dictionary<string, Type> _registeredEncryptors = new Dictionary<string, Type>();
private static Dictionary<string, CipherInfo> ciphers = new Dictionary<string, CipherInfo>();
private static readonly Type[] ConstructorTypes = { typeof(string), typeof(string) };
static EncryptorFactory()
{
foreach (string method in StreamTableNativeEncryptor.SupportedCiphers())
foreach (var method in StreamTableNativeEncryptor.SupportedCiphers())
{
if (!_registeredEncryptors.ContainsKey(method))
_registeredEncryptors.Add(method, typeof(StreamTableNativeEncryptor));
if (!_registeredEncryptors.ContainsKey(method.Key))
{
ciphers.Add(method.Key, method.Value);
_registeredEncryptors.Add(method.Key, typeof(StreamTableNativeEncryptor));
}
}
foreach (string method in AEADNativeEncryptor.SupportedCiphers())
foreach (var method in StreamRc4NativeEncryptor.SupportedCiphers())
{
if (!_registeredEncryptors.ContainsKey(method))
_registeredEncryptors.Add(method, typeof(AEADNativeEncryptor));
if (!_registeredEncryptors.ContainsKey(method.Key))
{
ciphers.Add(method.Key, method.Value);
_registeredEncryptors.Add(method.Key, typeof(StreamRc4NativeEncryptor));
}
}
foreach (string method in AEADBouncyCastleEncryptor.SupportedCiphers())
foreach (var method in AEADAesGcmNativeEncryptor.SupportedCiphers())
{
if (!_registeredEncryptors.ContainsKey(method.Key))
{
ciphers.Add(method.Key, method.Value);
_registeredEncryptors.Add(method.Key, typeof(AEADAesGcmNativeEncryptor));
}
}
foreach (var method in AEADNaClEncryptor.SupportedCiphers())
{
if (!_registeredEncryptors.ContainsKey(method.Key))
{
ciphers.Add(method.Key, method.Value);
_registeredEncryptors.Add(method.Key, typeof(AEADNaClEncryptor));
}
}
foreach (var method in StreamRc4NativeEncryptor.SupportedCiphers())
{
if (!_registeredEncryptors.ContainsKey(method))
_registeredEncryptors.Add(method, typeof(AEADBouncyCastleEncryptor));
if (!_registeredEncryptors.ContainsKey(method.Key))
{
ciphers.Add(method.Key, method.Value);
_registeredEncryptors.Add(method.Key, typeof(StreamRc4NativeEncryptor));
}
}
}


+ 3
- 2
shadowsocks-csharp/Encryption/IEncryptor.cs View File

@@ -1,11 +1,12 @@
using System;
using System.Collections.Generic;
namespace Shadowsocks.Encryption
{
public interface IEncryptor : IDisposable
public interface IEncryptor
{
/* length == -1 means not used */
int AddrBufLength { set; get; }
int AddressBufferLength { set; get; }
void Encrypt(byte[] buf, int length, byte[] outbuf, out int outlength);
void Decrypt(byte[] buf, int length, byte[] outbuf, out int outlength);
void EncryptUDP(byte[] buf, int length, byte[] outbuf, out int outlength);


+ 8
- 13
shadowsocks-csharp/Encryption/Stream/StreamEncryptor.cs View File

@@ -7,8 +7,7 @@ using Shadowsocks.Controller;
namespace Shadowsocks.Encryption.Stream
{
public abstract class StreamEncryptor
: EncryptorBase
public abstract class StreamEncryptor : EncryptorBase
{
// for UDP only
protected static byte[] _udpTmpBuf = new byte[65536];
@@ -17,7 +16,7 @@ namespace Shadowsocks.Encryption.Stream
private ByteCircularBuffer _encCircularBuffer = new ByteCircularBuffer(TCPHandler.BufferSize * 2);
private ByteCircularBuffer _decCircularBuffer = new ByteCircularBuffer(TCPHandler.BufferSize * 2);
protected Dictionary<string, EncryptorInfo> ciphers;
protected Dictionary<string, CipherInfo> ciphers;
protected byte[] _encryptIV;
protected byte[] _decryptIV;
@@ -27,10 +26,10 @@ namespace Shadowsocks.Encryption.Stream
protected bool _encryptIVSent;
protected string _method;
protected int _cipher;
protected CipherFamily _cipher;
// internal name in the crypto library
protected string _innerLibName;
protected EncryptorInfo CipherInfo;
protected CipherInfo CipherInfo;
// long-time master key
protected static byte[] _key = null;
protected int keyLen;
@@ -43,7 +42,7 @@ namespace Shadowsocks.Encryption.Stream
InitKey(password);
}
protected abstract Dictionary<string, EncryptorInfo> getCiphers();
protected abstract Dictionary<string, CipherInfo> getCiphers();
private void InitEncryptorInfo(string method)
{
@@ -51,14 +50,10 @@ namespace Shadowsocks.Encryption.Stream
_method = method;
ciphers = getCiphers();
CipherInfo = ciphers[_method];
_innerLibName = CipherInfo.InnerLibName;
_cipher = CipherInfo.Type;
if (_cipher == 0)
{
throw new System.Exception("method not found");
}
keyLen = CipherInfo.KeySize;
ivLen = CipherInfo.IvSize;
var parameter = (StreamCipherParameter)CipherInfo.CipherParameter;
keyLen = parameter.KeySize;
ivLen = parameter.IvSize;
}
private void InitKey(string password)


+ 9
- 20
shadowsocks-csharp/Encryption/Stream/StreamRc4NativeEncryptor.cs View File

@@ -8,27 +8,16 @@ namespace Shadowsocks.Encryption.Stream
{
public class StreamRc4NativeEncryptor : StreamEncryptor
{
const int Rc4 = 0;
const int Rc4Md5 = 1;

string _password;

byte[] realkey;
byte[] sbox;
byte[] realkey = new byte[256];
byte[] sbox = new byte[256];
public StreamRc4NativeEncryptor(string method, string password) : base(method, password)
{
_password = password;
}

public override void Dispose()
{
return;
}

protected override void initCipher(byte[] iv, bool isEncrypt)
{
base.initCipher(iv, isEncrypt);
if (_cipher == Rc4Md5)
if (_cipher == CipherFamily.Rc4Md5)
{
byte[] temp = new byte[keyLen + ivLen];
Array.Copy(_key, 0, temp, 0, keyLen);
@@ -54,19 +43,19 @@ namespace Shadowsocks.Encryption.Stream
Array.Copy(t, outbuf, length);
}

private static readonly Dictionary<string, EncryptorInfo> _ciphers = new Dictionary<string, EncryptorInfo>
private static readonly Dictionary<string, CipherInfo> _ciphers = new Dictionary<string, CipherInfo>
{
// original RC4 doesn't use IV
{ "rc4", new EncryptorInfo("RC4", 16, 0, Rc4) },
{ "rc4-md5", new EncryptorInfo("RC4", 16, 16, Rc4Md5) },
{ "rc4", new CipherInfo("rc4", 16, 0, CipherFamily.Rc4) },
{ "rc4-md5", new CipherInfo("rc4-md5", 16, 16, CipherFamily.Rc4Md5) },
};

public static IEnumerable<string> SupportedCiphers()
public static Dictionary<string, CipherInfo> SupportedCiphers()
{
return _ciphers.Keys;
return _ciphers;
}

protected override Dictionary<string, EncryptorInfo> getCiphers()
protected override Dictionary<string, CipherInfo> getCiphers()
{
return _ciphers;
}


+ 9
- 17
shadowsocks-csharp/Encryption/Stream/StreamTableNativeEncryptor.cs View File

@@ -8,9 +8,6 @@ namespace Shadowsocks.Encryption.Stream
{
public class StreamTableNativeEncryptor : StreamEncryptor
{
const int Plain = 0;
const int Table = 1;

string _password;

public StreamTableNativeEncryptor(string method, string password) : base(method, password)
@@ -18,15 +15,10 @@ namespace Shadowsocks.Encryption.Stream
_password = password;
}

public override void Dispose()
{
return;
}

protected override void initCipher(byte[] iv, bool isEncrypt)
{
base.initCipher(iv, isEncrypt);
if (_cipher == Table)
if (_cipher == CipherFamily.Table)
{
ulong a = BitConverter.ToUInt64(CryptoUtils.MD5(Encoding.UTF8.GetBytes(_password)), 0);
for (int i = 0; i < 256; i++)
@@ -46,7 +38,7 @@ namespace Shadowsocks.Encryption.Stream

protected override void cipherUpdate(bool isEncrypt, int length, byte[] buf, byte[] outbuf)
{
if (_cipher == Table)
if (_cipher == CipherFamily.Table)
{
var table = isEncrypt ? _encryptTable : _decryptTable;
for (int i = 0; i < length; i++)
@@ -54,24 +46,24 @@ namespace Shadowsocks.Encryption.Stream
outbuf[i] = table[buf[i]];
}
}
else if (_cipher == Plain)
else if (_cipher == CipherFamily.Plain)
{
Array.Copy(buf, outbuf, length);
}
}

private static readonly Dictionary<string, EncryptorInfo> _ciphers = new Dictionary<string, EncryptorInfo>
private static readonly Dictionary<string, CipherInfo> _ciphers = new Dictionary<string, CipherInfo>
{
{"plain", new EncryptorInfo("PLAIN", 0, 0, Plain) },
{"table", new EncryptorInfo("TABLE", 0, 0, Table) },
{"plain", new CipherInfo("plain", 0, 0, CipherFamily.Plain) },
{"table", new CipherInfo("table", 0, 0, CipherFamily.Table) },
};

public static IEnumerable<string> SupportedCiphers()
public static Dictionary<string, CipherInfo> SupportedCiphers()
{
return _ciphers.Keys;
return _ciphers;
}

protected override Dictionary<string, EncryptorInfo> getCiphers()
protected override Dictionary<string, CipherInfo> getCiphers()
{
return _ciphers;
}


+ 9
- 6
shadowsocks-csharp/shadowsocks-csharp.csproj View File

@@ -11,7 +11,12 @@
<Version>4.1.9.2</Version>
<AssemblyName>Shadowsocks</AssemblyName>
<ApplicationIcon>shadowsocks.ico</ApplicationIcon>
<StartupObject />
<StartupObject>Shadowsocks.Program</StartupObject>
<Nullable>enable</Nullable>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<DefineConstants>TRACE</DefineConstants>
</PropertyGroup>
<ItemGroup>
@@ -58,26 +63,24 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="BouncyCastle.NetCore" Version="1.8.5" />
<PackageReference Include="Caseless.Fody" Version="1.9.0" />
<!--PackageReference Include="Caseless.Fody" Version="1.9.0" />
<PackageReference Include="Costura.Fody" Version="4.1.0" />
<PackageReference Include="Fody" Version="6.1.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</PackageReference-->
<PackageReference Include="Microsoft.VisualBasic" Version="10.3.0" />
<PackageReference Include="NaCl.Core" Version="1.2.0" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="NLog" Version="4.6.8" />
<PackageReference Include="ZXing.Net" Version="0.16.5" />
<PackageReference Include="StringEx.CS" Version="0.3.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="System.Data.SqlClient" Version="4.8.1" />
<PackageReference Include="System.Management" Version="4.7.0" />
<PackageReference Include="ZXing.Net" Version="0.16.5" />
</ItemGroup>
<ItemGroup>


+ 36
- 15
test/CryptographyTest.cs View File

@@ -11,7 +11,7 @@ namespace Shadowsocks.Test
[TestClass]
public class CryptographyTest
{
Random random = new Random();
[TestMethod]
public void TestMD5()
{
@@ -19,7 +19,6 @@ namespace Shadowsocks.Test
{
System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create();
byte[] bytes = new byte[len];
var random = new Random();
random.NextBytes(bytes);
string md5str = Convert.ToBase64String(md5.ComputeHash(bytes));
string md5str2 = Convert.ToBase64String(CryptoUtils.MD5(bytes));
@@ -33,12 +32,12 @@ namespace Shadowsocks.Test
byte[] plain = new byte[16384];
byte[] cipher = new byte[plain.Length + 100];// AEAD with IPv4 address type needs +100
byte[] plain2 = new byte[plain.Length + 16];
int outLen = 0;
int outLen2 = 0;
var random = new Random();
//random = new Random();
random.NextBytes(plain);
encryptor.Encrypt(plain, plain.Length, cipher, out outLen);
decryptor.Decrypt(cipher, outLen, plain2, out outLen2);
encryptor.Encrypt(plain, plain.Length, cipher, out int outLen);
decryptor.Decrypt(cipher, outLen, plain2, out int outLen2);
Assert.AreEqual(plain.Length, outLen2);
for (int j = 0; j < plain.Length; j++)
{
@@ -66,15 +65,16 @@ namespace Shadowsocks.Test
{
var ector = enc.GetConstructor(new Type[] { typeof(string), typeof(string) });
var dctor = dec.GetConstructor(new Type[] { typeof(string), typeof(string) });
try
{
for (int i = 0; i < 100; i++)
IEncryptor encryptor = (IEncryptor)ector.Invoke(new object[] { method, password });
IEncryptor decryptor = (IEncryptor)dctor.Invoke(new object[] { method, password });
encryptor.AddressBufferLength = 1 + 4 + 2;// ADDR_ATYP_LEN + 4 + ADDR_PORT_LEN;
decryptor.AddressBufferLength = 1 + 4 + 2;// ADDR_ATYP_LEN + 4 + ADDR_PORT_LEN;
for (int i = 0; i < 16; i++)
{
IEncryptor encryptor = (IEncryptor)ector.Invoke(new object[] { method, password });
IEncryptor decryptor = (IEncryptor)dctor.Invoke(new object[] { method, password });
encryptor.AddrBufLength = 1 + 4 + 2;// ADDR_ATYP_LEN + 4 + ADDR_PORT_LEN;
decryptor.AddrBufLength = 1 + 4 + 2;// ADDR_ATYP_LEN + 4 + ADDR_PORT_LEN;
RunEncryptionRound(encryptor, decryptor);
}
}
@@ -98,7 +98,7 @@ namespace Shadowsocks.Test
// run it once before the multi-threading test to initialize global tables
RunSingleEncryptionThread(enc, dec, method);
List<Thread> threads = new List<Thread>();
for (int i = 0; i < 10; i++)
for (int i = 0; i < 8; i++)
{
Thread t = new Thread(new ThreadStart(() => RunSingleEncryptionThread(enc, dec, method))); threads.Add(t);
t.Start();
@@ -114,20 +114,41 @@ namespace Shadowsocks.Test
[TestMethod]
public void TestBouncyCastleAEADEncryption()
{
TestEncryptionMethod(typeof(AEADBouncyCastleEncryptor), "aes-128-gcm");
TestEncryptionMethod(typeof(AEADBouncyCastleEncryptor), "aes-192-gcm");
TestEncryptionMethod(typeof(AEADBouncyCastleEncryptor), "aes-256-gcm");
}
[TestMethod]
public void TestAesGcmNativeAEADEncryption()
{
TestEncryptionMethod(typeof(AEADAesGcmNativeEncryptor), "aes-128-gcm");
TestEncryptionMethod(typeof(AEADAesGcmNativeEncryptor), "aes-192-gcm");
TestEncryptionMethod(typeof(AEADAesGcmNativeEncryptor), "aes-256-gcm");
}
[TestMethod]
public void TestNaClAEADEncryption()
{
TestEncryptionMethod(typeof(AEADNaClEncryptor), "chacha20-ietf-poly1305");
TestEncryptionMethod(typeof(AEADNaClEncryptor), "xchacha20-ietf-poly1305");
}
[TestMethod]
public void TestNativeEncryption()
{
//TestEncryptionMethod(typeof(StreamTableNativeEncryptor), "table");
TestEncryptionMethod(typeof(StreamTableNativeEncryptor), "plain");
TestEncryptionMethod(typeof(StreamRc4NativeEncryptor), "rc4");
TestEncryptionMethod(typeof(StreamRc4NativeEncryptor), "rc4-md5");
}
[TestMethod]
public void TestNativeTableEncryption()
{
// Too slow, run once to save CPU
var enc = new StreamTableNativeEncryptor("table", "barfoo!");
var dec = new StreamTableNativeEncryptor("table", "barfoo!");
RunEncryptionRound(enc, dec);
}
}
}

Loading…
Cancel
Save