Browse Source

remove libsscrypto.dll.gz

pull/2865/head
Student Main 4 years ago
parent
commit
09c3b73e32
20 changed files with 83 additions and 1855 deletions
  1. +1
    -1
      shadowsocks-csharp/Controller/Service/PACServer.cs
  2. BIN
      shadowsocks-csharp/Data/libsscrypto.dll.gz
  3. +2
    -4
      shadowsocks-csharp/Encryption/AEAD/AEADEncryptor.cs
  4. +0
    -234
      shadowsocks-csharp/Encryption/AEAD/AEADMbedTLSEncryptor.cs
  5. +1
    -4
      shadowsocks-csharp/Encryption/AEAD/AEADNativeEncryptor.cs
  6. +0
    -192
      shadowsocks-csharp/Encryption/AEAD/AEADOpenSSLEncryptor.cs
  7. +0
    -141
      shadowsocks-csharp/Encryption/AEAD/AEADSodiumEncryptor.cs
  8. +4
    -46
      shadowsocks-csharp/Encryption/EncryptorFactory.cs
  9. +0
    -109
      shadowsocks-csharp/Encryption/MbedTLS.cs
  10. +0
    -164
      shadowsocks-csharp/Encryption/OpenSSL.cs
  11. +0
    -113
      shadowsocks-csharp/Encryption/Sodium.cs
  12. +2
    -2
      shadowsocks-csharp/Encryption/Stream/StreamEncryptor.cs
  13. +0
    -155
      shadowsocks-csharp/Encryption/Stream/StreamMbedTLSEncryptor.cs
  14. +2
    -2
      shadowsocks-csharp/Encryption/Stream/StreamNativeEncryptor.cs
  15. +0
    -159
      shadowsocks-csharp/Encryption/Stream/StreamOpenSSLEncryptor.cs
  16. +0
    -107
      shadowsocks-csharp/Encryption/Stream/StreamSodiumEncryptor.cs
  17. +68
    -85
      shadowsocks-csharp/Properties/Resources.Designer.cs
  18. +0
    -3
      shadowsocks-csharp/Properties/Resources.resx
  19. +1
    -10
      shadowsocks-csharp/shadowsocks-csharp.csproj
  20. +2
    -324
      test/CryptographyTest.cs

+ 1
- 1
shadowsocks-csharp/Controller/Service/PACServer.cs View File

@@ -51,7 +51,7 @@ namespace Shadowsocks.Controller
private static string GetHash(string content)
{
return HttpServerUtility.UrlTokenEncode(MbedTLS.MD5(Encoding.ASCII.GetBytes(content)));
return HttpServerUtility.UrlTokenEncode(CryptoUtils.MD5(Encoding.ASCII.GetBytes(content)));
}
public override bool Handle(byte[] firstPacket, int length, Socket socket, object state)


BIN
shadowsocks-csharp/Data/libsscrypto.dll.gz View File


+ 2
- 4
shadowsocks-csharp/Encryption/AEAD/AEADEncryptor.cs View File

@@ -103,15 +103,13 @@ namespace Shadowsocks.Encryption.AEAD
public void DeriveSessionKey(byte[] salt, byte[] masterKey, byte[] sessionKey)
{
int ret = MbedTLS.hkdf(salt, saltLen, masterKey, keyLen, InfoBytes, InfoBytes.Length, sessionKey,
keyLen);
if (ret != 0) throw new System.Exception("failed to generate session key");
CryptoUtils.HKDF(keyLen, masterKey, salt, InfoBytes).CopyTo(sessionKey,0);
}
protected void IncrementNonce(bool isEncrypt)
{
lock (_nonceIncrementLock) {
Sodium.sodium_increment(isEncrypt ? _encNonce : _decNonce, nonceLen);
CryptoUtils.SodiumIncrement(isEncrypt ? _encNonce : _decNonce);
}
}


+ 0
- 234
shadowsocks-csharp/Encryption/AEAD/AEADMbedTLSEncryptor.cs View File

