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