1. using System;
  2. using System.Collections;
  3. using System.Runtime.InteropServices;
  4. using System.Security.Cryptography;
  5. namespace Framework.Cryptography
  6. {
  7. public class SRP6
  8. {
  9. static HashAlgorithm hashAlgorithm = new SHA1Managed();
  10. IntPtr BNA, BNa, BNb, BNB, BNg, BNk, BNn, BNS, BNU, BNv, BNx;
  11. public byte[] K, M, N, S, salt, U;
  12. public byte[] A = new byte[0x20];
  13. public byte[] a = new byte[0x14];
  14. public byte[] b = new byte[0x14];
  15. public byte[] B = new byte[0x20];
  16. public byte[] g = new byte[] { 0x07 };
  17. public byte[] k = new byte[] { 0x03 };
  18. public string Username, Password;
  19. public SRP6()
  20. {
  21. N = new byte[] { 0x89, 0x4B, 0x64, 0x5E, 0x89, 0xE1, 0x53, 0x5B, 0xBD, 0xAD, 0x5B, 0x8B, 0x29, 0x06, 0x50, 0x53,
  22. 0x08, 0x01, 0xB1, 0x8E, 0xBF, 0xBF, 0x5E, 0x8F, 0xAB, 0x3C, 0x82, 0x87, 0x2A, 0x3E, 0x9B, 0xB7 };
  23. }
  24. [DllImport("libeay32.dll", CallingConvention = CallingConvention.Cdecl)]
  25. private static extern int BN_add(IntPtr r, IntPtr a, IntPtr b);
  26. [DllImport("libeay32.dll", EntryPoint = "BN_bin2bn", CallingConvention = CallingConvention.Cdecl)]
  27. private static extern IntPtr BN_Bin2BN(byte[] ByteArrayIn, int length, IntPtr to);
  28. [DllImport("libeay32.dll", CallingConvention = CallingConvention.Cdecl)]
  29. private static extern int BN_bn2bin(IntPtr a, byte[] to);
  30. [DllImport("libeay32.dll", EntryPoint = "BN_CTX_free", CallingConvention = CallingConvention.Cdecl)]
  31. private static extern int BN_ctx_free(IntPtr a);
  32. [DllImport("libeay32.dll", EntryPoint = "BN_CTX_new", CallingConvention = CallingConvention.Cdecl)]
  33. private static extern IntPtr BN_ctx_new();
  34. [DllImport("libeay32.dll", CallingConvention = CallingConvention.Cdecl)]
  35. private static extern int BN_div(IntPtr dv, IntPtr r, IntPtr a, IntPtr b, IntPtr ctx);
  36. [DllImport("libeay32.dll", EntryPoint = "BN_free", CallingConvention = CallingConvention.Cdecl)]
  37. private static extern void BN_Free(IntPtr r);
  38. [DllImport("libeay32.dll", CallingConvention = CallingConvention.Cdecl)]
  39. private static extern IntPtr BN_mod_exp(IntPtr res, IntPtr a, IntPtr p, IntPtr m, IntPtr ctx);
  40. [DllImport("libeay32.dll", CallingConvention = CallingConvention.Cdecl)]
  41. private static extern int BN_mul(IntPtr r, IntPtr a, IntPtr b, IntPtr ctx);
  42. [DllImport("libeay32.dll", CallingConvention = CallingConvention.Cdecl)]
  43. private static extern int BN_sub(IntPtr r, IntPtr a, IntPtr b);
  44. [DllImport("libeay32.dll", EntryPoint = "BN_new", CallingConvention=CallingConvention.Cdecl)]
  45. private static extern IntPtr BN_New();
  46. public void SetB(byte[] data)
  47. {
  48. this.B = data;
  49. Array.Reverse(this.B);
  50. this.BNB = BN_Bin2BN(this.B, this.B.Length, IntPtr.Zero);
  51. Array.Reverse(this.B);
  52. }
  53. public void CalculateG()
  54. {
  55. Array.Reverse(this.g);
  56. this.BNg = BN_Bin2BN(this.g, this.g.Length, IntPtr.Zero);
  57. Array.Reverse(this.g);
  58. }
  59. public void CalculateN()
  60. {
  61. Array.Reverse(this.N);
  62. this.BNn = BN_Bin2BN(this.N, this.N.Length, IntPtr.Zero);
  63. Array.Reverse(this.N);
  64. }
  65. public void Calculatek()
  66. {
  67. Array.Reverse(this.k);
  68. this.BNk = BN_Bin2BN(this.k, this.k.Length, IntPtr.Zero);
  69. Array.Reverse(this.k);
  70. }
  71. public void CalculateA()
  72. {
  73. RAND_bytes(this.a, 20);
  74. Array.Reverse(this.a);
  75. this.BNa = BN_Bin2BN(this.a, this.a.Length, IntPtr.Zero);
  76. Array.Reverse(this.a);
  77. IntPtr res = BN_New();
  78. IntPtr r = BN_New();
  79. IntPtr ptr3 = BN_New();
  80. this.BNA = BN_New();
  81. IntPtr ctx = BN_ctx_new();
  82. BN_mod_exp(res, this.BNg, this.BNa, this.BNn, ctx);
  83. BN_mul(r, this.BNk, this.BNv, ctx);
  84. BN_add(ptr3, res, r);
  85. BN_div(IntPtr.Zero, this.BNA, ptr3, this.BNn, ctx);
  86. BN_bn2bin(this.BNA, this.A);
  87. Array.Reverse(this.A);
  88. BN_ctx_free(ctx);
  89. BN_Free(ptr3);
  90. BN_Free(r);
  91. BN_Free(res);
  92. }
  93. public void CalculateK()
  94. {
  95. ArrayList list = Split(this.S);
  96. list[0] = hashAlgorithm.ComputeHash((byte[])list[0]);
  97. list[1] = hashAlgorithm.ComputeHash((byte[])list[1]);
  98. this.K = Combine((byte[])list[0], (byte[])list[1]);
  99. }
  100. public void CalculateM()
  101. {
  102. byte[] dst = new byte[this.S.Length + this.A.Length + this.B.Length + this.K.Length];
  103. Buffer.BlockCopy(this.S, 0, dst, 0, this.S.Length);
  104. Buffer.BlockCopy(this.A, 0, dst, this.S.Length, this.A.Length);
  105. Buffer.BlockCopy(this.B, 0, dst, this.S.Length + this.A.Length, this.B.Length);
  106. Buffer.BlockCopy(this.K, 0, dst, this.S.Length + this.A.Length + this.B.Length, this.K.Length);
  107. this.M = hashAlgorithm.ComputeHash(dst);
  108. }
  109. public void CalculateS()
  110. {
  111. IntPtr res = BN_New();
  112. IntPtr r = BN_New();
  113. IntPtr r1 = BN_New();
  114. IntPtr r2 = BN_New();
  115. IntPtr r3 = BN_New();
  116. IntPtr r4 = BN_New();
  117. IntPtr r5 = BN_New();
  118. this.BNS = BN_New();
  119. IntPtr ctx = BN_ctx_new();
  120. this.S = new byte[0x20];
  121. BN_mod_exp(res, this.BNg, this.BNx, this.BNn, ctx);
  122. BN_div(IntPtr.Zero, r, res, this.BNn, ctx);
  123. BN_mul(r1, this.BNk, res, ctx);
  124. BN_sub(r2, this.BNB, r1);
  125. BN_mul(r3, this.BNU, this.BNx, ctx);
  126. BN_add(r4, this.BNa, r3);
  127. BN_mod_exp(r5, r2, r4, this.BNn, ctx);
  128. BN_div(IntPtr.Zero, this.BNS, r5, this.BNn, ctx);
  129. BN_bn2bin(this.BNS, this.S);
  130. Array.Reverse(this.S);
  131. BN_ctx_free(ctx);
  132. BN_Free(r);
  133. BN_Free(r1);
  134. BN_Free(r2);
  135. BN_Free(r3);
  136. BN_Free(r4);
  137. BN_Free(r5);
  138. BN_Free(res);
  139. }
  140. public void CalculateU()
  141. {
  142. byte[] dst = new byte[this.A.Length + this.B.Length];
  143. Buffer.BlockCopy(this.A, 0, dst, 0, this.A.Length);
  144. Buffer.BlockCopy(this.B, 0, dst, a.Length, this.B.Length);
  145. this.U = hashAlgorithm.ComputeHash(dst);
  146. Array.Reverse(this.U);
  147. this.BNU = BN_Bin2BN(this.U, this.U.Length, IntPtr.Zero);
  148. Array.Reverse(this.U);
  149. }
  150. public void CalculateV()
  151. {
  152. this.BNv = BN_New();
  153. IntPtr ctx = BN_ctx_new();
  154. BN_mod_exp(this.BNv, this.BNg, this.BNx, this.BNn, ctx);
  155. BN_ctx_free(ctx);
  156. }
  157. public void CalculateX(byte[] username, byte[] password)
  158. {
  159. byte[] dst = new byte[this.salt.Length + password.Length];
  160. Buffer.BlockCopy(this.salt, 0, dst, 0, this.salt.Length);
  161. Buffer.BlockCopy(password, 0, dst, this.salt.Length, password.Length);
  162. byte[] buffer5 = hashAlgorithm.ComputeHash(dst, 0, dst.Length);
  163. Array.Reverse(buffer5);
  164. this.BNx = BN_Bin2BN(buffer5, buffer5.Length, IntPtr.Zero);
  165. }
  166. private static byte[] Combine(byte[] b1, byte[] b2)
  167. {
  168. if (b1.Length != b2.Length)
  169. {
  170. return null;
  171. }
  172. byte[] buffer = new byte[b1.Length + b2.Length];
  173. int index = 0;
  174. int num2 = 1;
  175. for (int i = 0; i < b1.Length; i++)
  176. {
  177. buffer[index] = b1[i];
  178. index++;
  179. index++;
  180. }
  181. for (int j = 0; j < b2.Length; j++)
  182. {
  183. buffer[num2] = b2[j];
  184. num2++;
  185. num2++;
  186. }
  187. return buffer;
  188. }
  189. ~SRP6()
  190. {
  191. BN_Free(this.BNA);
  192. BN_Free(this.BNb);
  193. BN_Free(this.BNB);
  194. BN_Free(this.BNg);
  195. BN_Free(this.BNk);
  196. BN_Free(this.BNn);
  197. BN_Free(this.BNS);
  198. BN_Free(this.BNU);
  199. BN_Free(this.BNv);
  200. BN_Free(this.BNx);
  201. }
  202. [DllImport("libeay32.dll", CallingConvention = CallingConvention.Cdecl)]
  203. public static extern int RAND_bytes(byte[] buf, int num);
  204. private static ArrayList Split(byte[] bo)
  205. {
  206. byte[] dst = new byte[bo.Length - 1];
  207. if (((bo.Length % 2) != 0) && (bo.Length > 2))
  208. {
  209. Buffer.BlockCopy(bo, 1, dst, 0, bo.Length);
  210. }
  211. byte[] buffer2 = new byte[bo.Length / 2];
  212. byte[] buffer3 = new byte[bo.Length / 2];
  213. int index = 0;
  214. int num2 = 1;
  215. for (int i = 0; i < buffer2.Length; i++)
  216. {
  217. buffer2[i] = bo[index];
  218. index++;
  219. index++;
  220. }
  221. for (int j = 0; j < buffer3.Length; j++)
  222. {
  223. buffer3[j] = bo[num2];
  224. num2++;
  225. num2++;
  226. }
  227. ArrayList list = new ArrayList();
  228. list.Add(buffer2);
  229. list.Add(buffer3);
  230. return list;
  231. }
  232. }
  233. }