diff --git a/Shadowsocks.Protocol/Shadowsocks/AeadClient.cs b/Shadowsocks.Protocol/Shadowsocks/AeadClient.cs index a6b72215..b2efbcf7 100644 --- a/Shadowsocks.Protocol/Shadowsocks/AeadClient.cs +++ b/Shadowsocks.Protocol/Shadowsocks/AeadClient.cs @@ -42,7 +42,7 @@ namespace Shadowsocks.Protocol.Shadowsocks public async Task ConvertUplink(IDuplexPipe client, IDuplexPipe server) { - var up = cryptoParameter.GetCrypto(); + using var up = cryptoParameter.GetCrypto(); var pmp = new ProtocolMessagePipe(server); var salt = new SaltMessage(16, true); await pmp.WriteAsync(salt); @@ -77,7 +77,7 @@ namespace Shadowsocks.Protocol.Shadowsocks public async Task ConvertDownlink(IDuplexPipe client, IDuplexPipe server) { - var down = cryptoParameter.GetCrypto(); + using var down = cryptoParameter.GetCrypto(); var pmp = new ProtocolMessagePipe(server); var salt = await pmp.ReadAsync(new SaltMessage(cryptoParameter.KeySize)); diff --git a/Shadowsocks.Protocol/Shadowsocks/Crypto/AeadAesGcmCrypto.cs b/Shadowsocks.Protocol/Shadowsocks/Crypto/AeadAesGcmCrypto.cs index 1fe5dac6..9245809d 100644 --- a/Shadowsocks.Protocol/Shadowsocks/Crypto/AeadAesGcmCrypto.cs +++ b/Shadowsocks.Protocol/Shadowsocks/Crypto/AeadAesGcmCrypto.cs @@ -1,38 +1,13 @@ -using System; -using System.Security.Cryptography; +using CryptoBase; namespace Shadowsocks.Protocol.Shadowsocks.Crypto { - class AeadAesGcmCrypto : ICrypto + public class AeadAesGcmCrypto : AeadCrypto { - AesGcm aes; - - CryptoParameter parameter; - public AeadAesGcmCrypto(CryptoParameter parameter) + public AeadAesGcmCrypto(CryptoParameter parameter) : base(parameter) { - this.parameter = parameter; } - public void Init(byte[] key, byte[] iv) => aes = new AesGcm(key); - - public int Decrypt(ReadOnlySpan nonce, Span plain, ReadOnlySpan cipher) - { - aes.Decrypt( - nonce, - cipher[0..^parameter.TagSize], - cipher[^parameter.TagSize..], - plain[0..(cipher.Length - parameter.TagSize)]); - return cipher.Length - parameter.TagSize; - } - - public int Encrypt(ReadOnlySpan nonce, ReadOnlySpan plain, Span cipher) - { - aes.Encrypt( - nonce, - plain, - cipher[0..plain.Length], - cipher.Slice(plain.Length, parameter.TagSize)); - return plain.Length + parameter.TagSize; - } + public override void Init(byte[] key, byte[] iv) => crypto = AEADCryptoCreate.AesGcm(key); } } diff --git a/Shadowsocks.Protocol/Shadowsocks/Crypto/AeadChaCha20Poly1305Crypto.cs b/Shadowsocks.Protocol/Shadowsocks/Crypto/AeadChaCha20Poly1305Crypto.cs new file mode 100644 index 00000000..a719c344 --- /dev/null +++ b/Shadowsocks.Protocol/Shadowsocks/Crypto/AeadChaCha20Poly1305Crypto.cs @@ -0,0 +1,13 @@ +using CryptoBase; + +namespace Shadowsocks.Protocol.Shadowsocks.Crypto +{ + public class AeadChaCha20Poly1305Crypto : AeadCrypto + { + public AeadChaCha20Poly1305Crypto(CryptoParameter parameter) : base(parameter) + { + } + + public override void Init(byte[] key, byte[] iv) => crypto = AEADCryptoCreate.ChaCha20Poly1305(key); + } +} diff --git a/Shadowsocks.Protocol/Shadowsocks/Crypto/AeadCrypto.cs b/Shadowsocks.Protocol/Shadowsocks/Crypto/AeadCrypto.cs new file mode 100644 index 00000000..9c67e995 --- /dev/null +++ b/Shadowsocks.Protocol/Shadowsocks/Crypto/AeadCrypto.cs @@ -0,0 +1,41 @@ +using CryptoBase.Abstractions.SymmetricCryptos; +using System; + +namespace Shadowsocks.Protocol.Shadowsocks.Crypto +{ + public abstract class AeadCrypto : ICrypto + { + protected IAEADCrypto? crypto; + + private readonly CryptoParameter _parameter; + + protected AeadCrypto(CryptoParameter parameter) + { + _parameter = parameter; + } + + public abstract void Init(byte[] key, byte[] iv); + + public int Decrypt(ReadOnlySpan nonce, Span plain, ReadOnlySpan cipher) + { + crypto!.Decrypt( + nonce, + cipher[..^_parameter.TagSize], + cipher[^_parameter.TagSize..], + plain[..(cipher.Length - _parameter.TagSize)]); + return cipher.Length - _parameter.TagSize; + } + + public int Encrypt(ReadOnlySpan nonce, ReadOnlySpan plain, Span cipher) + { + crypto!.Encrypt( + nonce, + plain, + cipher.Slice(0, plain.Length), + cipher.Slice(plain.Length, _parameter.TagSize)); + return plain.Length + _parameter.TagSize; + } + + public void Dispose() => crypto?.Dispose(); + } +} diff --git a/Shadowsocks.Protocol/Shadowsocks/Crypto/AeadXChaCha20Poly1305Crypto.cs b/Shadowsocks.Protocol/Shadowsocks/Crypto/AeadXChaCha20Poly1305Crypto.cs new file mode 100644 index 00000000..b0cfddb8 --- /dev/null +++ b/Shadowsocks.Protocol/Shadowsocks/Crypto/AeadXChaCha20Poly1305Crypto.cs @@ -0,0 +1,13 @@ +using CryptoBase; + +namespace Shadowsocks.Protocol.Shadowsocks.Crypto +{ + public class AeadXChaCha20Poly1305Crypto : AeadCrypto + { + public AeadXChaCha20Poly1305Crypto(CryptoParameter parameter) : base(parameter) + { + } + + public override void Init(byte[] key, byte[] iv) => crypto = AEADCryptoCreate.XChaCha20Poly1305(key); + } +} diff --git a/Shadowsocks.Protocol/Shadowsocks/Crypto/CryptoProvider.cs b/Shadowsocks.Protocol/Shadowsocks/Crypto/CryptoProvider.cs index 637e562d..fcbe164d 100644 --- a/Shadowsocks.Protocol/Shadowsocks/Crypto/CryptoProvider.cs +++ b/Shadowsocks.Protocol/Shadowsocks/Crypto/CryptoProvider.cs @@ -7,6 +7,8 @@ namespace Shadowsocks.Protocol.Shadowsocks.Crypto { static Dictionary parameters = new Dictionary { + ["xchacha20-ietf-poly1305"] = new CryptoParameter { KeySize = 32, NonceSize = 24, TagSize = 16, Crypto = typeof(AeadXChaCha20Poly1305Crypto) }, + ["chacha20-ietf-poly1305"] = new CryptoParameter { KeySize = 32, NonceSize = 12, TagSize = 16, Crypto = typeof(AeadChaCha20Poly1305Crypto) }, ["aes-256-gcm"] = new CryptoParameter { KeySize = 32, NonceSize = 12, TagSize = 16, Crypto = typeof(AeadAesGcmCrypto) }, ["aes-192-gcm"] = new CryptoParameter { KeySize = 24, NonceSize = 12, TagSize = 16, Crypto = typeof(AeadAesGcmCrypto) }, ["aes-128-gcm"] = new CryptoParameter { KeySize = 16, NonceSize = 12, TagSize = 16, Crypto = typeof(AeadAesGcmCrypto) }, diff --git a/Shadowsocks.Protocol/Shadowsocks/Crypto/UnsafeNoneCrypto.cs b/Shadowsocks.Protocol/Shadowsocks/Crypto/UnsafeNoneCrypto.cs index 4c885248..e28bf767 100644 --- a/Shadowsocks.Protocol/Shadowsocks/Crypto/UnsafeNoneCrypto.cs +++ b/Shadowsocks.Protocol/Shadowsocks/Crypto/UnsafeNoneCrypto.cs @@ -6,7 +6,6 @@ namespace Shadowsocks.Protocol.Shadowsocks.Crypto { public UnsafeNoneCrypto(CryptoParameter parameter) { - } public int Decrypt(ReadOnlySpan nonce, Span plain, ReadOnlySpan cipher) @@ -24,5 +23,9 @@ namespace Shadowsocks.Protocol.Shadowsocks.Crypto public void Init(byte[] key, byte[] iv) { } + + public void Dispose() + { + } } } diff --git a/Shadowsocks.Protocol/Shadowsocks/ICrypto.cs b/Shadowsocks.Protocol/Shadowsocks/ICrypto.cs index d23881cb..1fc12ffc 100644 --- a/Shadowsocks.Protocol/Shadowsocks/ICrypto.cs +++ b/Shadowsocks.Protocol/Shadowsocks/ICrypto.cs @@ -3,7 +3,7 @@ using System; namespace Shadowsocks.Protocol.Shadowsocks { // stream cipher simply ignore nonce - public interface ICrypto + public interface ICrypto : IDisposable { void Init(byte[] key, byte[] iv); int Encrypt(ReadOnlySpan nonce, ReadOnlySpan plain, Span cipher); diff --git a/Shadowsocks.Protocol/Shadowsocks/UnsafeClient.cs b/Shadowsocks.Protocol/Shadowsocks/UnsafeClient.cs index 02a19819..154cf953 100644 --- a/Shadowsocks.Protocol/Shadowsocks/UnsafeClient.cs +++ b/Shadowsocks.Protocol/Shadowsocks/UnsafeClient.cs @@ -24,7 +24,7 @@ namespace Shadowsocks.Protocol.Shadowsocks public async Task ConvertUplink(IDuplexPipe client, IDuplexPipe server) { - var up = parameter.GetCrypto(); + using var up = parameter.GetCrypto(); var pmp = new ProtocolMessagePipe(server); var key = CryptoUtils.SSKDF(password, parameter.KeySize); @@ -54,7 +54,7 @@ namespace Shadowsocks.Protocol.Shadowsocks public async Task ConvertDownlink(IDuplexPipe client, IDuplexPipe server) { - var down = parameter.GetCrypto(); + using var down = parameter.GetCrypto(); var pmp = new ProtocolMessagePipe(server); var salt = await pmp.ReadAsync(new SaltMessage(parameter.NonceSize));