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.

StreamNativeEncryptor.cs 6.3 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. namespace Shadowsocks.Encryption.Stream
  7. {
  8. public class StreamNativeEncryptor : StreamEncryptor
  9. {
  10. const int Plain = 0;
  11. const int Table = 1;
  12. const int Rc4 = 2;
  13. const int Rc4Md5 = 3;
  14. string _password;
  15. byte[] realkey;
  16. byte[] sbox;
  17. public StreamNativeEncryptor(string method, string password) : base(method, password)
  18. {
  19. _password = password;
  20. }
  21. public override void Dispose()
  22. {
  23. return;
  24. }
  25. protected override void initCipher(byte[] iv, bool isEncrypt)
  26. {
  27. base.initCipher(iv, isEncrypt);
  28. if (_cipher >= Rc4)
  29. {
  30. if (_cipher == Rc4Md5)
  31. {
  32. byte[] temp = new byte[keyLen + ivLen];
  33. Array.Copy(_key, 0, temp, 0, keyLen);
  34. Array.Copy(iv, 0, temp, keyLen, ivLen);
  35. realkey = CryptoUtils.MD5(temp);
  36. }
  37. else
  38. {
  39. realkey = _key;
  40. }
  41. sbox = SBox(realkey);
  42. }
  43. else if (_cipher == Table)
  44. {
  45. ulong a = BitConverter.ToUInt64(CryptoUtils.MD5(Encoding.UTF8.GetBytes(_password)), 0);
  46. for (int i = 0; i < 256; i++)
  47. {
  48. _encryptTable[i] = (byte)i;
  49. }
  50. for (int i = 1; i < 1024; i++)
  51. {
  52. _encryptTable = MergeSort(_encryptTable, a, i);
  53. }
  54. for (int i = 0; i < 256; i++)
  55. {
  56. _decryptTable[_encryptTable[i]] = (byte)i;
  57. }
  58. }
  59. }
  60. protected override void cipherUpdate(bool isEncrypt, int length, byte[] buf, byte[] outbuf)
  61. {
  62. if (_cipher == Table)
  63. {
  64. var table = isEncrypt ? _encryptTable : _decryptTable;
  65. for (int i = 0; i < length; i++)
  66. {
  67. outbuf[i] = table[buf[i]];
  68. }
  69. }
  70. else if (_cipher == Plain)
  71. {
  72. Array.Copy(buf, outbuf, length);
  73. }
  74. else
  75. {
  76. var ctx = isEncrypt ? enc_ctx : dec_ctx;
  77. byte[] t = new byte[length];
  78. Array.Copy(buf, t, length);
  79. RC4(ctx, sbox, t, length);
  80. Array.Copy(t, outbuf, length);
  81. }
  82. }
  83. private static readonly Dictionary<string, EncryptorInfo> _ciphers = new Dictionary<string, EncryptorInfo>
  84. {
  85. {"plain", new EncryptorInfo("PLAIN", 0, 0, Plain) },
  86. {"table", new EncryptorInfo("TABLE", 0, 0, Table) },
  87. { "rc4", new EncryptorInfo("RC4", 16, 0, Rc4) }, // original RC4 doesn't use IV
  88. { "rc4-md5", new EncryptorInfo("RC4", 16, 16, Rc4Md5) },
  89. };
  90. public static IEnumerable<string> SupportedCiphers()
  91. {
  92. return _ciphers.Keys;
  93. }
  94. protected override Dictionary<string, EncryptorInfo> getCiphers()
  95. {
  96. return _ciphers;
  97. }
  98. #region Table
  99. private byte[] _encryptTable = new byte[256];
  100. private byte[] _decryptTable = new byte[256];
  101. private static long Compare(byte x, byte y, ulong a, int i)
  102. {
  103. return (long)(a % (ulong)(x + i)) - (long)(a % (ulong)(y + i));
  104. }
  105. private byte[] MergeSort(byte[] array, ulong a, int j)
  106. {
  107. if (array.Length == 1)
  108. {
  109. return array;
  110. }
  111. int middle = array.Length / 2;
  112. byte[] left = new byte[middle];
  113. for (int i = 0; i < middle; i++)
  114. {
  115. left[i] = array[i];
  116. }
  117. byte[] right = new byte[array.Length - middle];
  118. for (int i = 0; i < array.Length - middle; i++)
  119. {
  120. right[i] = array[i + middle];
  121. }
  122. left = MergeSort(left, a, j);
  123. right = MergeSort(right, a, j);
  124. int leftptr = 0;
  125. int rightptr = 0;
  126. byte[] sorted = new byte[array.Length];
  127. for (int k = 0; k < array.Length; k++)
  128. {
  129. if (rightptr == right.Length || ((leftptr < left.Length) && (Compare(left[leftptr], right[rightptr], a, j) <= 0)))
  130. {
  131. sorted[k] = left[leftptr];
  132. leftptr++;
  133. }
  134. else if (leftptr == left.Length || ((rightptr < right.Length) && (Compare(right[rightptr], left[leftptr], a, j)) <= 0))
  135. {
  136. sorted[k] = right[rightptr];
  137. rightptr++;
  138. }
  139. }
  140. return sorted;
  141. }
  142. #endregion
  143. #region RC4
  144. class Context
  145. {
  146. public int index1 = 0;
  147. public int index2 = 0;
  148. }
  149. private Context enc_ctx = new Context();
  150. private Context dec_ctx = new Context();
  151. private byte[] SBox(byte[] key)
  152. {
  153. byte[] s = new byte[256];
  154. for (int i = 0; i < 256; i++)
  155. {
  156. s[i] = (byte)i;
  157. }
  158. for (int i = 0, j = 0; i < 256; i++)
  159. {
  160. j = (j + key[i % key.Length] + s[i]) & 255;
  161. Swap(s, i, j);
  162. }
  163. return s;
  164. }
  165. private void RC4(Context ctx, byte[] s, byte[] data, int length)
  166. {
  167. for (int n = 0; n < length; n++)
  168. {
  169. byte b = data[n];
  170. ctx.index1 = (ctx.index1 + 1) & 255;
  171. ctx.index2 = (ctx.index2 + s[ctx.index1]) & 255;
  172. Swap(s, ctx.index1, ctx.index2);
  173. data[n] = (byte)(b ^ s[(s[ctx.index1] + s[ctx.index2]) & 255]);
  174. }
  175. }
  176. private static void Swap(byte[] s, int i, int j)
  177. {
  178. byte c = s[i];
  179. s[i] = s[j];
  180. s[j] = c;
  181. }
  182. #endregion
  183. }
  184. }