@@ -1,234 +0,0 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Modes;
using Org.BouncyCastle.Crypto.Parameters;
using Shadowsocks.Encryption.Exception;
namespace Shadowsocks.Encryption.AEAD
{
public class AEADMbedTLSEncryptor
: AEADEncryptor, IDisposable
{
const int CIPHER_AES = 1;
private IntPtr _encryptCtx = IntPtr.Zero;
private IntPtr _decryptCtx = IntPtr.Zero;
public AEADMbedTLSEncryptor(string method, string password)
: base(method, password)
{
}
private static readonly Dictionary<string, EncryptorInfo> _ciphers = new Dictionary<string, EncryptorInfo>
{
{"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)},
};
public static List<string> SupportedCiphers()
{
return new List<string>(_ciphers.Keys);
}
protected override Dictionary<string, EncryptorInfo> getCiphers()
{
return _ciphers;
}
public override void InitCipher(byte[] salt, bool isEncrypt, bool isUdp)
{
base.InitCipher(salt, isEncrypt, isUdp);
IntPtr ctx = Marshal.AllocHGlobal(MbedTLS.cipher_get_size_ex());
if (isEncrypt)
{
_encryptCtx = ctx;
}
else
{
_decryptCtx = ctx;
}
MbedTLS.cipher_init(ctx);
if (MbedTLS.cipher_setup(ctx, MbedTLS.cipher_info_from_string(_innerLibName)) != 0)
throw new System.Exception("Cannot initialize mbed TLS cipher context");
DeriveSessionKey(isEncrypt ? _encryptSalt : _decryptSalt,
_Masterkey, _sessionKey);
CipherSetKey(isEncrypt, _sessionKey);
}
private void CipherSetKey(bool isEncrypt, byte[] key)
{
IntPtr ctx = isEncrypt ? _encryptCtx : _decryptCtx;
int ret = MbedTLS.cipher_setkey(ctx, key, keyLen * 8,
isEncrypt ? MbedTLS.MBEDTLS_ENCRYPT : MbedTLS.MBEDTLS_DECRYPT);
if (ret != 0) throw new System.Exception("failed to set key");
ret = MbedTLS.cipher_reset(ctx);
if (ret != 0) throw new System.Exception("failed to finish preparation");
}
public override void cipherEncrypt(byte[] plaintext, uint plen, byte[] ciphertext, ref uint clen)
{
// buf: all plaintext
// outbuf: ciphertext + tag
int ret;
byte[] tagbuf = new byte[tagLen];
uint olen = 0;
switch (_cipher)
{
case CIPHER_AES:
ret = MbedTLS.cipher_auth_encrypt(_encryptCtx,
/* nonce */
_encNonce, (uint)nonceLen,
/* AD */
IntPtr.Zero, 0,
/* plain */
plaintext, plen,
/* cipher */
ciphertext, ref olen,
tagbuf, (uint)tagLen);
if (ret != 0) throw new CryptoErrorException(String.Format("ret is {0}", ret));
Debug.Assert(olen == plen);
// attach tag to ciphertext
Array.Copy(tagbuf, 0, ciphertext, (int)plen, tagLen);
clen = olen + (uint)tagLen;
/////////
GcmBlockCipher cipher = new GcmBlockCipher(new AesEngine());
AeadParameters parameters = new AeadParameters(new KeyParameter(_sessionKey), tagLen * 8, _encNonce);
cipher.Init(true, parameters);
var ciphertext2 = new byte[cipher.GetOutputSize((int)plen)];
var len = cipher.ProcessBytes(plaintext, 0, (int)plen, ciphertext2, 0);
cipher.DoFinal(ciphertext2, len);
var clen2 = (uint)(ciphertext2.Length);
if (clen != clen2) throw new System.Exception();
for (int i = 0; i < ciphertext.Length; i++)
{
if (ciphertext[i] != ciphertext2[i])
{
throw new System.Exception();
}
}
//overwrite
ciphertext = ciphertext2;
clen = clen2;
/////////
break;
default:
throw new System.Exception("not implemented");
}
}
public override void cipherDecrypt(byte[] ciphertext, uint clen, byte[] plaintext, ref uint plen)
{
// buf: ciphertext + tag
// outbuf: plaintext
int ret;
uint olen = 0;
// split tag
byte[] tagbuf = new byte[tagLen];
Array.Copy(ciphertext, (int) (clen - tagLen), tagbuf, 0, tagLen);
switch (_cipher)
{
case CIPHER_AES:
ret = MbedTLS.cipher_auth_decrypt(_decryptCtx,
_decNonce, (uint)nonceLen,
IntPtr.Zero, 0,
ciphertext, (uint)(clen - tagLen),
plaintext, ref olen,
tagbuf, (uint)tagLen);
if (ret != 0) throw new CryptoErrorException(String.Format("ret is {0}", ret));
Debug.Assert(olen == clen - tagLen);
plen = olen;
/////////
GcmBlockCipher cipher = new GcmBlockCipher(new AesEngine());
AeadParameters parameters = new AeadParameters(new KeyParameter(_sessionKey), tagLen * 8, _decNonce);
cipher.Init(false, parameters);
var plaintext2 = new byte[cipher.GetOutputSize((int)clen)];
var len = cipher.ProcessBytes(ciphertext, 0, (int)clen, plaintext2, 0);
cipher.DoFinal(plaintext2, len);
var plen2 = (uint)(plaintext2.Length);
if (plen != plen2) throw new System.Exception();
for (int i = 0; i < plaintext.Length; i++)
{
if (plaintext[i] != plaintext2[i])
{
throw new System.Exception();
}
}
//overwrite
plaintext = plaintext2;
plen = plen2;
/////////
break;
default:
throw new System.Exception("not implemented");
}
}
#region IDisposable
private bool _disposed;
// instance based lock
private readonly object _lock = new object();
public override void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
~AEADMbedTLSEncryptor()
{
Dispose(false);
}
protected virtual void Dispose(bool disposing)
{
lock (_lock)
{
if (_disposed) return;
_disposed = true;
}
if (disposing)
{
// free managed objects
}
// free unmanaged objects
if (_encryptCtx != IntPtr.Zero)
{
MbedTLS.cipher_free(_encryptCtx);
Marshal.FreeHGlobal(_encryptCtx);
_encryptCtx = IntPtr.Zero;
}
if (_decryptCtx != IntPtr.Zero)
{
MbedTLS.cipher_free(_decryptCtx);
Marshal.FreeHGlobal(_decryptCtx);
_decryptCtx = IntPtr.Zero;
}
}
#endregion
}
}

+ 1
- 4
shadowsocks-csharp/Encryption/AEAD/AEADNativeEncryptor.cs View File

@@ -1,8 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Shadowsocks.Encryption.AEAD
{
@@ -33,7 +30,7 @@ namespace Shadowsocks.Encryption.AEAD

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




+ 0
- 192
shadowsocks-csharp/Encryption/AEAD/AEADOpenSSLEncryptor.cs View File

@@ -1,192 +0,0 @@
using System;
using System.Collections.Generic;
using Shadowsocks.Encryption.Exception;
namespace Shadowsocks.Encryption.AEAD
{
public class AEADOpenSSLEncryptor
: AEADEncryptor, IDisposable
{
const int CIPHER_AES = 1;
const int CIPHER_CHACHA20IETFPOLY1305 = 2;
private byte[] _opensslEncSubkey;
private byte[] _opensslDecSubkey;
private IntPtr _encryptCtx = IntPtr.Zero;
private IntPtr _decryptCtx = IntPtr.Zero;
private IntPtr _cipherInfoPtr = IntPtr.Zero;
public AEADOpenSSLEncryptor(string method, string password)
: base(method, password)
{
_opensslEncSubkey = new byte[keyLen];
_opensslDecSubkey = new byte[keyLen];
}
private static readonly Dictionary<string, EncryptorInfo> _ciphers = new Dictionary<string, EncryptorInfo>
{
{"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)},
{"chacha20-ietf-poly1305", new EncryptorInfo("chacha20-poly1305", 32, 32, 12, 16, CIPHER_CHACHA20IETFPOLY1305)}
};
public static List<string> SupportedCiphers()
{
return new List<string>(_ciphers.Keys);
}
protected override Dictionary<string, EncryptorInfo> getCiphers()
{
return _ciphers;
}
public override void InitCipher(byte[] salt, bool isEncrypt, bool isUdp)
{
base.InitCipher(salt, isEncrypt, isUdp);
_cipherInfoPtr = OpenSSL.GetCipherInfo(_innerLibName);
if (_cipherInfoPtr == IntPtr.Zero) throw new System.Exception("openssl: cipher not found");
IntPtr ctx = OpenSSL.EVP_CIPHER_CTX_new();
if (ctx == IntPtr.Zero) throw new System.Exception("openssl: fail to create ctx");
if (isEncrypt)
{
_encryptCtx = ctx;
}
else
{
_decryptCtx = ctx;
}
DeriveSessionKey(isEncrypt ? _encryptSalt : _decryptSalt, _Masterkey,
isEncrypt ? _opensslEncSubkey : _opensslDecSubkey);
var ret = OpenSSL.EVP_CipherInit_ex(ctx, _cipherInfoPtr, IntPtr.Zero, null, null,
isEncrypt ? OpenSSL.OPENSSL_ENCRYPT : OpenSSL.OPENSSL_DECRYPT);
if (ret != 1) throw new System.Exception("openssl: fail to init ctx");
ret = OpenSSL.EVP_CIPHER_CTX_set_key_length(ctx, keyLen);
if (ret != 1) throw new System.Exception("openssl: fail to set key length");
ret = OpenSSL.EVP_CIPHER_CTX_ctrl(ctx, OpenSSL.EVP_CTRL_AEAD_SET_IVLEN,
nonceLen, IntPtr.Zero);
if (ret != 1) throw new System.Exception("openssl: fail to set AEAD nonce length");
ret = OpenSSL.EVP_CipherInit_ex(ctx, IntPtr.Zero, IntPtr.Zero,
isEncrypt ? _opensslEncSubkey : _opensslDecSubkey,
null,
isEncrypt ? OpenSSL.OPENSSL_ENCRYPT : OpenSSL.OPENSSL_DECRYPT);
if (ret != 1) throw new System.Exception("openssl: cannot set key");
OpenSSL.EVP_CIPHER_CTX_set_padding(ctx, 0);
}
public override void cipherEncrypt(byte[] plaintext, uint plen, byte[] ciphertext, ref uint clen)
{
OpenSSL.SetCtxNonce(_encryptCtx, _encNonce, true);
// buf: all plaintext
// outbuf: ciphertext + tag
int ret;
int tmpLen = 0;
clen = 0;
var tagBuf = new byte[tagLen];
ret = OpenSSL.EVP_CipherUpdate(_encryptCtx, ciphertext, out tmpLen,
plaintext, (int) plen);
if (ret != 1) throw new CryptoErrorException("openssl: fail to encrypt AEAD");
clen += (uint) tmpLen;
// For AEAD cipher, it should not output anything
ret = OpenSSL.EVP_CipherFinal_ex(_encryptCtx, ciphertext, ref tmpLen);
if (ret != 1) throw new CryptoErrorException("openssl: fail to finalize AEAD");
if (tmpLen > 0)
{
throw new System.Exception("openssl: fail to finish AEAD");
}
OpenSSL.AEADGetTag(_encryptCtx, tagBuf, tagLen);
Array.Copy(tagBuf, 0, ciphertext, clen, tagLen);
clen += (uint) tagLen;
}
public override void cipherDecrypt(byte[] ciphertext, uint clen, byte[] plaintext, ref uint plen)
{
OpenSSL.SetCtxNonce(_decryptCtx, _decNonce, false);
// buf: ciphertext + tag
// outbuf: plaintext
int ret;
int tmpLen = 0;
plen = 0;
// split tag
byte[] tagbuf = new byte[tagLen];
Array.Copy(ciphertext, (int) (clen - tagLen), tagbuf, 0, tagLen);
OpenSSL.AEADSetTag(_decryptCtx, tagbuf, tagLen);
ret = OpenSSL.EVP_CipherUpdate(_decryptCtx,
plaintext, out tmpLen, ciphertext, (int) (clen - tagLen));
if (ret != 1) throw new CryptoErrorException("openssl: fail to decrypt AEAD");
plen += (uint) tmpLen;
// For AEAD cipher, it should not output anything
ret = OpenSSL.EVP_CipherFinal_ex(_decryptCtx, plaintext, ref tmpLen);
if (ret <= 0)
{
// If this is not successful authenticated
throw new CryptoErrorException(String.Format("ret is {0}", ret));
}
if (tmpLen > 0)
{
throw new System.Exception("openssl: fail to finish AEAD");
}
}
#region IDisposable
private bool _disposed;
// instance based lock
private readonly object _lock = new object();
public override void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
~AEADOpenSSLEncryptor()
{
Dispose(false);
}
protected virtual void Dispose(bool disposing)
{
lock (_lock)
{
if (_disposed) return;
_disposed = true;
}
if (disposing)
{
// free managed objects
}
// free unmanaged objects
if (_encryptCtx != IntPtr.Zero)
{
OpenSSL.EVP_CIPHER_CTX_free(_encryptCtx);
_encryptCtx = IntPtr.Zero;
}
if (_decryptCtx != IntPtr.Zero)
{
OpenSSL.EVP_CIPHER_CTX_free(_decryptCtx);
_decryptCtx = IntPtr.Zero;
}
}
#endregion
}
}

+ 0
- 141
shadowsocks-csharp/Encryption/AEAD/AEADSodiumEncryptor.cs View File

@@ -1,141 +0,0 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using NLog;
using Shadowsocks.Controller;
using Shadowsocks.Encryption.Exception;
namespace Shadowsocks.Encryption.AEAD
{
public class AEADSodiumEncryptor
: AEADEncryptor, IDisposable
{
private static Logger logger = LogManager.GetCurrentClassLogger();
private const int CIPHER_CHACHA20IETFPOLY1305 = 1;
private const int CIPHER_XCHACHA20IETFPOLY1305 = 2;
private const int CIPHER_AES256GCM = 3;
private byte[] _sodiumEncSubkey;
private byte[] _sodiumDecSubkey;
public AEADSodiumEncryptor(string method, string password)
: base(method, password)
{
_sodiumEncSubkey = new byte[keyLen];
_sodiumDecSubkey = new byte[keyLen];
}
private static readonly Dictionary<string, EncryptorInfo> _ciphers = new Dictionary<string, EncryptorInfo>
{
{"chacha20-ietf-poly1305", new EncryptorInfo(32, 32, 12, 16, CIPHER_CHACHA20IETFPOLY1305)},
{"xchacha20-ietf-poly1305", new EncryptorInfo(32, 32, 24, 16, CIPHER_XCHACHA20IETFPOLY1305)},
{"aes-256-gcm", new EncryptorInfo(32, 32, 12, 16, CIPHER_AES256GCM)},
};
public static List<string> SupportedCiphers()
{
return new List<string>(_ciphers.Keys);
}
protected override Dictionary<string, EncryptorInfo> getCiphers()
{
return _ciphers;
}
public override void InitCipher(byte[] salt, bool isEncrypt, bool isUdp)
{
base.InitCipher(salt, isEncrypt, isUdp);
DeriveSessionKey(isEncrypt ? _encryptSalt : _decryptSalt, _Masterkey,
isEncrypt ? _sodiumEncSubkey : _sodiumDecSubkey);
}
public override void cipherEncrypt(byte[] plaintext, uint plen, byte[] ciphertext, ref uint clen)
{
Debug.Assert(_sodiumEncSubkey != null);
// buf: all plaintext
// outbuf: ciphertext + tag
int ret;
ulong encClen = 0;
logger.Dump("_encNonce before enc", _encNonce, nonceLen);
logger.Dump("_sodiumEncSubkey", _sodiumEncSubkey, keyLen);
logger.Dump("before cipherEncrypt: plain", plaintext, (int) plen);
switch (_cipher)
{
case CIPHER_CHACHA20IETFPOLY1305:
ret = Sodium.crypto_aead_chacha20poly1305_ietf_encrypt(ciphertext, ref encClen,
plaintext, (ulong) plen,
null, 0,
null, _encNonce,
_sodiumEncSubkey);
break;
case CIPHER_XCHACHA20IETFPOLY1305:
ret = Sodium.crypto_aead_xchacha20poly1305_ietf_encrypt(ciphertext, ref encClen,
plaintext, (ulong)plen,
null, 0,
null, _encNonce,
_sodiumEncSubkey);
break;
case CIPHER_AES256GCM:
ret = Sodium.crypto_aead_aes256gcm_encrypt(ciphertext, ref encClen,
plaintext, (ulong)plen,
null, 0,
null, _encNonce,
_sodiumEncSubkey);
break;
default:
throw new System.Exception("not implemented");
}
if (ret != 0) throw new CryptoErrorException(String.Format("ret is {0}", ret));
logger.Dump("after cipherEncrypt: cipher", ciphertext, (int) encClen);
clen = (uint) encClen;
}
public override void cipherDecrypt(byte[] ciphertext, uint clen, byte[] plaintext, ref uint plen)
{
Debug.Assert(_sodiumDecSubkey != null);
// buf: ciphertext + tag
// outbuf: plaintext
int ret;
ulong decPlen = 0;
logger.Dump("_decNonce before dec", _decNonce, nonceLen);
logger.Dump("_sodiumDecSubkey", _sodiumDecSubkey, keyLen);
logger.Dump("before cipherDecrypt: cipher", ciphertext, (int) clen);
switch (_cipher)
{
case CIPHER_CHACHA20IETFPOLY1305:
ret = Sodium.crypto_aead_chacha20poly1305_ietf_decrypt(plaintext, ref decPlen,
null,
ciphertext, (ulong) clen,
null, 0,
_decNonce, _sodiumDecSubkey);
break;
case CIPHER_XCHACHA20IETFPOLY1305:
ret = Sodium.crypto_aead_xchacha20poly1305_ietf_decrypt(plaintext, ref decPlen,
null,
ciphertext, (ulong)clen,
null, 0,
_decNonce, _sodiumDecSubkey);
break;
case CIPHER_AES256GCM:
ret = Sodium.crypto_aead_aes256gcm_decrypt(plaintext, ref decPlen,
null,
ciphertext, (ulong)clen,
null, 0,
_decNonce, _sodiumDecSubkey);
break;
default:
throw new System.Exception("not implemented");
}
if (ret != 0) throw new CryptoErrorException(String.Format("ret is {0}", ret));
logger.Dump("after cipherDecrypt: plain", plaintext, (int) decPlen);
plen = (uint) decPlen;
}
public override void Dispose()
{
}
}
}

+ 4
- 46
shadowsocks-csharp/Encryption/EncryptorFactory.cs View File

@@ -11,70 +11,28 @@ namespace Shadowsocks.Encryption
{
private static Dictionary<string, Type> _registeredEncryptors = new Dictionary<string, Type>();
private static readonly Type[] ConstructorTypes = {typeof(string), typeof(string)};
private static readonly Type[] ConstructorTypes = { typeof(string), typeof(string) };
static EncryptorFactory()
{
var AEADMbedTLSEncryptorSupportedCiphers = AEADMbedTLSEncryptor.SupportedCiphers();
var AEADSodiumEncryptorSupportedCiphers = AEADSodiumEncryptor.SupportedCiphers();
if (Sodium.AES256GCMAvailable)
{
// prefer to aes-256-gcm in libsodium
AEADMbedTLSEncryptorSupportedCiphers.Remove("aes-256-gcm");
}
else
{
AEADSodiumEncryptorSupportedCiphers.Remove("aes-256-gcm");
}
// XXX: sequence matters, OpenSSL > Sodium > MbedTLS
foreach (string method in StreamNativeEncryptor.SupportedCiphers())
{
if (!_registeredEncryptors.ContainsKey(method))
_registeredEncryptors.Add(method, typeof(StreamNativeEncryptor));
}
foreach (string method in StreamOpenSSLEncryptor.SupportedCiphers())
{
if (!_registeredEncryptors.ContainsKey(method))
_registeredEncryptors.Add(method, typeof(StreamOpenSSLEncryptor));
}
foreach (string method in StreamSodiumEncryptor.SupportedCiphers())
{
if (!_registeredEncryptors.ContainsKey(method))
_registeredEncryptors.Add(method, typeof(StreamSodiumEncryptor));
}
foreach (string method in StreamMbedTLSEncryptor.SupportedCiphers())
{
if (!_registeredEncryptors.ContainsKey(method))
_registeredEncryptors.Add(method, typeof(StreamMbedTLSEncryptor));
}
foreach (string method in AEADNativeEncryptor.SupportedCiphers())
{
if (!_registeredEncryptors.ContainsKey(method))
_registeredEncryptors.Add(method, typeof(AEADNativeEncryptor));
}
foreach (string method in AEADOpenSSLEncryptor.SupportedCiphers())
{
if (!_registeredEncryptors.ContainsKey(method))
_registeredEncryptors.Add(method, typeof(AEADOpenSSLEncryptor));
}
foreach (string method in AEADSodiumEncryptorSupportedCiphers)
foreach (string method in AEADBouncyCastleEncryptor.SupportedCiphers())
{
if (!_registeredEncryptors.ContainsKey(method))
_registeredEncryptors.Add(method, typeof(AEADSodiumEncryptor));
_registeredEncryptors.Add(method, typeof(AEADBouncyCastleEncryptor));
}
foreach (string method in AEADMbedTLSEncryptorSupportedCiphers)
{
if (!_registeredEncryptors.ContainsKey(method))
_registeredEncryptors.Add(method, typeof(AEADMbedTLSEncryptor));
}
}
public static IEncryptor GetEncryptor(string method, string password)
@@ -89,7 +47,7 @@ namespace Shadowsocks.Encryption
ConstructorInfo c = t.GetConstructor(ConstructorTypes);
if (c == null) throw new System.Exception("Invalid ctor");
IEncryptor result = (IEncryptor) c.Invoke(new object[] {method, password});
IEncryptor result = (IEncryptor)c.Invoke(new object[] { method, password });
return result;
}


+ 0
- 109
shadowsocks-csharp/Encryption/MbedTLS.cs View File

@@ -1,109 +0,0 @@
using System;
using System.IO;
using System.Runtime.InteropServices;
using NLog;
using Shadowsocks.Controller;
using Shadowsocks.Properties;
using Shadowsocks.Util;
namespace Shadowsocks.Encryption
{
public static class MbedTLS
{
private static Logger logger = LogManager.GetCurrentClassLogger();
private const string DLLNAME = "libsscrypto.dll";
public const int MBEDTLS_ENCRYPT = 1;
public const int MBEDTLS_DECRYPT = 0;
static MbedTLS()
{
string dllPath = Utils.GetTempPath(DLLNAME);
try
{
FileManager.UncompressFile(dllPath, Resources.libsscrypto_dll);
}
catch (IOException)
{
}
catch (System.Exception e)
{
logger.LogUsefulException(e);
}
LoadLibrary(dllPath);
}
public static byte[] MD5(byte[] input)
{
byte[] output = new byte[16];
if (md5_ret(input, (uint) input.Length, output) != 0)
throw new System.Exception("mbedtls: MD5 failure");
return output;
}
[DllImport("Kernel32.dll")]
private static extern IntPtr LoadLibrary(string path);
[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
public static extern int md5_ret(byte[] input, uint ilen, byte[] output);
/// <summary>
/// Get cipher ctx size for unmanaged memory allocation
/// </summary>
/// <returns></returns>
[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
public static extern int cipher_get_size_ex();
#region Cipher layer wrappers
[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr cipher_info_from_string(string cipher_name);
[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
public static extern void cipher_init(IntPtr ctx);
[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
public static extern int cipher_setup(IntPtr ctx, IntPtr cipher_info);
// XXX: Check operation before using it
[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
public static extern int cipher_setkey(IntPtr ctx, byte[] key, int key_bitlen, int operation);
[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
public static extern int cipher_set_iv(IntPtr ctx, byte[] iv, int iv_len);
[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
public static extern int cipher_reset(IntPtr ctx);
[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
public static extern int cipher_update(IntPtr ctx, byte[] input, int ilen, byte[] output, ref int olen);
[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
public static extern void cipher_free(IntPtr ctx);
[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
public static extern int cipher_auth_encrypt(IntPtr ctx,
byte[] iv, uint iv_len,
IntPtr ad, uint ad_len,
byte[] input, uint ilen,
byte[] output, ref uint olen,
byte[] tag, uint tag_len);
[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
public static extern int cipher_auth_decrypt(IntPtr ctx,
byte[] iv, uint iv_len,
IntPtr ad, uint ad_len,
byte[] input, uint ilen,
byte[] output, ref uint olen,
byte[] tag, uint tag_len);
[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
public static extern int hkdf(byte[] salt,
int salt_len, byte[] ikm, int ikm_len,
byte[] info, int info_len, byte[] okm,
int okm_len);
#endregion
}
}

+ 0
- 164
shadowsocks-csharp/Encryption/OpenSSL.cs View File

@@ -1,164 +0,0 @@
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Security;
using System.Text;
using NLog;
using Shadowsocks.Controller;
using Shadowsocks.Encryption.Exception;
using Shadowsocks.Properties;
using Shadowsocks.Util;
namespace Shadowsocks.Encryption
{
// XXX: only for OpenSSL 1.1.0 and higher
public static class OpenSSL
{
private static Logger logger = LogManager.GetCurrentClassLogger();
private const string DLLNAME = "libsscrypto.dll";
public const int OPENSSL_ENCRYPT = 1;
public const int OPENSSL_DECRYPT = 0;
public const int EVP_CTRL_AEAD_SET_IVLEN = 0x9;
public const int EVP_CTRL_AEAD_GET_TAG = 0x10;
public const int EVP_CTRL_AEAD_SET_TAG = 0x11;
static OpenSSL()
{
string dllPath = Utils.GetTempPath(DLLNAME);
try
{
FileManager.UncompressFile(dllPath, Resources.libsscrypto_dll);
}
catch (IOException)
{
}
catch (System.Exception e)
{
logger.LogUsefulException(e);
}
LoadLibrary(dllPath);
}
public static IntPtr GetCipherInfo(string cipherName)
{
var name = Encoding.ASCII.GetBytes(cipherName);
Array.Resize(ref name, name.Length + 1);
return EVP_get_cipherbyname(name);
}
/// <summary>
/// Need init cipher context after EVP_CipherFinal_ex to reuse context
/// </summary>
/// <param name="ctx"></param>
/// <param name="cipherType"></param>
/// <param name="nonce"></param>
public static void SetCtxNonce(IntPtr ctx, byte[] nonce, bool isEncrypt)
{
var ret = EVP_CipherInit_ex(ctx, IntPtr.Zero,
IntPtr.Zero, null,
nonce,
isEncrypt ? OPENSSL_ENCRYPT : OPENSSL_DECRYPT);
if (ret != 1) throw new System.Exception("openssl: fail to set AEAD nonce");
}
public static void AEADGetTag(IntPtr ctx, byte[] tagbuf, int taglen)
{
IntPtr tagBufIntPtr = IntPtr.Zero;
try
{
tagBufIntPtr = Marshal.AllocHGlobal(taglen);
var ret = EVP_CIPHER_CTX_ctrl(ctx,
EVP_CTRL_AEAD_GET_TAG, taglen, tagBufIntPtr);
if (ret != 1) throw new CryptoErrorException("openssl: fail to get AEAD tag");
// take tag from unmanaged memory
Marshal.Copy(tagBufIntPtr, tagbuf, 0, taglen);
}
finally
{
if (tagBufIntPtr != IntPtr.Zero)
{
Marshal.FreeHGlobal(tagBufIntPtr);
}
}
}
public static void AEADSetTag(IntPtr ctx, byte[] tagbuf, int taglen)
{
IntPtr tagBufIntPtr = IntPtr.Zero;
try
{
// allocate unmanaged memory for tag
tagBufIntPtr = Marshal.AllocHGlobal(taglen);
// copy tag to unmanaged memory
Marshal.Copy(tagbuf, 0, tagBufIntPtr, taglen);
var ret = EVP_CIPHER_CTX_ctrl(ctx,
EVP_CTRL_AEAD_SET_TAG, taglen, tagBufIntPtr);
if (ret != 1) throw new CryptoErrorException("openssl: fail to set AEAD tag");
}
finally
{
if (tagBufIntPtr != IntPtr.Zero)
{
Marshal.FreeHGlobal(tagBufIntPtr);
}
}
}
[DllImport("Kernel32.dll")]
private static extern IntPtr LoadLibrary(string path);
[SuppressUnmanagedCodeSecurity]
[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr EVP_CIPHER_CTX_new();
[SuppressUnmanagedCodeSecurity]
[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
public static extern void EVP_CIPHER_CTX_free(IntPtr ctx);
[SuppressUnmanagedCodeSecurity]
[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
public static extern int EVP_CIPHER_CTX_reset(IntPtr ctx);
[SuppressUnmanagedCodeSecurity]
[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
public static extern int EVP_CipherInit_ex(IntPtr ctx, IntPtr type,
IntPtr impl, byte[] key, byte[] iv, int enc);
[SuppressUnmanagedCodeSecurity]
[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
public static extern int EVP_CipherUpdate(IntPtr ctx, byte[] outb,
out int outl, byte[] inb, int inl);
[SuppressUnmanagedCodeSecurity]
[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
public static extern int EVP_CipherFinal_ex(IntPtr ctx, byte[] outm, ref int outl);
[SuppressUnmanagedCodeSecurity]
[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
public static extern int EVP_CIPHER_CTX_set_padding(IntPtr x, int padding);
[SuppressUnmanagedCodeSecurity]
[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
public static extern int EVP_CIPHER_CTX_set_key_length(IntPtr x, int keylen);
[SuppressUnmanagedCodeSecurity]
[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
public static extern int EVP_CIPHER_CTX_ctrl(IntPtr ctx, int type, int arg, IntPtr ptr);
/// <summary>
/// simulate NUL-terminated string
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
[SuppressUnmanagedCodeSecurity]
[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr EVP_get_cipherbyname(byte[] name);
}
}

+ 0
- 113
shadowsocks-csharp/Encryption/Sodium.cs View File

@@ -1,113 +0,0 @@
using System;
using System.IO;
using System.Runtime.InteropServices;
using NLog;
using Shadowsocks.Controller;
using Shadowsocks.Properties;
using Shadowsocks.Util;
namespace Shadowsocks.Encryption
{
public static class Sodium
{
private static Logger logger = LogManager.GetCurrentClassLogger();
private const string DLLNAME = "libsscrypto.dll";
private static bool _initialized = false;
private static readonly object _initLock = new object();
public static bool AES256GCMAvailable { get; private set; } = false;
static Sodium()
{
string dllPath = Utils.GetTempPath(DLLNAME);
try
{
FileManager.UncompressFile(dllPath, Resources.libsscrypto_dll);
}
catch (IOException)
{
}
catch (System.Exception e)
{
logger.LogUsefulException(e);
}
LoadLibrary(dllPath);
lock (_initLock)
{
if (!_initialized)
{
if (sodium_init() == -1)
{
throw new System.Exception("Failed to initialize sodium");
}
else /* 1 means already initialized; 0 means success */
{
_initialized = true;
}
AES256GCMAvailable = crypto_aead_aes256gcm_is_available() == 1;
logger.Debug($"sodium: AES256GCMAvailable is {AES256GCMAvailable}");
}
}
}
[DllImport("Kernel32.dll")]
private static extern IntPtr LoadLibrary(string path);
[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
private static extern int sodium_init();
[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
private static extern int crypto_aead_aes256gcm_is_available();
#region AEAD
[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
public static extern int sodium_increment(byte[] n, int nlen);
[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
public static extern int crypto_aead_chacha20poly1305_ietf_encrypt(byte[] c, ref ulong clen_p, byte[] m,
ulong mlen, byte[] ad, ulong adlen, byte[] nsec, byte[] npub, byte[] k);
[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
public static extern int crypto_aead_chacha20poly1305_ietf_decrypt(byte[] m, ref ulong mlen_p,
byte[] nsec, byte[] c, ulong clen, byte[] ad, ulong adlen, byte[] npub, byte[] k);
[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
public static extern int crypto_aead_xchacha20poly1305_ietf_encrypt(byte[] c, ref ulong clen_p, byte[] m, ulong mlen,
byte[] ad, ulong adlen, byte[] nsec, byte[] npub, byte[] k);
[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
public static extern int crypto_aead_xchacha20poly1305_ietf_decrypt(byte[] m, ref ulong mlen_p, byte[] nsec, byte[] c,
ulong clen, byte[] ad, ulong adlen, byte[] npub, byte[] k);
[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
public static extern int crypto_aead_aes256gcm_encrypt(byte[] c, ref ulong clen_p, byte[] m, ulong mlen,
byte[] ad, ulong adlen, byte[] nsec, byte[] npub, byte[] k);
[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
public static extern int crypto_aead_aes256gcm_decrypt(byte[] m, ref ulong mlen_p, byte[] nsec, byte[] c,
ulong clen, byte[] ad, ulong adlen, byte[] npub, byte[] k);
#endregion
#region Stream
[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
public static extern int crypto_stream_salsa20_xor_ic(byte[] c, byte[] m, ulong mlen, byte[] n, ulong ic,
byte[] k);
[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
public static extern int crypto_stream_chacha20_xor_ic(byte[] c, byte[] m, ulong mlen, byte[] n, ulong ic,
byte[] k);
[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)]
public static extern int crypto_stream_chacha20_ietf_xor_ic(byte[] c, byte[] m, ulong mlen, byte[] n, uint ic,
byte[] k);
#endregion
}
}

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

@@ -75,11 +75,11 @@ namespace Shadowsocks.Encryption.Stream
byte[] md5sum = null;
while (i < keylen) {
if (i == 0) {
md5sum = MbedTLS.MD5(password);
md5sum = CryptoUtils.MD5(password);
} else {
Array.Copy(md5sum, 0, result, 0, MD5_LEN);
Array.Copy(password, 0, result, MD5_LEN, password.Length);
md5sum = MbedTLS.MD5(result);
md5sum = CryptoUtils.MD5(result);
}
Array.Copy(md5sum, 0, key, i, Math.Min(MD5_LEN, keylen - i));
i += MD5_LEN;


+ 0
- 155
shadowsocks-csharp/Encryption/Stream/StreamMbedTLSEncryptor.cs View File

@@ -1,155 +0,0 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using Shadowsocks.Encryption.Exception;
namespace Shadowsocks.Encryption.Stream
{
public class StreamMbedTLSEncryptor
: StreamEncryptor, IDisposable
{
const int CIPHER_RC4 = 1;
const int CIPHER_AES = 2;
const int CIPHER_BLOWFISH = 3;
const int CIPHER_CAMELLIA = 4;
private IntPtr _encryptCtx = IntPtr.Zero;
private IntPtr _decryptCtx = IntPtr.Zero;
public StreamMbedTLSEncryptor(string method, string password)
: base(method, password)
{
}
private static Dictionary<string, EncryptorInfo> _ciphers = new Dictionary<string, EncryptorInfo> {
{ "aes-128-cfb", new EncryptorInfo("AES-128-CFB128", 16, 16, CIPHER_AES) },
{ "aes-192-cfb", new EncryptorInfo("AES-192-CFB128", 24, 16, CIPHER_AES) },
{ "aes-256-cfb", new EncryptorInfo("AES-256-CFB128", 32, 16, CIPHER_AES) },
{ "aes-128-ctr", new EncryptorInfo("AES-128-CTR", 16, 16, CIPHER_AES) },
{ "aes-192-ctr", new EncryptorInfo("AES-192-CTR", 24, 16, CIPHER_AES) },
{ "aes-256-ctr", new EncryptorInfo("AES-256-CTR", 32, 16, CIPHER_AES) },
{ "bf-cfb", new EncryptorInfo("BLOWFISH-CFB64", 16, 8, CIPHER_BLOWFISH) },
{ "camellia-128-cfb", new EncryptorInfo("CAMELLIA-128-CFB128", 16, 16, CIPHER_CAMELLIA) },
{ "camellia-192-cfb", new EncryptorInfo("CAMELLIA-192-CFB128", 24, 16, CIPHER_CAMELLIA) },
{ "camellia-256-cfb", new EncryptorInfo("CAMELLIA-256-CFB128", 32, 16, CIPHER_CAMELLIA) },
{ "rc4-md5", new EncryptorInfo("ARC4-128", 16, 16, CIPHER_RC4) }
};
public static List<string> SupportedCiphers()
{
return new List<string>(_ciphers.Keys);
}
protected override Dictionary<string, EncryptorInfo> getCiphers()
{
return _ciphers;
}
protected override void initCipher(byte[] iv, bool isEncrypt)
{
base.initCipher(iv, isEncrypt);
IntPtr ctx = Marshal.AllocHGlobal(MbedTLS.cipher_get_size_ex());
if (isEncrypt)
{
_encryptCtx = ctx;
}
else
{
_decryptCtx = ctx;
}
byte[] realkey;
if (_method == "rc4-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;
}
MbedTLS.cipher_init(ctx);
if (MbedTLS.cipher_setup( ctx, MbedTLS.cipher_info_from_string( _innerLibName ) ) != 0 )
throw new System.Exception("Cannot initialize mbed TLS cipher context");
/*
* MbedTLS takes key length by bit
* cipher_setkey() will set the correct key schedule
* and operation
*
* MBEDTLS_AES_{EN,DE}CRYPT
* == MBEDTLS_BLOWFISH_{EN,DE}CRYPT
* == MBEDTLS_CAMELLIA_{EN,DE}CRYPT
* == MBEDTLS_{EN,DE}CRYPT
*
*/
if (MbedTLS.cipher_setkey(ctx, realkey, keyLen * 8,
isEncrypt ? MbedTLS.MBEDTLS_ENCRYPT : MbedTLS.MBEDTLS_DECRYPT) != 0 )
throw new System.Exception("Cannot set mbed TLS cipher key");
if (MbedTLS.cipher_set_iv(ctx, iv, ivLen) != 0)
throw new System.Exception("Cannot set mbed TLS cipher IV");
if (MbedTLS.cipher_reset(ctx) != 0)
throw new System.Exception("Cannot finalize mbed TLS cipher context");
}
protected override void cipherUpdate(bool isEncrypt, int length, byte[] buf, byte[] outbuf)
{
// C# could be multi-threaded
if (_disposed)
{
throw new ObjectDisposedException(this.ToString());
}
if (MbedTLS.cipher_update(isEncrypt ? _encryptCtx : _decryptCtx,
buf, length, outbuf, ref length) != 0 )
throw new CryptoErrorException();
}
#region IDisposable
private bool _disposed;
// instance based lock
private readonly object _lock = new object();
public override void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
~StreamMbedTLSEncryptor()
{
Dispose(false);
}
protected virtual void Dispose(bool disposing)
{
lock (_lock)
{
if (_disposed) return;
_disposed = true;
}
if (disposing)
{
// free managed objects
}
// free unmanaged objects
if (_encryptCtx != IntPtr.Zero)
{
MbedTLS.cipher_free(_encryptCtx);
Marshal.FreeHGlobal(_encryptCtx);
_encryptCtx = IntPtr.Zero;
}
if (_decryptCtx != IntPtr.Zero)
{
MbedTLS.cipher_free(_decryptCtx);
Marshal.FreeHGlobal(_decryptCtx);
_decryptCtx = IntPtr.Zero;
}
}
#endregion
}
}

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

@@ -37,7 +37,7 @@ namespace Shadowsocks.Encryption.Stream
byte[] temp = new byte[keyLen + ivLen];
Array.Copy(_key, 0, temp, 0, keyLen);
Array.Copy(iv, 0, temp, keyLen, ivLen);
realkey = MbedTLS.MD5(temp);
realkey = CryptoUtils.MD5(temp);
}
else
{
@@ -47,7 +47,7 @@ namespace Shadowsocks.Encryption.Stream
}
else if (_cipher == Table)
{
ulong a = BitConverter.ToUInt64(MbedTLS.MD5(Encoding.UTF8.GetBytes(_password)), 0);
ulong a = BitConverter.ToUInt64(CryptoUtils.MD5(Encoding.UTF8.GetBytes(_password)), 0);
for (int i = 0; i < 256; i++)
{
_encryptTable[i] = (byte)i;


+ 0
- 159
shadowsocks-csharp/Encryption/Stream/StreamOpenSSLEncryptor.cs View File

@@ -1,159 +0,0 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using Shadowsocks.Encryption.Exception;
namespace Shadowsocks.Encryption.Stream
{
public class StreamOpenSSLEncryptor
: StreamEncryptor, IDisposable
{
const int CIPHER_RC4 = 1;
const int CIPHER_AES = 2;
const int CIPHER_CAMELLIA = 3;
const int CIPHER_BLOWFISH = 4;
const int CIPHER_CHACHA20_IETF = 5;
private IntPtr _encryptCtx = IntPtr.Zero;
private IntPtr _decryptCtx = IntPtr.Zero;
public StreamOpenSSLEncryptor(string method, string password)
: base(method, password)
{
}
// XXX: name=RC4,blkSz=1,keyLen=16,ivLen=0, do NOT pass IV to it
private static readonly Dictionary<string, EncryptorInfo> _ciphers = new Dictionary<string, EncryptorInfo>
{
{ "aes-128-cfb", new EncryptorInfo("AES-128-CFB", 16, 16, CIPHER_AES) },
{ "aes-192-cfb", new EncryptorInfo("AES-192-CFB", 24, 16, CIPHER_AES) },
{ "aes-256-cfb", new EncryptorInfo("AES-256-CFB", 32, 16, CIPHER_AES) },
{ "aes-128-ctr", new EncryptorInfo("aes-128-ctr", 16, 16, CIPHER_AES) },
{ "aes-192-ctr", new EncryptorInfo("aes-192-ctr", 24, 16, CIPHER_AES) },
{ "aes-256-ctr", new EncryptorInfo("aes-256-ctr", 32, 16, CIPHER_AES) },
{ "bf-cfb", new EncryptorInfo("bf-cfb", 16, 8, CIPHER_BLOWFISH) },
{ "camellia-128-cfb", new EncryptorInfo("CAMELLIA-128-CFB", 16, 16, CIPHER_CAMELLIA) },
{ "camellia-192-cfb", new EncryptorInfo("CAMELLIA-192-CFB", 24, 16, CIPHER_CAMELLIA) },
{ "camellia-256-cfb", new EncryptorInfo("CAMELLIA-256-CFB", 32, 16, CIPHER_CAMELLIA) },
{ "rc4-md5", new EncryptorInfo("RC4", 16, 16, CIPHER_RC4) },
// it's using ivLen=16, not compatible
//{ "chacha20-ietf", new EncryptorInfo("chacha20", 32, 12, CIPHER_CHACHA20_IETF) }
};
public static List<string> SupportedCiphers()
{
return new List<string>(_ciphers.Keys);
}
protected override Dictionary<string, EncryptorInfo> getCiphers()
{
return _ciphers;
}
protected override void initCipher(byte[] iv, bool isEncrypt)
{
base.initCipher(iv, isEncrypt);
IntPtr cipherInfo = OpenSSL.GetCipherInfo(_innerLibName);
if (cipherInfo == IntPtr.Zero) throw new System.Exception("openssl: cipher not found");
IntPtr ctx = OpenSSL.EVP_CIPHER_CTX_new();
if (ctx == IntPtr.Zero) throw new System.Exception("fail to create ctx");
if (isEncrypt)
{
_encryptCtx = ctx;
}
else
{
_decryptCtx = ctx;
}
byte[] realkey;
if (_method == "rc4-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;
}
var ret = OpenSSL.EVP_CipherInit_ex(ctx, cipherInfo, IntPtr.Zero, null,null,
isEncrypt ? OpenSSL.OPENSSL_ENCRYPT : OpenSSL.OPENSSL_DECRYPT);
if (ret != 1) throw new System.Exception("openssl: fail to set key length");
ret = OpenSSL.EVP_CIPHER_CTX_set_key_length(ctx, keyLen);
if (ret != 1) throw new System.Exception("openssl: fail to set key length");
ret = OpenSSL.EVP_CipherInit_ex(ctx, IntPtr.Zero, IntPtr.Zero, realkey,
_method == "rc4-md5" ? null : iv,
isEncrypt ? OpenSSL.OPENSSL_ENCRYPT : OpenSSL.OPENSSL_DECRYPT);
if (ret != 1) throw new System.Exception("openssl: cannot set key and iv");
OpenSSL.EVP_CIPHER_CTX_set_padding(ctx, 0);
}
protected override void cipherUpdate(bool isEncrypt, int length, byte[] buf, byte[] outbuf)
{
// C# could be multi-threaded
if (_disposed)
{
throw new ObjectDisposedException(this.ToString());
}
int outlen = 0;
var ret = OpenSSL.EVP_CipherUpdate(isEncrypt ? _encryptCtx : _decryptCtx,
outbuf, out outlen, buf, length);
if (ret != 1)
throw new CryptoErrorException(String.Format("ret is {0}", ret));
Debug.Assert(outlen == length);
}
#region IDisposable
private bool _disposed;
// instance based lock
private readonly object _lock = new object();
public override void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
~StreamOpenSSLEncryptor()
{
Dispose(false);
}
protected virtual void Dispose(bool disposing)
{
lock (_lock)
{
if (_disposed) return;
_disposed = true;
}
if (disposing)
{
// free managed objects
}
// free unmanaged objects
if (_encryptCtx != IntPtr.Zero)
{
OpenSSL.EVP_CIPHER_CTX_free(_encryptCtx);
_encryptCtx = IntPtr.Zero;
}
if (_decryptCtx != IntPtr.Zero)
{
OpenSSL.EVP_CIPHER_CTX_free(_decryptCtx);
_decryptCtx = IntPtr.Zero;
}
}
#endregion
}
}

+ 0
- 107
shadowsocks-csharp/Encryption/Stream/StreamSodiumEncryptor.cs View File

@@ -1,107 +0,0 @@
using System;
using System.Collections.Generic;
using Shadowsocks.Encryption.Exception;
namespace Shadowsocks.Encryption.Stream
{
public class StreamSodiumEncryptor
: StreamEncryptor, IDisposable
{
const int CIPHER_SALSA20 = 1;
const int CIPHER_CHACHA20 = 2;
const int CIPHER_CHACHA20_IETF = 3;
const int SODIUM_BLOCK_SIZE = 64;
protected int _encryptBytesRemaining;
protected int _decryptBytesRemaining;
protected ulong _encryptIC;
protected ulong _decryptIC;
protected byte[] _encryptBuf;
protected byte[] _decryptBuf;
public StreamSodiumEncryptor(string method, string password)
: base(method, password)
{
_encryptBuf = new byte[MAX_INPUT_SIZE + SODIUM_BLOCK_SIZE];
_decryptBuf = new byte[MAX_INPUT_SIZE + SODIUM_BLOCK_SIZE];
}
private static readonly Dictionary<string, EncryptorInfo> _ciphers = new Dictionary<string, EncryptorInfo> {
{ "salsa20", new EncryptorInfo(32, 8, CIPHER_SALSA20) },
{ "chacha20", new EncryptorInfo(32, 8, CIPHER_CHACHA20) },
{ "chacha20-ietf", new EncryptorInfo(32, 12, CIPHER_CHACHA20_IETF) }
};
protected override Dictionary<string, EncryptorInfo> getCiphers()
{
return _ciphers;
}
public static List<string> SupportedCiphers()
{
return new List<string>(_ciphers.Keys);
}
protected override void cipherUpdate(bool isEncrypt, int length, byte[] buf, byte[] outbuf)
{
// TODO write a unidirection cipher so we don't have to if if if
int bytesRemaining;
ulong ic;
byte[] sodiumBuf;
byte[] iv;
int ret = -1;
if (isEncrypt)
{
bytesRemaining = _encryptBytesRemaining;
ic = _encryptIC;
sodiumBuf = _encryptBuf;
iv = _encryptIV;
}
else
{
bytesRemaining = _decryptBytesRemaining;
ic = _decryptIC;
sodiumBuf = _decryptBuf;
iv = _decryptIV;
}
int padding = bytesRemaining;
Buffer.BlockCopy(buf, 0, sodiumBuf, padding, length);
switch (_cipher)
{
case CIPHER_SALSA20:
ret = Sodium.crypto_stream_salsa20_xor_ic(sodiumBuf, sodiumBuf, (ulong)(padding + length), iv, ic, _key);
break;
case CIPHER_CHACHA20:
ret = Sodium.crypto_stream_chacha20_xor_ic(sodiumBuf, sodiumBuf, (ulong)(padding + length), iv, ic, _key);
break;
case CIPHER_CHACHA20_IETF:
ret = Sodium.crypto_stream_chacha20_ietf_xor_ic(sodiumBuf, sodiumBuf, (ulong)(padding + length), iv, (uint)ic, _key);
break;
}
if (ret != 0) throw new CryptoErrorException();
Buffer.BlockCopy(sodiumBuf, padding, outbuf, 0, length);
padding += length;
ic += (ulong)padding / SODIUM_BLOCK_SIZE;
bytesRemaining = padding % SODIUM_BLOCK_SIZE;
if (isEncrypt)
{
_encryptBytesRemaining = bytesRemaining;
_encryptIC = ic;
}
else
{
_decryptBytesRemaining = bytesRemaining;
_decryptIC = ic;
}
}
public override void Dispose()
{
}
}
}

+ 68
- 85
shadowsocks-csharp/Properties/Resources.Designer.cs View File

@@ -1,10 +1,10 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
// 此代码由工具生成。
// 运行时版本:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// 对此文件的更改可能会导致不正确的行为,并且如果
// 重新生成代码,这些更改将会丢失。
// </auto-generated>
//------------------------------------------------------------------------------
@@ -13,12 +13,12 @@ namespace Shadowsocks.Properties {
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// 一个强类型的资源类,用于查找本地化的字符串等。
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
// 此类是由 StronglyTypedResourceBuilder
// 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
// 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen
// (以 /str 作为命令选项),或重新生成 VS 项目。
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
@@ -33,7 +33,7 @@ namespace Shadowsocks.Properties {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// 返回此类使用的缓存的 ResourceManager 实例。
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
@@ -47,8 +47,8 @@ namespace Shadowsocks.Properties {
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// 重写当前线程的 CurrentUICulture 属性
/// 重写当前线程的 CurrentUICulture 属性。
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
@@ -61,7 +61,7 @@ namespace Shadowsocks.Properties {
}
/// <summary>
/// Looks up a localized string similar to /* eslint-disable */
/// 查找类似 /* eslint-disable */
///// Was generated by gfwlist2pac in precise mode
///// https://github.com/clowwindy/gfwlist2pac
///
@@ -76,7 +76,7 @@ namespace Shadowsocks.Properties {
///* This file is part of Adblock Plus &lt;http://adblockplus.org/&gt;,
///* Copyright (C) 2006-2014 Eyeo GmbH
///*
///* Adblock Plus is free software: you can redistribute it and/or [rest of string was truncated]&quot;;.
///* Adblock Plus is free software: you can redistribute it and/or [字符串的其余部分被截断]&quot;; 的本地化字符串。
/// </summary>
internal static string abp_js {
get {
@@ -85,29 +85,28 @@ namespace Shadowsocks.Properties {
}
/// <summary>
/// Looks up a localized string similar to var __USERRULES__ = [];
///var __RULES__ = [
/// &quot;|http://85.17.73.31/&quot;,
/// &quot;||agnesb.fr&quot;,
/// &quot;||akiba-web.com&quot;,
/// &quot;||altrec.com&quot;,
/// &quot;||angela-merkel.de&quot;,
/// &quot;||angola.org&quot;,
/// &quot;||apartmentratings.com&quot;,
/// &quot;||apartments.com&quot;,
/// &quot;||arena.taipei&quot;,
/// &quot;||asianspiss.com&quot;,
/// &quot;||assimp.org&quot;,
/// &quot;||athenaeizou.com&quot;,
/// &quot;||azubu.tv&quot;,
/// &quot;||bankmobilevibe.com&quot;,
/// &quot;||banorte.com&quot;,
/// &quot;||bash-hackers.org&quot;,
/// &quot;||beeg.com&quot;,
/// &quot;||global.bing.com&quot;,
/// &quot;||bloombergview.com&quot;,
/// &quot;||booktopia.com.au&quot;,
/// [rest of string was truncated]&quot;;.
/// 查找类似 var __USERRULES__ = [];
///var __RULES__ = [
/// &quot;|http://85.17.73.31/&quot;,
/// &quot;||agnesb.fr&quot;,
/// &quot;||akiba-web.com&quot;,
/// &quot;||altrec.com&quot;,
/// &quot;||angela-merkel.de&quot;,
/// &quot;||angola.org&quot;,
/// &quot;||apartmentratings.com&quot;,
/// &quot;||apartments.com&quot;,
/// &quot;||arena.taipei&quot;,
/// &quot;||asianspiss.com&quot;,
/// &quot;||assimp.org&quot;,
/// &quot;||athenaeizou.com&quot;,
/// &quot;||azubu.tv&quot;,
/// &quot;||bankmobilevibe.com&quot;,
/// &quot;||banorte.com&quot;,
/// &quot;||bash-hackers.org&quot;,
/// &quot;||beeg.com&quot;,
/// &quot;||global.bing.com&quot;,
/// &quot;||bloombergview.com&quot;,
/// &quot; [字符串的其余部分被截断]&quot;; 的本地化字符串。
/// </summary>
internal static string default_abp_rule {
get {
@@ -116,24 +115,21 @@ namespace Shadowsocks.Properties {
}
/// <summary>
/// Looks up a localized string similar to en,zh-CN,zh-TW,ja
///#Restart program to apply translation,,,
///#This is comment line,,,
///#Always keep language name at head of file,,,
///#Language name is output in log,,,
///&quot;#You can find it by search &quot;&quot;Current language is:&quot;&quot;&quot;,,,
///#Please use UTF-8 with BOM encoding so we can edit it in Excel,,,
///,,,
///Shadowsocks,Shadowsocks,Shadowsocks,Shadowsocks
///,,,
///#Menu,,,
///,,,
///System Proxy,系统代理,系統代理,システムプロキシ
///Disable,禁用,禁用,無効
///PAC,PAC 模式,PAC 模式,PAC
///Global,全局模式,全局模式,全般
///Servers,服务器,伺服器,サーバー
///Edit Servers...,编辑服务器...,編輯伺服器...,サーバーの編集.. [rest of string was truncated]&quot;;.
/// 查找类似 en,ru-RU,zh-CN,zh-TW,ja
///#Restart program to apply translation,,,,
///#This is comment line,,,,
///#Always keep language name at head of file,,,,
///#Language name is output in log,,,,
///&quot;#You can find it by search &quot;&quot;Current language is:&quot;&quot;&quot;,,,,
///#Please use UTF-8 with BOM encoding so we can edit it in Excel,,,,
///,,,,
///Shadowsocks,Shadowsocks,Shadowsocks,Shadowsocks,Shadowsocks
///,,,,
///#Menu,,,,
///,,,,
///System Proxy,Системный прокси-сервер,系统代理,系統代理,システムプロキシ
///Disable,Отключен,禁用,禁用,無効
///PAC,Сценарий настройки (PAC),PA [字符串的其余部分被截断]&quot;; 的本地化字符串。
/// </summary>
internal static string i18n_csv {
get {
@@ -142,26 +138,13 @@ namespace Shadowsocks.Properties {
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] libsscrypto_dll {
get {
object obj = ResourceManager.GetObject("libsscrypto_dll", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized string similar to &lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?&gt;
/// 查找类似 &lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?&gt;
///&lt;!-- Warning: Configuration may reset after shadowsocks upgrade. --&gt;
///&lt;!-- If you messed it up, delete this file and Shadowsocks will create a new one. --&gt;
///&lt;nlog xmlns=&quot;http://www.nlog-project.org/schemas/NLog.xsd&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;&gt;
/// &lt;targets&gt;
/// &lt;target name=&quot;file&quot; xsi:type=&quot;File&quot; fileName=&quot;shadowsocks.log&quot;/&gt;
///
/// &lt;/targets&gt;
/// &lt;rules&gt;
/// &lt;logger name=&quot;Name.Space.Class1&quot; minlevel=&quot;Debug&quot; writeTo=&quot;f1&quot; /&gt;
/// &lt;/rules&gt;
///&lt;/nlog&gt;.
/// &lt;!-- This line is managed by Shadowsocks. Do not modify it unless you know what you are doing.--&gt;
/// &lt;target name=&quot;file&quot; xsi:type=&quot;File&quot; fileName=&quot;ss_win_temp\shadowsocks.log&quot; writ [字符串的其余部分被截断]&quot;; 的本地化字符串。
/// </summary>
internal static string NLog_config {
get {
@@ -170,7 +153,7 @@ namespace Shadowsocks.Properties {
}
/// <summary>
/// Looks up a localized string similar to listen-address __PRIVOXY_BIND_IP__:__PRIVOXY_BIND_PORT__
/// 查找类似 listen-address __PRIVOXY_BIND_IP__:__PRIVOXY_BIND_PORT__
///toggle 0
///logfile ss_privoxy.log
///show-on-task-bar 0
@@ -178,7 +161,7 @@ namespace Shadowsocks.Properties {
///forward-socks5 / __SOCKS_HOST__:__SOCKS_PORT__ .
///max-client-connections 2048
///hide-console
///.
/// 的本地化字符串。
/// </summary>
internal static string privoxy_conf {
get {
@@ -187,7 +170,7 @@ namespace Shadowsocks.Properties {
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// 查找 System.Byte[] 类型的本地化资源。
/// </summary>
internal static byte[] privoxy_exe {
get {
@@ -197,7 +180,7 @@ namespace Shadowsocks.Properties {
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// 查找 System.Drawing.Bitmap 类型的本地化资源。
/// </summary>
internal static System.Drawing.Bitmap ss32Fill {
get {
@@ -207,7 +190,7 @@ namespace Shadowsocks.Properties {
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// 查找 System.Drawing.Bitmap 类型的本地化资源。
/// </summary>
internal static System.Drawing.Bitmap ss32In {
get {
@@ -217,7 +200,7 @@ namespace Shadowsocks.Properties {
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// 查找 System.Drawing.Bitmap 类型的本地化资源。
/// </summary>
internal static System.Drawing.Bitmap ss32Out {
get {
@@ -227,7 +210,7 @@ namespace Shadowsocks.Properties {
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// 查找 System.Drawing.Bitmap 类型的本地化资源。
/// </summary>
internal static System.Drawing.Bitmap ss32Outline {
get {
@@ -237,7 +220,7 @@ namespace Shadowsocks.Properties {
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// 查找 System.Drawing.Bitmap 类型的本地化资源。
/// </summary>
internal static System.Drawing.Bitmap ssw128 {
get {
@@ -247,7 +230,7 @@ namespace Shadowsocks.Properties {
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// 查找 System.Byte[] 类型的本地化资源。
/// </summary>
internal static byte[] sysproxy_exe {
get {
@@ -257,7 +240,7 @@ namespace Shadowsocks.Properties {
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// 查找 System.Byte[] 类型的本地化资源。
/// </summary>
internal static byte[] sysproxy64_exe {
get {
@@ -267,9 +250,9 @@ namespace Shadowsocks.Properties {
}
/// <summary>
/// Looks up a localized string similar to ! Put user rules line by line in this file.
/// 查找类似 ! Put user rules line by line in this file.
///! See https://adblockplus.org/en/filter-cheatsheet
///.
/// 的本地化字符串。
/// </summary>
internal static string user_rule {
get {


+ 0
- 3
shadowsocks-csharp/Properties/Resources.resx View File

@@ -127,9 +127,6 @@
<data name="i18n_csv" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Data\i18n.csv;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
</data>
<data name="libsscrypto_dll" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Data\libsscrypto.dll.gz;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="NLog_config" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\data\nlog.config;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
</data>


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

@@ -119,24 +119,16 @@
<Compile Include="Controller\System\Hotkeys\HotkeyCallbacks.cs" />
<Compile Include="Encryption\AEAD\AEADBouncyCastleEncryptor.cs" />
<Compile Include="Encryption\AEAD\AEADEncryptor.cs" />
<Compile Include="Encryption\AEAD\AEADMbedTLSEncryptor.cs" />
<Compile Include="Encryption\AEAD\AEADNativeEncryptor.cs" />
<Compile Include="Encryption\AEAD\AEADOpenSSLEncryptor.cs" />
<Compile Include="Encryption\AEAD\AEADSodiumEncryptor.cs" />
<Compile Include="Encryption\CircularBuffer\ByteCircularBuffer.cs" />
<Compile Include="Encryption\CryptoUtils.cs" />
<Compile Include="Encryption\EncryptorBase.cs" />
<Compile Include="Encryption\EncryptorFactory.cs" />
<Compile Include="Encryption\Exception\CryptoException.cs" />
<Compile Include="Encryption\IEncryptor.cs" />
<Compile Include="Encryption\MbedTLS.cs" />
<Compile Include="Encryption\OpenSSL.cs" />
<Compile Include="Encryption\RNG.cs" />
<Compile Include="Encryption\Sodium.cs" />
<Compile Include="Encryption\Stream\StreamEncryptor.cs" />
<Compile Include="Encryption\Stream\StreamMbedTLSEncryptor.cs" />
<Compile Include="Encryption\Stream\StreamNativeEncryptor.cs" />
<Compile Include="Encryption\Stream\StreamOpenSSLEncryptor.cs" />
<Compile Include="Encryption\Stream\StreamSodiumEncryptor.cs" />
<Compile Include="Model\HotKeyConfig.cs" />
<Compile Include="Model\NLogConfig.cs" />
<Compile Include="Model\ProxyConfig.cs" />
@@ -272,7 +264,6 @@
<SubType>Designer</SubType>
</None>
<None Include="Data\i18n.csv" />
<None Include="Data\libsscrypto.dll.gz" />
<None Include="Data\NLog.config" />
<None Include="Data\privoxy.exe.gz" />
</ItemGroup>


+ 2
- 324
test/CryptographyTest.cs View File

@@ -22,71 +22,10 @@ namespace Shadowsocks.Test
random.NextBytes(bytes);
string md5str = Convert.ToBase64String(md5.ComputeHash(bytes));
string md5str2 = Convert.ToBase64String(CryptoUtils.MD5(bytes));
string md5str3 = Convert.ToBase64String(MbedTLS.MD5(bytes));
Assert.IsTrue(md5str == md5str2);
Assert.IsTrue(md5str == md5str3);
}
}
[TestMethod]
public void TestHKDF()
{
int keylen = 32;
int saltlen = 32;
byte[] master = new byte[keylen];
byte[] info = new byte[8];
byte[] salt = new byte[saltlen];
Random r = new Random();
r.NextBytes(master);
r.NextBytes(info);
r.NextBytes(salt);
string bchkdf = Convert.ToBase64String(CryptoUtils.HKDF(keylen, master, salt, info));
string mbhkdf = Convert.ToBase64String(MbedTLShkdf(keylen, master, salt, info));
Assert.IsTrue(bchkdf == mbhkdf);
}
private byte[] MbedTLShkdf(int keylen, byte[] master, byte[] salt, byte[] info)
{
byte[] sessionKey = new byte[keylen];
MbedTLS.hkdf(salt, salt.Length, master, keylen, info, info.Length, sessionKey, keylen);
return sessionKey;
}
[TestMethod]
public void TestSodiumIncrement()
{
byte[] full255 = new byte[32];
for (int i = 0; i < full255.Length; i++)
{
full255[i] = 255;
}
byte[] zero255 = new byte[32];
zero255[0] = 255;
byte[] rd = new byte[32];
new Random().NextBytes(rd);
RunSodiumIncrement(full255);
RunSodiumIncrement(zero255);
RunSodiumIncrement(rd);
}
private void RunSodiumIncrement(byte[] data)
{
byte[] data2 = new byte[data.Length];
data.CopyTo(data2, 0);
CryptoUtils.SodiumIncrement(data);
Sodium.sodium_increment(data2, data2.Length);
for (int i = 0; i < data.Length; i++)
{
Assert.AreEqual(data[i], data2[i]);
}
}
private void RunEncryptionRound(IEncryptor encryptor, IEncryptor decryptor)
{
RNG.Reload();
@@ -123,173 +62,6 @@ namespace Shadowsocks.Test
private static bool encryptionFailed = false;
private static object locker = new object();
[TestMethod]
public void TestMbedTLSEncryption()
{
encryptionFailed = false;
// run it once before the multi-threading test to initialize global tables
RunSingleMbedTLSEncryptionThread();
List<Thread> threads = new List<Thread>();
for (int i = 0; i < 10; i++)
{
Thread t = new Thread(new ThreadStart(RunSingleMbedTLSEncryptionThread));
threads.Add(t);
t.Start();
}
foreach (Thread t in threads)
{
t.Join();
}
RNG.Close();
Assert.IsFalse(encryptionFailed);
}
private void RunSingleMbedTLSEncryptionThread()
{
try
{
for (int i = 0; i < 100; i++)
{
IEncryptor encryptor;
IEncryptor decryptor;
encryptor = new StreamMbedTLSEncryptor("aes-256-cfb", "barfoo!");
decryptor = new StreamMbedTLSEncryptor("aes-256-cfb", "barfoo!");
RunEncryptionRound(encryptor, decryptor);
}
}
catch
{
encryptionFailed = true;
throw;
}
}
[TestMethod]
public void TestRC4Encryption()
{
encryptionFailed = false;
// run it once before the multi-threading test to initialize global tables
RunSingleRC4EncryptionThread();
List<Thread> threads = new List<Thread>();
for (int i = 0; i < 10; i++)
{
Thread t = new Thread(new ThreadStart(RunSingleRC4EncryptionThread));
threads.Add(t);
t.Start();
}
foreach (Thread t in threads)
{
t.Join();
}
RNG.Close();
Assert.IsFalse(encryptionFailed);
}
private void RunSingleRC4EncryptionThread()
{
try
{
for (int i = 0; i < 100; i++)
{
var random = new Random();
IEncryptor encryptor;
IEncryptor decryptor;
encryptor = new StreamMbedTLSEncryptor("rc4-md5", "barfoo!");
decryptor = new StreamMbedTLSEncryptor("rc4-md5", "barfoo!");
RunEncryptionRound(encryptor, decryptor);
}
}
catch
{
encryptionFailed = true;
throw;
}
}
[TestMethod]
public void TestSodiumEncryption()
{
encryptionFailed = false;
// run it once before the multi-threading test to initialize global tables
RunSingleSodiumEncryptionThread();
List<Thread> threads = new List<Thread>();
for (int i = 0; i < 10; i++)
{
Thread t = new Thread(new ThreadStart(RunSingleSodiumEncryptionThread));
threads.Add(t);
t.Start();
}
foreach (Thread t in threads)
{
t.Join();
}
RNG.Close();
Assert.IsFalse(encryptionFailed);
}
private void RunSingleSodiumEncryptionThread()
{
try
{
for (int i = 0; i < 100; i++)
{
var random = new Random();
IEncryptor encryptor;
IEncryptor decryptor;
encryptor = new StreamSodiumEncryptor("salsa20", "barfoo!");
decryptor = new StreamSodiumEncryptor("salsa20", "barfoo!");
RunEncryptionRound(encryptor, decryptor);
}
}
catch
{
encryptionFailed = true;
throw;
}
}
[TestMethod]
public void TestOpenSSLEncryption()
{
encryptionFailed = false;
// run it once before the multi-threading test to initialize global tables
RunSingleOpenSSLEncryptionThread();
List<Thread> threads = new List<Thread>();
for (int i = 0; i < 10; i++)
{
Thread t = new Thread(new ThreadStart(RunSingleOpenSSLEncryptionThread));
threads.Add(t);
t.Start();
}
foreach (Thread t in threads)
{
t.Join();
}
RNG.Close();
Assert.IsFalse(encryptionFailed);
}
private void RunSingleOpenSSLEncryptionThread()
{
try
{
for (int i = 0; i < 100; i++)
{
var random = new Random();
IEncryptor encryptor;
IEncryptor decryptor;
encryptor = new StreamOpenSSLEncryptor("aes-256-cfb", "barfoo!");
decryptor = new StreamOpenSSLEncryptor("aes-256-cfb", "barfoo!");
RunEncryptionRound(encryptor, decryptor);
}
}
catch
{
encryptionFailed = true;
throw;
}
}
[TestMethod]
public void TestBouncyCastleAEADEncryption()
{
@@ -337,17 +109,11 @@ namespace Shadowsocks.Test
{
for (int i = 0; i < 100; i++)
{
IEncryptor encryptorO, encryptorN, encryptorN2;
IEncryptor decryptorO, decryptorN, decryptorN2;
encryptorO = new StreamOpenSSLEncryptor("rc4-md5", "barfoo!");
decryptorO = new StreamOpenSSLEncryptor("rc4-md5", "barfoo!");
IEncryptor encryptorN;
IEncryptor decryptorN;
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
@@ -379,93 +145,5 @@ namespace Shadowsocks.Test
throw;
}
}
[TestMethod]
public void TestOpenSSLAEADEncryption()
{
encryptionFailed = false;
// run it once before the multi-threading test to initialize global tables
RunSingleOpenSSLAEADEncryptionThread();
List<Thread> threads = new List<Thread>();
for (int i = 0; i < 10; i++)
{
Thread t = new Thread(new ThreadStart(RunSingleOpenSSLAEADEncryptionThread));
threads.Add(t);
t.Start();
}
foreach (Thread t in threads)
{
t.Join();
}
RNG.Close();
Assert.IsFalse(encryptionFailed);
}
private void RunSingleOpenSSLAEADEncryptionThread()
{
try
{
for (int i = 0; i < 100; i++)
{
var random = new Random();
IEncryptor encryptor;
IEncryptor decryptor;
encryptor = new Encryption.AEAD.AEADOpenSSLEncryptor("aes-256-gcm", "barfoo!");
encryptor.AddrBufLength = 1 + 4 + 2;// ADDR_ATYP_LEN + 4 + ADDR_PORT_LEN;
decryptor = new Encryption.AEAD.AEADOpenSSLEncryptor("aes-256-gcm", "barfoo!");
decryptor.AddrBufLength = 1 + 4 + 2;// ADDR_ATYP_LEN + 4 + ADDR_PORT_LEN;
RunEncryptionRound(encryptor, decryptor);
}
}
catch
{
encryptionFailed = true;
throw;
}
}
[TestMethod]
public void TestMBedTLSAEADEncryption()
{
encryptionFailed = false;
// run it once before the multi-threading test to initialize global tables
RunSingleMBedTLSAEADEncryptionThread();
List<Thread> threads = new List<Thread>();
for (int i = 0; i < 10; i++)
{
Thread t = new Thread(new ThreadStart(RunSingleMBedTLSAEADEncryptionThread));
threads.Add(t);
t.Start();
}
foreach (Thread t in threads)
{
t.Join();
}
RNG.Close();
Assert.IsFalse(encryptionFailed);
}
private void RunSingleMBedTLSAEADEncryptionThread()
{
try
{
for (int i = 0; i < 100; i++)
{
var random = new Random();
IEncryptor encryptor;
IEncryptor decryptor;
encryptor = new Encryption.AEAD.AEADMbedTLSEncryptor("aes-256-gcm", "barfoo!");
encryptor.AddrBufLength = 1 + 4 + 2;// ADDR_ATYP_LEN + 4 + ADDR_PORT_LEN;
decryptor = new Encryption.AEAD.AEADMbedTLSEncryptor("aes-256-gcm", "barfoo!");
decryptor.AddrBufLength = 1 + 4 + 2;// ADDR_ATYP_LEN + 4 + ADDR_PORT_LEN;
RunEncryptionRound(encryptor, decryptor);
}
}
catch
{
encryptionFailed = true;
throw;
}
}
}
}

Loading…
Cancel
Save