RealmSession.cs 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. using System;
  2. using System.Security.Cryptography;
  3. using System.Threading.Tasks;
  4. using BossBase;
  5. using Helper;
  6. using Log;
  7. namespace BossClient
  8. {
  9. public class RealmSession: IDisposable
  10. {
  11. public int ID { get; set; }
  12. public IMessageChannel MessageChannel { get; set; }
  13. public RealmSession(int id, IMessageChannel messageChannel)
  14. {
  15. this.ID = id;
  16. this.MessageChannel = messageChannel;
  17. }
  18. public void Dispose()
  19. {
  20. this.MessageChannel.Dispose();
  21. }
  22. public async Task<SMSG_Password_Protect_Type> Handle_SMSG_Password_Protect_Type()
  23. {
  24. var result = await this.MessageChannel.RecvMessage();
  25. ushort opcode = result.Item1;
  26. byte[] message = result.Item2;
  27. if (opcode != MessageOpcode.SMSG_PASSWORD_PROTECT_TYPE)
  28. {
  29. throw new BossException(string.Format(
  30. "session: {0}, opcode: {1}", this.ID, opcode));
  31. }
  32. var smsgPasswordProtectType =
  33. ProtobufHelper.FromBytes<SMSG_Password_Protect_Type>(message);
  34. return smsgPasswordProtectType;
  35. }
  36. public async Task<SMSG_Auth_Logon_Challenge_Response>
  37. Handle_SMSG_Auth_Logon_Challenge_Response()
  38. {
  39. var result = await this.MessageChannel.RecvMessage();
  40. ushort opcode = result.Item1;
  41. byte[] message = result.Item2;
  42. if (opcode != MessageOpcode.SMSG_AUTH_LOGON_CHALLENGE_RESPONSE)
  43. {
  44. Logger.Trace("opcode: {0}", opcode);
  45. throw new BossException(string.Format(
  46. "session: {0}, opcode: {1}", this.ID, opcode));
  47. }
  48. var smsgAuthLogonChallengeResponse =
  49. ProtobufHelper.FromBytes<SMSG_Auth_Logon_Challenge_Response>(message);
  50. return smsgAuthLogonChallengeResponse;
  51. }
  52. public async Task<SMSG_Auth_Logon_Proof_M2> Handle_SMSG_Auth_Logon_Proof_M2()
  53. {
  54. var result = await this.MessageChannel.RecvMessage();
  55. ushort opcode = result.Item1;
  56. byte[] message = result.Item2;
  57. if (opcode != MessageOpcode.SMSG_AUTH_LOGON_PROOF_M2)
  58. {
  59. throw new BossException(string.Format(
  60. "session: {0}, error opcode: {1}", this.ID, opcode));
  61. }
  62. var smsgAuthLogonProofM2 = ProtobufHelper.FromBytes<SMSG_Auth_Logon_Proof_M2>(message);
  63. return smsgAuthLogonProofM2;
  64. }
  65. public async Task<SMSG_Realm_List> Handle_SMSG_Realm_List()
  66. {
  67. var result = await this.MessageChannel.RecvMessage();
  68. ushort opcode = result.Item1;
  69. byte[] message = result.Item2;
  70. if (opcode != MessageOpcode.SMSG_REALM_LIST)
  71. {
  72. throw new BossException(string.Format(
  73. "session: {0}, error opcode: {1}", this.ID, opcode));
  74. }
  75. var smsgRealmList = ProtobufHelper.FromBytes<SMSG_Realm_List>(message);
  76. return smsgRealmList;
  77. }
  78. public async Task<Tuple<string, ushort, SRP6Client>> Login(string account, string password)
  79. {
  80. byte[] passwordBytes = password.ToByteArray();
  81. MD5 md5 = MD5.Create();
  82. byte[] passwordMd5 = md5.ComputeHash(passwordBytes);
  83. byte[] passwordMd5Hex = passwordMd5.ToHex().ToLower().ToByteArray();
  84. // 发送帐号和密码MD5
  85. var cmsgAuthLogonPermit = new CMSG_Auth_Logon_Permit
  86. {
  87. Account = account.ToByteArray(),
  88. PasswordMd5 = passwordMd5Hex
  89. };
  90. Logger.Trace("session: {0}, account: {1}, password: {2}", this.ID,
  91. cmsgAuthLogonPermit.Account.ToStr(), cmsgAuthLogonPermit.PasswordMd5.ToHex());
  92. this.MessageChannel.SendMessage(MessageOpcode.CMSG_AUTH_LOGON_PERMIT, cmsgAuthLogonPermit);
  93. var smsgPasswordProtectType = await this.Handle_SMSG_Password_Protect_Type();
  94. if (smsgPasswordProtectType.Code != 200)
  95. {
  96. throw new BossException(string.Format(
  97. "session: {0}, SMSG_Password_Protect_Type: {1}",
  98. this.ID, JsonHelper.ToString(smsgPasswordProtectType)));
  99. }
  100. // 这个消息已经没有作用,只用来保持原有的代码流程
  101. var cmsgAuthLogonChallenge = new CMSG_Auth_Logon_Challenge();
  102. this.MessageChannel.SendMessage(
  103. MessageOpcode.CMSG_AUTH_LOGON_CHALLENGE, cmsgAuthLogonChallenge);
  104. var smsgAuthLogonChallengeResponse =
  105. await this.Handle_SMSG_Auth_Logon_Challenge_Response();
  106. if (smsgAuthLogonChallengeResponse.ErrorCode != ErrorCode.REALM_AUTH_SUCCESS)
  107. {
  108. throw new BossException(
  109. string.Format("session: {0}, SMSG_Auth_Logon_Challenge_Response: {1}",
  110. this.ID, JsonHelper.ToString(smsgAuthLogonChallengeResponse)));
  111. }
  112. Logger.Trace("session: {0}, SMSG_Auth_Logon_Challenge_Response OK", this.ID);
  113. // 以下是SRP6处理过程
  114. var n = smsgAuthLogonChallengeResponse.N.ToUBigInteger();
  115. var g = smsgAuthLogonChallengeResponse.G.ToUBigInteger();
  116. var b = smsgAuthLogonChallengeResponse.B.ToUBigInteger();
  117. var salt = smsgAuthLogonChallengeResponse.S.ToUBigInteger();
  118. var srp6Client = new SRP6Client(
  119. new SHA1Managed(), n, g, b, salt, account.ToByteArray(), passwordMd5Hex);
  120. Logger.Debug("s: {0}\nN: {1}\nG: {2}\nB: {3}\nA: {4}\nS: {5}\nK: {6}\nm: {7}\na: {8}",
  121. srp6Client.Salt.ToUBigIntegerArray().ToHex(),
  122. srp6Client.N.ToUBigIntegerArray().ToHex(),
  123. srp6Client.G.ToUBigIntegerArray().ToHex(),
  124. srp6Client.B.ToUBigIntegerArray().ToHex(),
  125. srp6Client.A.ToUBigIntegerArray().ToHex(),
  126. srp6Client.S.ToUBigIntegerArray().ToHex(),
  127. srp6Client.K.ToUBigIntegerArray().ToHex(),
  128. srp6Client.M.ToUBigIntegerArray().ToHex(),
  129. srp6Client.SmallA.ToUBigIntegerArray().ToHex());
  130. var cmsgAuthLogonProof = new CMSG_Auth_Logon_Proof
  131. {
  132. A = srp6Client.A.ToUBigIntegerArray(),
  133. M = srp6Client.M.ToUBigIntegerArray()
  134. };
  135. this.MessageChannel.SendMessage(MessageOpcode.CMSG_AUTH_LOGON_PROOF, cmsgAuthLogonProof);
  136. var smsgAuthLogonProofM2 = await this.Handle_SMSG_Auth_Logon_Proof_M2();
  137. if (smsgAuthLogonProofM2.ErrorCode != ErrorCode.REALM_AUTH_SUCCESS)
  138. {
  139. throw new BossException(string.Format(
  140. "session: {0}, SMSG_Auth_Logon_Proof_M2: {1}",
  141. this.ID, JsonHelper.ToString(smsgAuthLogonProofM2)));
  142. }
  143. Logger.Trace("session: {0}, SMSG_Auth_Logon_Proof_M2 OK", this.ID);
  144. // 请求realm list
  145. var cmsgRealmList = new CMSG_Realm_List();
  146. this.MessageChannel.SendMessage(MessageOpcode.CMSG_REALM_LIST, cmsgRealmList);
  147. var smsgRealmList = await this.Handle_SMSG_Realm_List();
  148. Logger.Trace("session: {0}, SMSG_Realm_List OK", this.ID);
  149. string gateIP = smsgRealmList.GateIP;
  150. ushort gatePort = (ushort)smsgRealmList.GatePort;
  151. return Tuple.Create(gateIP, gatePort, srp6Client);
  152. }
  153. }
  154. }