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.

StreamRc4NativeEncryptor.cs 3.3 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  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 StreamRc4NativeEncryptor : StreamEncryptor
  9. {
  10. const int Rc4 = 0;
  11. const int Rc4Md5 = 1;
  12. string _password;
  13. byte[] realkey;
  14. byte[] sbox;
  15. public StreamRc4NativeEncryptor(string method, string password) : base(method, password)
  16. {
  17. _password = password;
  18. }
  19. public override void Dispose()
  20. {
  21. return;
  22. }
  23. protected override void initCipher(byte[] iv, bool isEncrypt)
  24. {
  25. base.initCipher(iv, isEncrypt);
  26. if (_cipher == Rc4Md5)
  27. {
  28. byte[] temp = new byte[keyLen + ivLen];
  29. Array.Copy(_key, 0, temp, 0, keyLen);
  30. Array.Copy(iv, 0, temp, keyLen, ivLen);
  31. realkey = CryptoUtils.MD5(temp);
  32. }
  33. else
  34. {
  35. realkey = _key;
  36. }
  37. sbox = SBox(realkey);
  38. }
  39. protected override void cipherUpdate(bool isEncrypt, int length, byte[] buf, byte[] outbuf)
  40. {
  41. var ctx = isEncrypt ? enc_ctx : dec_ctx;
  42. byte[] t = new byte[length];
  43. Array.Copy(buf, t, length);
  44. RC4(ctx, sbox, t, length);
  45. Array.Copy(t, outbuf, length);
  46. }
  47. private static readonly Dictionary<string, EncryptorInfo> _ciphers = new Dictionary<string, EncryptorInfo>
  48. {
  49. // original RC4 doesn't use IV
  50. { "rc4", new EncryptorInfo("RC4", 16, 0, Rc4) },
  51. { "rc4-md5", new EncryptorInfo("RC4", 16, 16, Rc4Md5) },
  52. };
  53. public static IEnumerable<string> SupportedCiphers()
  54. {
  55. return _ciphers.Keys;
  56. }
  57. protected override Dictionary<string, EncryptorInfo> getCiphers()
  58. {
  59. return _ciphers;
  60. }
  61. #region RC4
  62. class Context
  63. {
  64. public int index1 = 0;
  65. public int index2 = 0;
  66. }
  67. private Context enc_ctx = new Context();
  68. private Context dec_ctx = new Context();
  69. private byte[] SBox(byte[] key)
  70. {
  71. byte[] s = new byte[256];
  72. for (int i = 0; i < 256; i++)
  73. {
  74. s[i] = (byte)i;
  75. }
  76. for (int i = 0, j = 0; i < 256; i++)
  77. {
  78. j = (j + key[i % key.Length] + s[i]) & 255;
  79. Swap(s, i, j);
  80. }
  81. return s;
  82. }
  83. private void RC4(Context ctx, byte[] s, byte[] data, int length)
  84. {
  85. for (int n = 0; n < length; n++)
  86. {
  87. byte b = data[n];
  88. ctx.index1 = (ctx.index1 + 1) & 255;
  89. ctx.index2 = (ctx.index2 + s[ctx.index1]) & 255;
  90. Swap(s, ctx.index1, ctx.index2);
  91. data[n] = (byte)(b ^ s[(s[ctx.index1] + s[ctx.index2]) & 255]);
  92. }
  93. }
  94. private static void Swap(byte[] s, int i, int j)
  95. {
  96. byte c = s[i];
  97. s[i] = s[j];
  98. s[j] = c;
  99. }
  100. #endregion
  101. }
  102. }