@@ -0,0 +1,85 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Linq; | |||||
using System.Text; | |||||
using System.Threading.Tasks; | |||||
using NaCl.Core; | |||||
using NaCl.Core.Base; | |||||
namespace Shadowsocks.Encryption.AEAD | |||||
{ | |||||
public class AEADNaClEncryptor : AEADEncryptor | |||||
{ | |||||
SnufflePoly1305 enc; | |||||
SnufflePoly1305 dec; | |||||
public AEADNaClEncryptor(string method, string password) : base(method, password) | |||||
{ | |||||
} | |||||
public override void InitCipher(byte[] salt, bool isEncrypt, bool isUdp) | |||||
{ | |||||
base.InitCipher(salt, isEncrypt, isUdp); | |||||
DeriveSessionKey(isEncrypt ? encryptSalt : decryptSalt, | |||||
_Masterkey, sessionKey); | |||||
SnufflePoly1305 tmp; | |||||
switch (_cipher) | |||||
{ | |||||
default: | |||||
case CipherChaCha20Poly1305: | |||||
tmp = new ChaCha20Poly1305(sessionKey); | |||||
break; | |||||
case CipherXChaCha20Poly1305: | |||||
tmp = new XChaCha20Poly1305(sessionKey); | |||||
break; | |||||
} | |||||
if (isEncrypt) enc = tmp; | |||||
else dec = tmp; | |||||
} | |||||
public override void cipherDecrypt(byte[] ciphertext, uint clen, byte[] plaintext, ref uint plen) | |||||
{ | |||||
var pt = dec.Decrypt(ciphertext, null, decNonce); | |||||
pt.CopyTo(plaintext, 0); | |||||
plen = (uint)pt.Length; | |||||
} | |||||
public override void cipherEncrypt(byte[] plaintext, uint plen, byte[] ciphertext, ref uint clen) | |||||
{ | |||||
var ct = enc.Encrypt(plaintext, null, encNonce); | |||||
ct.CopyTo(ciphertext, 0); | |||||
clen = (uint)ct.Length; | |||||
} | |||||
public override void Dispose() | |||||
{ | |||||
} | |||||
const int CipherChaCha20Poly1305 = 1; | |||||
const int CipherXChaCha20Poly1305 = 2; | |||||
private static readonly Dictionary<string, EncryptorInfo> _ciphers = new Dictionary<string, EncryptorInfo> | |||||
{ | |||||
{"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)}, | |||||
}; | |||||
protected override Dictionary<string, EncryptorInfo> getCiphers() | |||||
{ | |||||
return _ciphers; | |||||
} | |||||
public override byte[] CipherEncrypt2(byte[] plain) | |||||
{ | |||||
return enc.Encrypt(plain, null, encNonce); | |||||
} | |||||
public override byte[] CipherDecrypt2(byte[] cipher) | |||||
{ | |||||
return dec.Decrypt(cipher, null, decNonce); | |||||
} | |||||
} | |||||
} |
@@ -5,8 +5,13 @@ | |||||
<package id="Costura.Fody" version="3.3.3" targetFramework="net472" /> | <package id="Costura.Fody" version="3.3.3" targetFramework="net472" /> | ||||
<package id="Fody" version="4.2.1" targetFramework="net472" developmentDependency="true" /> | <package id="Fody" version="4.2.1" targetFramework="net472" developmentDependency="true" /> | ||||
<package id="GlobalHotKey" version="1.1.0" targetFramework="net472" /> | <package id="GlobalHotKey" version="1.1.0" targetFramework="net472" /> | ||||
<package id="NaCl.Core" version="1.2.0" targetFramework="net472" /> | |||||
<package id="Newtonsoft.Json" version="12.0.2" targetFramework="net472" /> | <package id="Newtonsoft.Json" version="12.0.2" targetFramework="net472" /> | ||||
<package id="NLog" version="4.6.8" targetFramework="net472" /> | <package id="NLog" version="4.6.8" targetFramework="net472" /> | ||||
<package id="StringEx.CS" version="0.3.1" targetFramework="net472" developmentDependency="true" /> | <package id="StringEx.CS" version="0.3.1" targetFramework="net472" developmentDependency="true" /> | ||||
<package id="System.Buffers" version="4.4.0" targetFramework="net472" /> | |||||
<package id="System.Memory" version="4.5.2" targetFramework="net472" /> | |||||
<package id="System.Numerics.Vectors" version="4.4.0" targetFramework="net472" /> | |||||
<package id="System.Runtime.CompilerServices.Unsafe" version="4.5.2" targetFramework="net472" /> | |||||
<package id="ZXing.Net" version="0.16.5" targetFramework="net472" /> | <package id="ZXing.Net" version="0.16.5" targetFramework="net472" /> | ||||
</packages> | </packages> |
@@ -66,6 +66,8 @@ | |||||
</PackageReference> | </PackageReference> | ||||
<PackageReference Include="Microsoft.VisualBasic" Version="10.3.0" /> | <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="Newtonsoft.Json" Version="12.0.3" /> | ||||
<PackageReference Include="NLog" Version="4.6.8" /> | <PackageReference Include="NLog" Version="4.6.8" /> | ||||
<PackageReference Include="StringEx.CS" Version="0.3.1"> | <PackageReference Include="StringEx.CS" Version="0.3.1"> | ||||
@@ -82,17 +82,39 @@ namespace Shadowsocks.Test | |||||
Assert.IsFalse(encryptionFailed); | Assert.IsFalse(encryptionFailed); | ||||
} | } | ||||
private void RunSingleBouncyCastleAEADEncryptionThread() | |||||
{ | |||||
try | |||||
{ | |||||
for (int i = 0; i < 100; i++) | |||||
{ | |||||
var random = new Random(); | |||||
IEncryptor encryptor; | |||||
IEncryptor decryptor; | |||||
encryptor = new Encryption.AEAD.AEADBouncyCastleEncryptor("aes-256-gcm", "barfoo!"); | |||||
encryptor.AddrBufLength = 1 + 4 + 2;// ADDR_ATYP_LEN + 4 + ADDR_PORT_LEN; | |||||
decryptor = new Encryption.AEAD.AEADBouncyCastleEncryptor("aes-256-gcm", "barfoo!"); | |||||
decryptor.AddrBufLength = 1 + 4 + 2;// ADDR_ATYP_LEN + 4 + ADDR_PORT_LEN; | |||||
RunEncryptionRound(encryptor, decryptor); | |||||
} | |||||
} | |||||
catch | |||||
{ | |||||
encryptionFailed = true; | |||||
throw; | |||||
} | |||||
} | |||||
[TestMethod] | [TestMethod] | ||||
public void TestNativeEncryption() | |||||
public void TesNaClAEADEncryption() | |||||
{ | { | ||||
encryptionFailed = false; | encryptionFailed = false; | ||||
// run it once before the multi-threading test to initialize global tables | // run it once before the multi-threading test to initialize global tables | ||||
RunSingleNativeEncryptionThread(); | |||||
RunSingleNaClAEADEncryptionThread(); | |||||
List<Thread> threads = new List<Thread>(); | List<Thread> threads = new List<Thread>(); | ||||
for (int i = 0; i < 10; i++) | for (int i = 0; i < 10; i++) | ||||
{ | { | ||||
Thread t = new Thread(new ThreadStart(RunSingleNativeEncryptionThread)); | |||||
threads.Add(t); | |||||
Thread t = new Thread(new ThreadStart(RunSingleNaClAEADEncryptionThread)); threads.Add(t); | |||||
t.Start(); | t.Start(); | ||||
} | } | ||||
foreach (Thread t in threads) | foreach (Thread t in threads) | ||||
@@ -103,17 +125,20 @@ namespace Shadowsocks.Test | |||||
Assert.IsFalse(encryptionFailed); | Assert.IsFalse(encryptionFailed); | ||||
} | } | ||||
private void RunSingleNativeEncryptionThread() | |||||
private void RunSingleNaClAEADEncryptionThread() | |||||
{ | { | ||||
try | try | ||||
{ | { | ||||
for (int i = 0; i < 100; i++) | for (int i = 0; i < 100; i++) | ||||
{ | { | ||||
IEncryptor encryptorN; | |||||
IEncryptor decryptorN; | |||||
encryptorN = new StreamRc4NativeEncryptor("rc4-md5", "barfoo!"); | |||||
decryptorN = new StreamRc4NativeEncryptor("rc4-md5", "barfoo!"); | |||||
RunEncryptionRound(encryptorN, decryptorN); | |||||
var random = new Random(); | |||||
IEncryptor encryptor; | |||||
IEncryptor decryptor; | |||||
encryptor = new Encryption.AEAD.AEADNaClEncryptor("chacha20-ietf-poly1305", "barfoo!"); | |||||
encryptor.AddrBufLength = 1 + 4 + 2;// ADDR_ATYP_LEN + 4 + ADDR_PORT_LEN; | |||||
decryptor = new Encryption.AEAD.AEADNaClEncryptor("chacha20-ietf-poly1305", "barfoo!"); | |||||
decryptor.AddrBufLength = 1 + 4 + 2;// ADDR_ATYP_LEN + 4 + ADDR_PORT_LEN; | |||||
RunEncryptionRound(encryptor, decryptor); | |||||
} | } | ||||
} | } | ||||
catch | catch | ||||
@@ -123,20 +148,38 @@ namespace Shadowsocks.Test | |||||
} | } | ||||
} | } | ||||
private void RunSingleBouncyCastleAEADEncryptionThread() | |||||
[TestMethod] | |||||
public void TestNativeEncryption() | |||||
{ | |||||
encryptionFailed = false; | |||||
// run it once before the multi-threading test to initialize global tables | |||||
RunSingleNativeEncryptionThread(); | |||||
List<Thread> threads = new List<Thread>(); | |||||
for (int i = 0; i < 10; i++) | |||||
{ | |||||
Thread t = new Thread(new ThreadStart(RunSingleNativeEncryptionThread)); | |||||
threads.Add(t); | |||||
t.Start(); | |||||
} | |||||
foreach (Thread t in threads) | |||||
{ | |||||
t.Join(); | |||||
} | |||||
RNG.Close(); | |||||
Assert.IsFalse(encryptionFailed); | |||||
} | |||||
private void RunSingleNativeEncryptionThread() | |||||
{ | { | ||||
try | try | ||||
{ | { | ||||
for (int i = 0; i < 100; i++) | for (int i = 0; i < 100; i++) | ||||
{ | { | ||||
var random = new Random(); | |||||
IEncryptor encryptor; | |||||
IEncryptor decryptor; | |||||
encryptor = new Encryption.AEAD.AEADBouncyCastleEncryptor("aes-256-gcm", "barfoo!"); | |||||
encryptor.AddrBufLength = 1 + 4 + 2;// ADDR_ATYP_LEN + 4 + ADDR_PORT_LEN; | |||||
decryptor = new Encryption.AEAD.AEADAesGcmNativeEncryptor("aes-256-gcm", "barfoo!"); | |||||
decryptor.AddrBufLength = 1 + 4 + 2;// ADDR_ATYP_LEN + 4 + ADDR_PORT_LEN; | |||||
RunEncryptionRound(encryptor, decryptor); | |||||
IEncryptor encryptorN; | |||||
IEncryptor decryptorN; | |||||
encryptorN = new StreamRc4NativeEncryptor("rc4-md5", "barfoo!"); | |||||
decryptorN = new StreamRc4NativeEncryptor("rc4-md5", "barfoo!"); | |||||
RunEncryptionRound(encryptorN, decryptorN); | |||||
} | } | ||||
} | } | ||||
catch | catch | ||||