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.5 kB

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