From 83b994e3b4537ab8826350ccd24ed3b18b1e9364 Mon Sep 17 00:00:00 2001 From: Student Main Date: Sat, 21 Mar 2020 15:39:18 +0800 Subject: [PATCH] NaCl.Core based ChaCha20Poly1305 --- .../Encryption/AEAD/AEADNaClEncryptor.cs | 75 ++++++++++++++++ shadowsocks-csharp/packages.config | 5 ++ shadowsocks-csharp/shadowsocks-csharp.csproj | 18 ++++ test/CryptographyTest.cs | 89 ++++++++++++++----- 4 files changed, 164 insertions(+), 23 deletions(-) create mode 100644 shadowsocks-csharp/Encryption/AEAD/AEADNaClEncryptor.cs diff --git a/shadowsocks-csharp/Encryption/AEAD/AEADNaClEncryptor.cs b/shadowsocks-csharp/Encryption/AEAD/AEADNaClEncryptor.cs new file mode 100644 index 00000000..d2631e21 --- /dev/null +++ b/shadowsocks-csharp/Encryption/AEAD/AEADNaClEncryptor.cs @@ -0,0 +1,75 @@ +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 _ciphers = new Dictionary + { + {"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 getCiphers() + { + return _ciphers; + } + } +} diff --git a/shadowsocks-csharp/packages.config b/shadowsocks-csharp/packages.config index 67621a9d..63937973 100644 --- a/shadowsocks-csharp/packages.config +++ b/shadowsocks-csharp/packages.config @@ -5,8 +5,13 @@ + + + + + \ No newline at end of file diff --git a/shadowsocks-csharp/shadowsocks-csharp.csproj b/shadowsocks-csharp/shadowsocks-csharp.csproj index 4c5bbb56..1f028e9a 100644 --- a/shadowsocks-csharp/shadowsocks-csharp.csproj +++ b/shadowsocks-csharp/shadowsocks-csharp.csproj @@ -82,6 +82,9 @@ + + ..\packages\NaCl.Core.1.2.0\lib\net47\NaCl.Core.dll + ..\packages\Newtonsoft.Json.12.0.2\lib\net45\Newtonsoft.Json.dll @@ -90,13 +93,26 @@ + + ..\packages\System.Buffers.4.4.0\lib\netstandard2.0\System.Buffers.dll + + + ..\packages\System.Memory.4.5.2\lib\netstandard2.0\System.Memory.dll + + + + ..\packages\System.Numerics.Vectors.4.4.0\lib\net46\System.Numerics.Vectors.dll + + + ..\packages\System.Runtime.CompilerServices.Unsafe.4.5.2\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll + @@ -120,10 +136,12 @@ + + diff --git a/test/CryptographyTest.cs b/test/CryptographyTest.cs index 49ef5e87..84ea9bf0 100644 --- a/test/CryptographyTest.cs +++ b/test/CryptographyTest.cs @@ -310,6 +310,72 @@ namespace Shadowsocks.Test 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] + public void TesNaClAEADEncryption() + { + encryptionFailed = false; + // run it once before the multi-threading test to initialize global tables + RunSingleNaClAEADEncryptionThread(); + List threads = new List(); + for (int i = 0; i < 10; i++) + { + Thread t = new Thread(new ThreadStart(RunSingleNaClAEADEncryptionThread)); threads.Add(t); + t.Start(); + } + foreach (Thread t in threads) + { + t.Join(); + } + RNG.Close(); + Assert.IsFalse(encryptionFailed); + } + + private void RunSingleNaClAEADEncryptionThread() + { + try + { + for (int i = 0; i < 100; i++) + { + 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 + { + encryptionFailed = true; + throw; + } + } + [TestMethod] public void TestNativeEncryption() { @@ -357,29 +423,6 @@ namespace Shadowsocks.Test } } - 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] public void TestOpenSSLAEADEncryption() {