diff --git a/shadowsocks-csharp/Encryption/AEAD/AEADBouncyCastleEncryptor.cs b/shadowsocks-csharp/Encryption/AEAD/AEADBouncyCastleEncryptor.cs index 2147028c..be028808 100644 --- a/shadowsocks-csharp/Encryption/AEAD/AEADBouncyCastleEncryptor.cs +++ b/shadowsocks-csharp/Encryption/AEAD/AEADBouncyCastleEncryptor.cs @@ -9,14 +9,16 @@ using System.Threading.Tasks; namespace Shadowsocks.Encryption.AEAD { - public class AEADBouncyCastleEncryptor : AEADEncryptor//, IDisposable + public class AEADBouncyCastleEncryptor : AEADEncryptor, IDisposable { + static int CIPHER_AES = 1; // dummy + public AEADBouncyCastleEncryptor(string method, string password) : base(method, password) { } - static int CIPHER_AES=1; + private static readonly Dictionary _ciphers = new Dictionary { {"aes-128-gcm", new EncryptorInfo("AES-128-GCM", 16, 16, 12, 16, CIPHER_AES)}, @@ -29,46 +31,47 @@ namespace Shadowsocks.Encryption.AEAD return _ciphers; } + public override void InitCipher(byte[] salt, bool isEncrypt, bool isUdp) + { + base.InitCipher(salt, isEncrypt, isUdp); + + DeriveSessionKey(isEncrypt ? _encryptSalt : _decryptSalt, + _Masterkey, _sessionKey); + } + public override void cipherDecrypt(byte[] ciphertext, uint clen, byte[] plaintext, ref uint plen) { - GcmBlockCipher cipher = new GcmBlockCipher(new AesEngine()); + var cipher = new GcmBlockCipher(new AesEngine()); AeadParameters parameters = new AeadParameters(new KeyParameter(_sessionKey), tagLen * 8, _decNonce); cipher.Init(false, parameters); - plaintext = new byte[cipher.GetOutputSize((int)clen)]; - var len = cipher.ProcessBytes(ciphertext, 0, (int)clen, plaintext, 0); - cipher.DoFinal(plaintext, len); - plen = (uint)(plaintext.Length); + var plaintextBC = new byte[cipher.GetOutputSize((int)clen)]; + var len = cipher.ProcessBytes(ciphertext, 0, (int)clen, plaintextBC, 0); + cipher.DoFinal(plaintextBC, len); + plen = (uint)(plaintextBC.Length); + Array.Copy(plaintextBC, 0, plaintext, 0, plen); } public override void cipherEncrypt(byte[] plaintext, uint plen, byte[] ciphertext, ref uint clen) { - GcmBlockCipher cipher = new GcmBlockCipher(new AesEngine()); + var cipher = new GcmBlockCipher(new AesEngine()); AeadParameters parameters = new AeadParameters(new KeyParameter(_sessionKey), tagLen * 8, _encNonce); cipher.Init(true, parameters); - ciphertext = new byte[cipher.GetOutputSize((int)plen)]; - var len = cipher.ProcessBytes(plaintext, 0, (int)plen, ciphertext, 0); - cipher.DoFinal(ciphertext, len); - clen = (uint)(ciphertext.Length); - } - - public override void Dispose() - { - //throw new NotImplementedException(); + var ciphertextBC = new byte[cipher.GetOutputSize((int)plen)]; + var len = cipher.ProcessBytes(plaintext, 0, (int)plen, ciphertextBC, 0); + cipher.DoFinal(ciphertextBC, len); + clen = (uint)(ciphertextBC.Length); + Array.Copy(ciphertextBC, 0, ciphertext, 0, clen); } - public override void InitCipher(byte[] salt, bool isEncrypt, bool isUdp) + public static List SupportedCiphers() { - base.InitCipher(salt, isEncrypt, isUdp); - - DeriveSessionKey(isEncrypt ? _encryptSalt : _decryptSalt, - _Masterkey, _sessionKey); + return new List(_ciphers.Keys); } - public static List SupportedCiphers() + public override void Dispose() { - return new List(_ciphers.Keys); } } } diff --git a/test/CryptographyTest.cs b/test/CryptographyTest.cs index 6455c9ca..1ad1cebe 100644 --- a/test/CryptographyTest.cs +++ b/test/CryptographyTest.cs @@ -44,20 +44,20 @@ namespace Shadowsocks.Test { Assert.AreEqual(plain[j], plain2[j]); } - //encryptor.Encrypt(plain, 1000, cipher, out outLen); - //decryptor.Decrypt(cipher, outLen, plain2, out outLen2); - //Assert.AreEqual(1000, outLen2); - //for (int j = 0; j < outLen2; j++) - //{ - // Assert.AreEqual(plain[j], plain2[j]); - //} - //encryptor.Encrypt(plain, 12333, cipher, out outLen); - //decryptor.Decrypt(cipher, outLen, plain2, out outLen2); - //Assert.AreEqual(12333, outLen2); - //for (int j = 0; j < outLen2; j++) - //{ - // Assert.AreEqual(plain[j], plain2[j]); - //} + encryptor.Encrypt(plain, 1000, cipher, out outLen); + decryptor.Decrypt(cipher, outLen, plain2, out outLen2); + Assert.AreEqual(1000, outLen2); + for (int j = 0; j < outLen2; j++) + { + Assert.AreEqual(plain[j], plain2[j]); + } + encryptor.Encrypt(plain, 12333, cipher, out outLen); + decryptor.Decrypt(cipher, outLen, plain2, out outLen2); + Assert.AreEqual(12333, outLen2); + for (int j = 0; j < outLen2; j++) + { + Assert.AreEqual(plain[j], plain2[j]); + } } private static bool encryptionFailed = false; @@ -231,15 +231,15 @@ namespace Shadowsocks.Test } [TestMethod] - public void TestBouncyCastleEncryption() + public void TestBouncyCastleAEADEncryption() { encryptionFailed = false; // run it once before the multi-threading test to initialize global tables - RunSingleBouncyCastleEncryptionThread(); + RunSingleBouncyCastleAEADEncryptionThread(); List threads = new List(); for (int i = 0; i < 10; i++) { - Thread t = new Thread(new ThreadStart(RunSingleBouncyCastleEncryptionThread)); + Thread t = new Thread(new ThreadStart(RunSingleBouncyCastleAEADEncryptionThread)); threads.Add(t); t.Start(); } @@ -251,11 +251,11 @@ namespace Shadowsocks.Test Assert.IsFalse(encryptionFailed); } - private void RunSingleBouncyCastleEncryptionThread() + private void RunSingleBouncyCastleAEADEncryptionThread() { try { - for (int i = 0; i < 10; i++) + for (int i = 0; i < 100; i++) { var random = new Random(); IEncryptor encryptor; @@ -299,7 +299,7 @@ namespace Shadowsocks.Test { try { - for (int i = 0; i < 10; i++) + for (int i = 0; i < 100; i++) { var random = new Random(); IEncryptor encryptor; @@ -343,7 +343,7 @@ namespace Shadowsocks.Test { try { - for (int i = 0; i < 10; i++) + for (int i = 0; i < 100; i++) { var random = new Random(); IEncryptor encryptor;