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 5.9 kB

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