diff --git a/shadowsocks-csharp/Controller/ShadowsocksController.cs b/shadowsocks-csharp/Controller/ShadowsocksController.cs index 6340213a..a50ed720 100644 --- a/shadowsocks-csharp/Controller/ShadowsocksController.cs +++ b/shadowsocks-csharp/Controller/ShadowsocksController.cs @@ -272,6 +272,7 @@ namespace Shadowsocks.Controller { SystemProxy.Update(_config, true); } + Encryption.RNG.Close(); } public void TouchPACFile() @@ -413,6 +414,7 @@ namespace Shadowsocks.Controller protected void Reload() { + Encryption.RNG.Reload(); // some logic in configuration updated the config when saving, we need to read it again _config = Configuration.Load(); StatisticsConfiguration = StatisticsStrategyConfiguration.Load(); diff --git a/shadowsocks-csharp/Encryption/IVEncryptor.cs b/shadowsocks-csharp/Encryption/IVEncryptor.cs index f6781a29..8a9d88d2 100755 --- a/shadowsocks-csharp/Encryption/IVEncryptor.cs +++ b/shadowsocks-csharp/Encryption/IVEncryptor.cs @@ -1,8 +1,6 @@ using System; using System.Collections.Generic; using System.Collections.Concurrent; -using System.Linq; -using System.Security.Cryptography; using System.Text; using System.Net; @@ -237,10 +235,7 @@ namespace Shadowsocks.Encryption protected static void randBytes(byte[] buf, int length) { - using (RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider()) - { - rng.GetBytes(buf, 0, length); - } + RNG.GetBytes(buf, length); } public override void Encrypt(byte[] buf, int length, byte[] outbuf, out int outlength) diff --git a/shadowsocks-csharp/Encryption/RNG.cs b/shadowsocks-csharp/Encryption/RNG.cs new file mode 100644 index 00000000..cb783144 --- /dev/null +++ b/shadowsocks-csharp/Encryption/RNG.cs @@ -0,0 +1,44 @@ +using System; +using System.Security.Cryptography; + +namespace Shadowsocks.Encryption +{ + public static class RNG + { + private static RNGCryptoServiceProvider _rng = null; + + public static void Init() + { + if (_rng == null) + _rng = new RNGCryptoServiceProvider(); + } + + public static void Close() + { + if (_rng == null) return; + _rng.Dispose(); + _rng = null; + } + + public static void Reload() + { + Close(); + Init(); + } + + public static void GetBytes(byte[] buf, int len) + { + try + { + _rng.GetBytes(buf, 0, len); + } + catch (Exception) + { + // the backup way + byte[] tmp = new byte[len]; + _rng.GetBytes(tmp); + Buffer.BlockCopy(tmp, 0, buf, 0, len); + } + } + } +} \ No newline at end of file diff --git a/shadowsocks-csharp/shadowsocks-csharp.csproj b/shadowsocks-csharp/shadowsocks-csharp.csproj index 77460a90..26ea4fd2 100644 --- a/shadowsocks-csharp/shadowsocks-csharp.csproj +++ b/shadowsocks-csharp/shadowsocks-csharp.csproj @@ -183,6 +183,7 @@ + diff --git a/test/UnitTest.cs b/test/UnitTest.cs index 6364dba2..539140d6 100755 --- a/test/UnitTest.cs +++ b/test/UnitTest.cs @@ -68,6 +68,7 @@ namespace test private void RunEncryptionRound(IEncryptor encryptor, IEncryptor decryptor) { + RNG.Reload(); byte[] plain = new byte[16384]; byte[] cipher = new byte[plain.Length + 16 + IVEncryptor.ONETIMEAUTH_BYTES + IVEncryptor.AUTH_BYTES]; byte[] plain2 = new byte[plain.Length + 16]; @@ -117,6 +118,7 @@ namespace test { t.Join(); } + RNG.Close(); Assert.IsFalse(encryptionFailed); } @@ -156,6 +158,7 @@ namespace test { t.Join(); } + RNG.Close(); Assert.IsFalse(encryptionFailed); } @@ -196,6 +199,7 @@ namespace test { t.Join(); } + RNG.Close(); Assert.IsFalse(encryptionFailed); }