You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

PolarSSLEncryptor.cs 6.0 kB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Runtime.InteropServices;
  4. using System.Security.Cryptography;
  5. using System.Text;
  6. using System.Threading;
  7. namespace Shadowsocks.Encryption
  8. {
  9. public class PolarSSLEncryptor
  10. : IVEncryptor, IDisposable
  11. {
  12. const int CIPHER_AES = 1;
  13. const int CIPHER_RC4 = 2;
  14. private IntPtr _encryptCtx = IntPtr.Zero;
  15. private IntPtr _decryptCtx = IntPtr.Zero;
  16. public PolarSSLEncryptor(string method, string password, bool onetimeauth)
  17. : base(method, password, onetimeauth)
  18. {
  19. InitKey(method, password);
  20. }
  21. private static Dictionary<string, int[]> _ciphers = new Dictionary<string, int[]> {
  22. {"aes-128-cfb", new int[]{16, 16, CIPHER_AES, PolarSSL.AES_CTX_SIZE}},
  23. {"aes-192-cfb", new int[]{24, 16, CIPHER_AES, PolarSSL.AES_CTX_SIZE}},
  24. {"aes-256-cfb", new int[]{32, 16, CIPHER_AES, PolarSSL.AES_CTX_SIZE}},
  25. {"rc4", new int[]{16, 0, CIPHER_RC4, PolarSSL.ARC4_CTX_SIZE}},
  26. {"rc4-md5", new int[]{16, 16, CIPHER_RC4, PolarSSL.ARC4_CTX_SIZE}},
  27. };
  28. public static List<string> SupportedCiphers()
  29. {
  30. return new List<string>(_ciphers.Keys);
  31. }
  32. protected override Dictionary<string, int[]> getCiphers()
  33. {
  34. return _ciphers;
  35. }
  36. protected override void initCipher(byte[] iv, bool isCipher)
  37. {
  38. base.initCipher(iv, isCipher);
  39. IntPtr ctx;
  40. ctx = Marshal.AllocHGlobal(_cipherInfo[3]);
  41. if (isCipher)
  42. {
  43. _encryptCtx = ctx;
  44. }
  45. else
  46. {
  47. _decryptCtx = ctx;
  48. }
  49. byte[] realkey;
  50. if (_method == "rc4-md5")
  51. {
  52. byte[] temp = new byte[keyLen + ivLen];
  53. realkey = new byte[keyLen];
  54. Array.Copy(_key, 0, temp, 0, keyLen);
  55. Array.Copy(iv, 0, temp, keyLen, ivLen);
  56. realkey = MD5.Create().ComputeHash(temp);
  57. }
  58. else
  59. {
  60. realkey = _key;
  61. }
  62. if (_cipher == CIPHER_AES)
  63. {
  64. PolarSSL.aes_init(ctx);
  65. // PolarSSL takes key length by bit
  66. // since we'll use CFB mode, here we both do enc, not dec
  67. PolarSSL.aes_setkey_enc(ctx, realkey, keyLen * 8);
  68. }
  69. else if (_cipher == CIPHER_RC4)
  70. {
  71. PolarSSL.arc4_init(ctx);
  72. // PolarSSL RC4 takes key length by byte
  73. PolarSSL.arc4_setup(ctx, realkey, keyLen);
  74. }
  75. }
  76. protected override void cipherUpdate(bool isCipher, int length, byte[] buf, byte[] outbuf)
  77. {
  78. // C# could be multi-threaded
  79. if (_disposed)
  80. {
  81. throw new ObjectDisposedException(this.ToString());
  82. }
  83. byte[] iv;
  84. int ivOffset;
  85. IntPtr ctx;
  86. if (isCipher)
  87. {
  88. iv = _encryptIV;
  89. ivOffset = _encryptIVOffset;
  90. ctx = _encryptCtx;
  91. }
  92. else
  93. {
  94. iv = _decryptIV;
  95. ivOffset = _decryptIVOffset;
  96. ctx = _decryptCtx;
  97. }
  98. switch (_cipher)
  99. {
  100. case CIPHER_AES:
  101. PolarSSL.aes_crypt_cfb128(ctx, isCipher ? PolarSSL.AES_ENCRYPT : PolarSSL.AES_DECRYPT, length, ref ivOffset, iv, buf, outbuf);
  102. if (isCipher)
  103. {
  104. _encryptIVOffset = ivOffset;
  105. }
  106. else
  107. {
  108. _decryptIVOffset = ivOffset;
  109. }
  110. break;
  111. case CIPHER_RC4:
  112. PolarSSL.arc4_crypt(ctx, length, buf, outbuf);
  113. break;
  114. }
  115. }
  116. #region IDisposable
  117. private bool _disposed;
  118. public override void Dispose()
  119. {
  120. Dispose(true);
  121. GC.SuppressFinalize(this);
  122. }
  123. ~PolarSSLEncryptor()
  124. {
  125. Dispose(false);
  126. }
  127. protected virtual void Dispose(bool disposing)
  128. {
  129. lock (this)
  130. {
  131. if (_disposed)
  132. {
  133. return;
  134. }
  135. _disposed = true;
  136. }
  137. if (disposing)
  138. {
  139. if (_encryptCtx != IntPtr.Zero)
  140. {
  141. switch (_cipher)
  142. {
  143. case CIPHER_AES:
  144. PolarSSL.aes_free(_encryptCtx);
  145. break;
  146. case CIPHER_RC4:
  147. PolarSSL.arc4_free(_encryptCtx);
  148. break;
  149. }
  150. Marshal.FreeHGlobal(_encryptCtx);
  151. _encryptCtx = IntPtr.Zero;
  152. }
  153. if (_decryptCtx != IntPtr.Zero)
  154. {
  155. switch (_cipher)
  156. {
  157. case CIPHER_AES:
  158. PolarSSL.aes_free(_decryptCtx);
  159. break;
  160. case CIPHER_RC4:
  161. PolarSSL.arc4_free(_decryptCtx);
  162. break;
  163. }
  164. Marshal.FreeHGlobal(_decryptCtx);
  165. _decryptCtx = IntPtr.Zero;
  166. }
  167. }
  168. }
  169. #endregion
  170. }
  171. }