diff --git a/shadowsocks-csharp/Encryption/AEAD/AEADAesGcmNativeEncryptor.cs b/shadowsocks-csharp/Encryption/AEAD/AEADAesGcmNativeEncryptor.cs index 44177e3f..6add700c 100644 --- a/shadowsocks-csharp/Encryption/AEAD/AEADAesGcmNativeEncryptor.cs +++ b/shadowsocks-csharp/Encryption/AEAD/AEADAesGcmNativeEncryptor.cs @@ -32,48 +32,6 @@ namespace Shadowsocks.Encryption.AEAD } #endregion - public override void cipherDecrypt(byte[] ciphertext, uint clen, byte[] plaintext, ref uint plen) - { - using (var aes = new AesGcm(sessionKey)) - { - byte[] tag = new byte[tagLen]; - byte[] cipherWithoutTag = new byte[clen]; - Array.Copy(ciphertext, 0, cipherWithoutTag, 0, clen - tagLen); - Array.Copy(ciphertext, clen - tagLen, tag, 0, tagLen); - aes.Decrypt(nonce, ciphertext, cipherWithoutTag, tag); - } - } - - public override void cipherEncrypt(byte[] plaintext, uint plen, byte[] ciphertext, ref uint clen) - { - using (var aes = new AesGcm(sessionKey)) - { - byte[] tag = new byte[tagLen]; - byte[] cipherWithoutTag = new byte[clen]; - aes.Encrypt(nonce, plaintext, cipherWithoutTag, tag); - cipherWithoutTag.CopyTo(ciphertext, 0); - tag.CopyTo(ciphertext, clen); - } - } - - public override byte[] CipherDecrypt2(byte[] cipher) - { - var (cipherMem, tagMem) = GetCipherTextAndTagMem(cipher); - Span plainMem = new Span(new byte[cipherMem.Length]); - - using var aes = new AesGcm(sessionKey); - aes.Decrypt(nonce.AsSpan(), cipherMem.Span, tagMem.Span, plainMem); - return plainMem.ToArray(); - } - - public override byte[] CipherEncrypt2(byte[] plain) - { - Span d = new Span(new byte[plain.Length + tagLen]); - using var aes = new AesGcm(sessionKey); - aes.Encrypt(nonce.AsSpan(), plain.AsSpan(), d.Slice(0, plain.Length), d.Slice(plain.Length)); - - return d.ToArray(); - } public override int CipherEncrypt(Span plain, Span cipher) { using var aes = new AesGcm(sessionKey); @@ -85,7 +43,9 @@ namespace Shadowsocks.Encryption.AEAD { int clen = cipher.Length - tagLen; using var aes = new AesGcm(sessionKey); - aes.Decrypt(nonce.AsSpan(), plain, cipher.Slice(0, clen), cipher.Slice(clen)); + var ciphertxt = cipher.Slice(0, clen); + var tag = cipher.Slice(clen); + aes.Decrypt(nonce.AsSpan(), ciphertxt, tag, plain.Slice(0, clen)); return clen; } } diff --git a/shadowsocks-csharp/Encryption/AEAD/AEADEncryptor.cs b/shadowsocks-csharp/Encryption/AEAD/AEADEncryptor.cs index 7858bb80..78781182 100644 --- a/shadowsocks-csharp/Encryption/AEAD/AEADEncryptor.cs +++ b/shadowsocks-csharp/Encryption/AEAD/AEADEncryptor.cs @@ -18,9 +18,6 @@ namespace Shadowsocks.Encryption.AEAD private const string Info = "ss-subkey"; private static readonly byte[] InfoBytes = Encoding.ASCII.GetBytes(Info); - // for UDP only - protected static byte[] _udpTmpBuf = new byte[65536]; - // every connection should create its own buffer private ByteCircularBuffer buffer = new ByteCircularBuffer(MaxInputSize * 2); @@ -29,19 +26,16 @@ namespace Shadowsocks.Encryption.AEAD protected Dictionary ciphers; - protected string _method; - protected CipherFamily _cipher; + protected CipherFamily cipherFamily; protected CipherInfo CipherInfo; - protected static byte[] masterKey = null; - protected byte[] sessionKey; + protected static byte[] masterKey = Array.Empty(); + protected byte[] sessionKey = Array.Empty(); protected int keyLen; protected int saltLen; protected int tagLen; protected int nonceLen; protected byte[] salt; - - protected object _nonceIncrementLock = new object(); protected byte[] nonce; // Is first packet @@ -53,29 +47,21 @@ namespace Shadowsocks.Encryption.AEAD public AEADEncryptor(string method, string password) : base(method, password) { - InitEncryptorInfo(method); - InitKey(password); - // Initialize all-zero nonce for each connection - nonce = new byte[nonceLen]; - nonce = new byte[nonceLen]; - } - - protected abstract Dictionary getCiphers(); - - protected void InitEncryptorInfo(string method) - { - method = method.ToLower(); - _method = method; - ciphers = getCiphers(); - CipherInfo = ciphers[_method]; - _cipher = CipherInfo.Type; + CipherInfo = getCiphers()[method.ToLower()]; + cipherFamily = CipherInfo.Type; var parameter = (AEADCipherParameter)CipherInfo.CipherParameter; keyLen = parameter.KeySize; saltLen = parameter.SaltSize; tagLen = parameter.TagSize; nonceLen = parameter.NonceSize; + + InitKey(password); + // Initialize all-zero nonce for each connection + nonce = new byte[nonceLen]; } + protected abstract Dictionary getCiphers(); + protected void InitKey(string password) { byte[] passbuf = Encoding.UTF8.GetBytes(password); @@ -84,7 +70,7 @@ namespace Shadowsocks.Encryption.AEAD if (masterKey.Length != keyLen) Array.Resize(ref masterKey, keyLen); DeriveKey(passbuf, masterKey, keyLen); // init session key - if (sessionKey == null) sessionKey = new byte[keyLen]; + sessionKey = new byte[keyLen]; } public void DeriveKey(byte[] password, byte[] key, int keylen) @@ -111,50 +97,9 @@ namespace Shadowsocks.Encryption.AEAD DeriveSessionKey(salt, masterKey, sessionKey); } - /// - /// - /// - /// Input, plain text - /// plaintext.Length - /// Output, allocated by caller, tag space included, - /// length = plaintext.Length + tagLen, [enc][tag] order - /// Should be same as ciphertext.Length - public abstract void cipherEncrypt(byte[] plaintext, uint plen, byte[] ciphertext, ref uint clen); - public abstract int CipherEncrypt(Span plain, Span cipher); public abstract int CipherDecrypt(Span plain, Span cipher); - // plain -> cipher + tag - [Obsolete] - public abstract byte[] CipherEncrypt2(byte[] plain); - // cipher + tag -> plain - [Obsolete] - public abstract byte[] CipherDecrypt2(byte[] cipher); - - public (Memory, Memory) GetCipherTextAndTagMem(byte[] cipher) - { - var mc = cipher.AsMemory(); - var clen = mc.Length - tagLen; - var c = mc.Slice(0, clen); - var t = mc.Slice(clen); - - return (c, t); - } - public (byte[], byte[]) GetCipherTextAndTag(byte[] cipher) - { - var (c, t) = GetCipherTextAndTagMem(cipher); - return (c.ToArray(), t.ToArray()); - } - - /// - /// - /// - /// Cipher text in [enc][tag] order - /// ciphertext.Length - /// Output plain text may with additional data allocated by caller - /// Output, should be used plain text length - public abstract void cipherDecrypt(byte[] ciphertext, uint clen, byte[] plaintext, ref uint plen); - #region TCP public override void Encrypt(byte[] buf, int length, byte[] outbuf, out int outlength) @@ -266,7 +211,8 @@ namespace Shadowsocks.Encryption.AEAD byte[] encLenBytes = buffer.Peek(ChunkLengthBytes + tagLen); // try to dec chunk len - byte[] decChunkLenBytes = CipherDecrypt2(encLenBytes); + byte[] decChunkLenBytes = new byte[ChunkLengthBytes]; + CipherDecrypt(decChunkLenBytes, encLenBytes); ushort chunkLen = (ushort)IPAddress.NetworkToHostOrder((short)BitConverter.ToUInt16(decChunkLenBytes, 0)); if (chunkLen > ChunkLengthMask) { @@ -287,15 +233,17 @@ namespace Shadowsocks.Encryption.AEAD // drop chunk len and its tag from buffer buffer.Skip(ChunkLengthBytes + tagLen); byte[] encChunkBytes = buffer.Get(chunkLen + tagLen); - byte[] decChunkBytes = CipherDecrypt2(encChunkBytes); + // byte[] decChunkBytes = CipherDecrypt2(encChunkBytes); + + int len = CipherDecrypt(outbuf.AsSpan().Slice(outlength), encChunkBytes); IncrementNonce(); #endregion // output to outbuf - decChunkBytes.CopyTo(outbuf, outlength); + // decChunkBytes.CopyTo(outbuf, outlength); // Buffer.BlockCopy(decChunkBytes, 0, outbuf, outlength, (int)decChunkLen); - outlength += decChunkBytes.Length; + outlength += len; logger.Debug("aead dec outlength " + outlength); if (outlength + 100 > TCPHandler.BufferSize) { @@ -326,36 +274,18 @@ namespace Shadowsocks.Encryption.AEAD public override void EncryptUDP(byte[] buf, int length, byte[] outbuf, out int outlength) { // Generate salt - //RNG.GetBytes(outbuf, saltLen); RNG.GetSpan(outbuf.AsSpan(0, saltLen)); InitCipher(outbuf, true, true); - //uint olen = 0; - lock (_udpTmpBuf) - { - //cipherEncrypt(buf, (uint)length, _udpTmpBuf, ref olen); - var plain = buf.AsSpan(0, length).ToArray(); // mmp - var cipher = CipherEncrypt2(plain); - //Debug.Assert(olen == length + tagLen); - Buffer.BlockCopy(cipher, 0, outbuf, saltLen, length + tagLen); - //Buffer.BlockCopy(_udpTmpBuf, 0, outbuf, saltLen, (int)olen); - outlength = saltLen + cipher.Length; - } + outlength = saltLen + CipherEncrypt( + buf.AsSpan(0, length), + outbuf.AsSpan(saltLen, length + tagLen)); + } public override void DecryptUDP(byte[] buf, int length, byte[] outbuf, out int outlength) { InitCipher(buf, false, true); - //uint olen = 0; - lock (_udpTmpBuf) - { - // copy remaining data to first pos - Buffer.BlockCopy(buf, saltLen, buf, 0, length - saltLen); - byte[] b = buf.AsSpan(0, length - saltLen).ToArray(); - byte[] o = CipherDecrypt2(b); - //cipherDecrypt(buf, (uint)(length - saltLen), _udpTmpBuf, ref olen); - Buffer.BlockCopy(o, 0, outbuf, 0, o.Length); - outlength = o.Length; - } + outlength = CipherDecrypt(outbuf, buf.AsSpan(saltLen, length - saltLen)); } #endregion diff --git a/shadowsocks-csharp/Encryption/AEAD/AEADNaClEncryptor.cs b/shadowsocks-csharp/Encryption/AEAD/AEADNaClEncryptor.cs index eee85e98..6e956420 100644 --- a/shadowsocks-csharp/Encryption/AEAD/AEADNaClEncryptor.cs +++ b/shadowsocks-csharp/Encryption/AEAD/AEADNaClEncryptor.cs @@ -37,7 +37,7 @@ namespace Shadowsocks.Encryption.AEAD public override void InitCipher(byte[] salt, bool isEncrypt, bool isUdp) { base.InitCipher(salt, isEncrypt, isUdp); - switch (_cipher) + switch (cipherFamily) { default: case CipherFamily.Chacha20Poly1305: @@ -48,31 +48,7 @@ namespace Shadowsocks.Encryption.AEAD break; } } - - public override void cipherDecrypt(byte[] ciphertext, uint clen, byte[] plaintext, ref uint plen) - { - var pt = enc.Decrypt(ciphertext, null, nonce); - 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, nonce); - ct.CopyTo(ciphertext, 0); - clen = (uint)ct.Length; - } - - public override byte[] CipherEncrypt2(byte[] plain) - { - return enc.Encrypt(plain, null, nonce); - } - - public override byte[] CipherDecrypt2(byte[] cipher) - { - return enc.Decrypt(cipher, null, nonce); - } - + public override int CipherEncrypt(Span plain, Span cipher) { var ct = enc.Encrypt(plain, null, nonce);