Przeglądaj źródła

SRP6联调通过!

tanghai 13 lat temu
rodzic
commit
02a4acebc4

+ 1 - 0
CSharp/App/Modules/Robot/Packages.config

@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <packages>
+  <package id="BouncyCastle" version="1.7.0" targetFramework="net45" />
   <package id="CommonServiceLocator" version="1.0" targetFramework="net45" />
   <package id="Prism" version="4.1.0.0" targetFramework="net45" />
   <package id="Prism.MEFExtensions" version="4.1.0.0" targetFramework="net45" />

+ 0 - 6
CSharp/App/Modules/Robot/Protos/Messages.cs

@@ -127,12 +127,6 @@ namespace Robot.Protos
 
 		[DataMember(Order = 5, IsRequired = true)]
 		public byte[] S { get; set; }
-
-		[DataMember(Order = 6, IsRequired = true)]
-		public byte[] Unk3 { get; set; }
-
-		[DataMember(Order = 7, IsRequired = true)]
-		public uint SecurityFlags { get; set; }
 	}
 
 	[DataContract]

+ 26 - 16
CSharp/App/Modules/Robot/RealmSession.cs

@@ -79,6 +79,8 @@ namespace Robot
 				Logger.Trace("opcode: {0}", opcode);
 			}
 
+			Logger.Trace("message: {0}", message.ToHex());
+
 			var smsgAuthLogonChallengeResponse =
 				ProtobufHelper.FromBytes<SMSG_Auth_Logon_Challenge_Response>(message);
 
@@ -90,6 +92,9 @@ namespace Robot
 					JsonHelper.ToString(smsgAuthLogonChallengeResponse)));
 			}
 
+			Logger.Debug("SMSG_Auth_Logon_Challenge_Response: \n{0}", 
+				JsonHelper.ToString(smsgAuthLogonChallengeResponse));
+
 			return smsgAuthLogonChallengeResponse;
 		}
 
@@ -149,12 +154,13 @@ namespace Robot
 			byte[] passwordBytes = password.ToByteArray();
 			MD5 md5 = MD5.Create();
 			byte[] passwordMd5 = md5.ComputeHash(passwordBytes);
+			byte[] passwordMd5Hex = passwordMd5.ToHex().ToLower().ToByteArray();
 
 			// 发送帐号和密码MD5
 			var cmsgAuthLogonPermit = new CMSG_Auth_Logon_Permit
 			{ 
 				Account = account.ToByteArray(),
-				PasswordMd5 = passwordMd5.ToHex().ToLower().ToByteArray()
+				PasswordMd5 = passwordMd5Hex
 			};
 
 			Logger.Trace("account: {0}, password: {1}", 
@@ -170,24 +176,28 @@ namespace Robot
 				await this.Handle_SMSG_Auth_Logon_Challenge_Response();
 
 			// 以下是SRP6处理过程
-			var n = smsgAuthLogonChallengeResponse.N.ToUnsignedBigInteger();
-			var g = smsgAuthLogonChallengeResponse.G.ToUnsignedBigInteger();
-			var s = smsgAuthLogonChallengeResponse.S.ToUnsignedBigInteger();
-			var b = smsgAuthLogonChallengeResponse.B.ToUnsignedBigInteger();
-			string identity = account + ":" + password;
-
-			var srp6Client = new SRP6Client(new SHA1Managed(), n, g, b, s, identity, password);
-
-			Logger.Debug("N: {0}\nG: {1}\ns: {2}\nB: {3}\nA: {4}\nS: {5}\nK: {6}\nm: {7}",
-				srp6Client.N.ToTrimByteArray().ToHex(), srp6Client.G.ToTrimByteArray().ToHex(),
-				srp6Client.S.ToTrimByteArray().ToHex(), srp6Client.B.ToTrimByteArray().ToHex(),
-				srp6Client.A.ToTrimByteArray().ToHex(), srp6Client.S.ToTrimByteArray().ToHex(),
-				srp6Client.K.ToTrimByteArray().ToHex(), srp6Client.M.ToHex());
+			var n = smsgAuthLogonChallengeResponse.N.ToUBigInteger();
+			var g = smsgAuthLogonChallengeResponse.G.ToUBigInteger();
+			var b = smsgAuthLogonChallengeResponse.B.ToUBigInteger();
+			var salt = smsgAuthLogonChallengeResponse.S.ToUBigInteger();
+
+			var srp6Client = new SRP6Client(
+				new SHA1Managed(), n, g, b, salt, account.ToByteArray(), passwordMd5Hex);
+
+			Logger.Debug("s: {0}\nN: {1}\nG: {2}\nB: {3}\nA: {4}\nS: {5}\nK: {6}\nm: {7}",
+				srp6Client.Salt.ToUBigIntegerArray().ToHex(),
+				srp6Client.N.ToUBigIntegerArray().ToHex(), 
+				srp6Client.G.ToUBigIntegerArray().ToHex(),
+				srp6Client.B.ToUBigIntegerArray().ToHex(),
+				srp6Client.A.ToUBigIntegerArray().ToHex(), 
+				srp6Client.S.ToUBigIntegerArray().ToHex(),
+				srp6Client.K.ToUBigIntegerArray().ToHex(), 
+				srp6Client.M.ToUBigIntegerArray().ToHex());
 
 			var cmsgAuthLogonProof = new CMSG_Auth_Logon_Proof
 			{
-				A = srp6Client.A.ToTrimByteArray(),
-				M = srp6Client.M
+				A = srp6Client.A.ToUBigIntegerArray(),
+				M = srp6Client.M.ToUBigIntegerArray()
 			};
 			this.SendMessage(MessageOpcode.CMSG_AUTH_LOGON_PROOF, cmsgAuthLogonProof);
 		}

+ 4 - 0
CSharp/App/Modules/Robot/Robot.csproj

@@ -32,6 +32,10 @@
     <WarningLevel>4</WarningLevel>
   </PropertyGroup>
   <ItemGroup>
+    <Reference Include="BouncyCastle.Crypto, Version=1.7.4137.9283, Culture=neutral, PublicKeyToken=a4292a325f69b123, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\..\..\packages\BouncyCastle.1.7.0\lib\Net20\BouncyCastle.Crypto.dll</HintPath>
+    </Reference>
     <Reference Include="Microsoft.Practices.Prism">
       <HintPath>..\..\..\packages\Prism.4.1.0.0\lib\NET40\Microsoft.Practices.Prism.dll</HintPath>
     </Reference>

+ 1 - 1
CSharp/App/Modules/Robot/RobotViewModel.cs

@@ -15,7 +15,7 @@ namespace Modules.Robot
 		private readonly ClientHost clientHost;
 		private string loginIP = "192.168.11.95";
 		private ushort loginPort = 8888;
-		private string account = "egametang";
+		private string account = "egametang@163.com";
 		private string password = "163bio1";
 
 		private readonly DispatcherTimer timer = new DispatcherTimer(DispatcherPriority.Normal)

+ 53 - 33
CSharp/App/Modules/Robot/SRP6Client.cs

@@ -4,6 +4,7 @@ using System.Linq;
 using System.Numerics;
 using System.Security.Cryptography;
 using Helper;
+using Org.BouncyCastle.Crypto.Digests;
 
 namespace Robot
 {
@@ -17,25 +18,32 @@ namespace Robot
 		private readonly BigInteger u;    // U
 		private readonly BigInteger s;    // S
 		private readonly BigInteger k;    // K
-		private readonly byte[] m;        // M
+		private readonly BigInteger m;        // M
 		private readonly byte[] p;
-		private readonly string account;
+		private readonly byte[] account;
 		private readonly BigInteger salt; // s, 服务端发过来的salt
 		private const int lowerK = 3;
+		private readonly BigInteger smallA ;
 		private readonly HashAlgorithm hashAlgorithm;
 
 		public SRP6Client(
 			HashAlgorithm hashAlgorithm, BigInteger n, BigInteger g, BigInteger b,
-			BigInteger salt, string account, string password)
+			BigInteger salt, byte[] account, byte[] passwordMd5Hex)
 		{
+			this.smallA = BigIntegerHelper.RandUnsignedBigInteger(19);
+
 			this.hashAlgorithm = hashAlgorithm;
 			this.n = n;
 			this.g = g;
 			this.b = b;
 			this.salt = salt;
 			this.account = account;
-			string identity = account + ":" + password;
-			this.p = hashAlgorithm.ComputeHash(identity.ToByteArray());
+			this.p = hashAlgorithm.ComputeHash(new byte[0]
+				.Concat(account)
+				.Concat(new[] { (byte)':' })
+				.Concat(passwordMd5Hex)
+				.ToArray());
+
 			this.a = this.CalculateA();  // A = g ^ a % N
 			this.x = this.CalculateX();  // X = H(s, P)
 			this.u = this.CalculateU();  // U = H(A, B)
@@ -108,7 +116,7 @@ namespace Robot
 			}
 		}
 
-		public byte[] M
+		public BigInteger M
 		{
 			get
 			{
@@ -124,6 +132,22 @@ namespace Robot
 			}
 		}
 
+		public BigInteger Salt
+		{
+			get
+			{
+				return this.salt;
+			}
+		}
+
+		public BigInteger SmallA
+		{
+			get
+			{
+				return this.smallA;
+			}
+		}
+
 		/// <summary>
 		/// 计算X: X = H(s, P)
 		/// </summary>
@@ -132,10 +156,10 @@ namespace Robot
 		{
 			hashAlgorithm.Initialize();
 			var joinBytes = new byte[0]
-				.Concat(salt.ToTrimByteArray())
+				.Concat(this.Salt.ToUBigIntegerArray())
 				.Concat(this.P)
 				.ToArray();
-			return hashAlgorithm.ComputeHash(joinBytes).ToUnsignedBigInteger();
+			return hashAlgorithm.ComputeHash(joinBytes).ToUBigInteger();
 		}
 
 		/// <summary>
@@ -144,9 +168,7 @@ namespace Robot
 		/// <returns></returns>
 		private BigInteger CalculateA()
 		{
-			BigInteger randomA = BigIntegerHelper.RandUnsignedBigInteger(19);
-			BigInteger calculatA = BigInteger.ModPow(this.G, randomA, this.N);
-			return calculatA;
+			return BigInteger.ModPow(this.G, this.SmallA, this.N);
 		}
 
 		/// <summary>
@@ -157,10 +179,10 @@ namespace Robot
 		{
 			hashAlgorithm.Initialize();
 			var joinBytes = new byte[0]
-				.Concat(this.A.ToTrimByteArray())
-				.Concat(this.B.ToTrimByteArray())
+				.Concat(this.A.ToUBigIntegerArray())
+				.Concat(this.B.ToUBigIntegerArray())
 				.ToArray();
-			return hashAlgorithm.ComputeHash(joinBytes).ToUnsignedBigInteger();
+			return hashAlgorithm.ComputeHash(joinBytes).ToUBigInteger();
 		}
 
 		/// <summary>
@@ -170,8 +192,9 @@ namespace Robot
 		private BigInteger CalculateS()
 		{
 			BigInteger s1 = this.B - BigInteger.ModPow(this.G, this.X, this.N) * lowerK;
-			BigInteger s2 = this.A + (this.U * this.X);
-			return BigInteger.ModPow(s1, s2, this.N);
+			BigInteger s2 = this.SmallA + (this.U * this.X);
+			BigInteger s3 = BigInteger.ModPow(s1, s2, this.N);
+			return s3;
 		}
 
 		/// <summary>
@@ -181,11 +204,10 @@ namespace Robot
 		private BigInteger CalculateK()
 		{
 			hashAlgorithm.Initialize();
-			byte[] sBytes = this.S.ToTrimByteArray();
-			int sLength = sBytes.Length;
-			int halfLength = sLength / 2;
+			byte[] sBytes = this.S.ToUBigIntegerArray();
+			int halfLength = sBytes.Length / 2;
 			var kBytes = new byte[40];
-			var halfS = new byte[sLength];
+			var halfS = new byte[halfLength];
 
 			for (int i = 0; i < halfLength; ++i)
 			{
@@ -207,18 +229,18 @@ namespace Robot
 				kBytes[i * 2 + 1] = p2[i];
 			}
 
-			return kBytes.ToUnsignedBigInteger();
+			return kBytes.ToUBigInteger();
 		}
 
 		/// <summary>
 		/// 
 		/// </summary>
 		/// <returns></returns>
-		private Byte[] CalculateM()
+		private BigInteger CalculateM()
 		{
 			hashAlgorithm.Initialize();
-			var hashN = hashAlgorithm.ComputeHash(this.N.ToTrimByteArray());
-			var hashG = hashAlgorithm.ComputeHash(this.G.ToTrimByteArray());
+			var hashN = hashAlgorithm.ComputeHash(this.N.ToUBigIntegerArray());
+			var hashG = hashAlgorithm.ComputeHash(this.G.ToUBigIntegerArray());
 
 			// 这里与标准srp6不一样,只异或了20个byte,实际上有32个byte
 			for (var i = 0; i < 20; ++i)
@@ -227,20 +249,18 @@ namespace Robot
 			}
 
 			var hashGXorhashN = hashN; // H(N) ^ H(g)
-			var hashedIdentity = hashAlgorithm.ComputeHash(this.account.ToByteArray()); // H(I)
+			var hashedIdentity = hashAlgorithm.ComputeHash(this.account); // H(I)
 
 			// H(H(N) ^ H(g), H(P), s, A, B, K_c)
-			var calculateM = hashAlgorithm.ComputeHash(new byte[0]
+			var mBytes = hashAlgorithm.ComputeHash(new byte[0]
 				.Concat(hashGXorhashN)
 				.Concat(hashedIdentity)
-				.Concat(this.salt.ToTrimByteArray())
-				.Concat(this.A.ToTrimByteArray())
-				.Concat(this.B.ToTrimByteArray())
-				.Concat(this.K.ToTrimByteArray())
+				.Concat(this.Salt.ToUBigIntegerArray())
+				.Concat(this.A.ToUBigIntegerArray())
+				.Concat(this.B.ToUBigIntegerArray())
+				.Concat(this.K.ToUBigIntegerArray())
 				.ToArray());
-			var copyM = new byte[20];
-			Array.Copy(calculateM, copyM, copyM.Length);
-			return calculateM;
+			return mBytes.ToUBigInteger();
 		}
 	}
 }

+ 16 - 11
CSharp/Platform/Helper/BigIntegerHelper.cs

@@ -24,24 +24,29 @@ namespace Helper
 			var random = new Random();
 			random.NextBytes(bigIntegerBytes);
 
-			var newBigIntegerBytes = new byte[byteNum + 1];
+			return bigIntegerBytes.ToUBigInteger();
+		}
 
-			// 给最高位加个0,防止变成负数
-			Array.Copy(bigIntegerBytes, newBigIntegerBytes, bigIntegerBytes.Length);
-			newBigIntegerBytes[newBigIntegerBytes.Length - 1] = 0;
+		public static BigInteger ToBigInteger(this byte[] bytes)
+		{
+			return new BigInteger(bytes);
+		}
 
-			var bigInteger = new BigInteger(newBigIntegerBytes);
-			return bigInteger;
+		public static BigInteger ToUBigInteger(this byte[] bytes)
+		{
+			var dst = new byte[bytes.Length + 1];
+			Array.Copy(bytes, dst, bytes.Length);
+			return new BigInteger(dst);
 		}
 
-		public static byte[] ToTrimByteArray(this BigInteger bigInteger)
+		public static byte[] ToUBigIntegerArray(this BigInteger bigInteger)
 		{
-			var bytes = bigInteger.ToByteArray();
-			if (bytes[bytes.Length - 1] == 0)
+			var result = bigInteger.ToByteArray();
+			if (result[result.Length - 1] == 0 && (result.Length % 0x10) != 0)
 			{
-				return bytes.Take(bytes.Length - 1).ToArray();
+				Array.Resize(ref result, result.Length - 1);
 			}
-			return bytes;
+			return result;
 		}
 	}
 }

+ 5 - 9
CSharp/Platform/Helper/ByteHelper.cs

@@ -1,4 +1,5 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
 using System.Globalization;
 using System.Linq;
 using System.Numerics;
@@ -33,15 +34,10 @@ namespace Helper
 			return stringBuilder.ToString();
 		}
 
-		public static BigInteger ToUnsignedBigInteger(this byte[] bytes)
+		public static byte[] Reverse(this byte[] bytes)
 		{
-			bytes = bytes.Concat(new[] { (byte)'0' }).ToArray();
-			return new BigInteger(bytes);
-		}
-
-		public static BigInteger ToBigInteger(this byte[] bytes)
-		{
-			return new BigInteger(bytes);
+			Array.Reverse(bytes);
+			return bytes;
 		}
 	}
 }

+ 24 - 1
CSharp/Platform/Helper/StringHelper.cs

@@ -1,4 +1,6 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
+using System.Globalization;
 using System.Text;
 
 namespace Helper
@@ -16,5 +18,26 @@ namespace Helper
 			byte[] byteArray = Encoding.Default.GetBytes(str);
 			return byteArray;
 		}
+
+		public static byte[] HexToBytes(this string hexString)
+		{
+			if (hexString.Length % 2 != 0)
+			{
+				throw new ArgumentException(String.Format(CultureInfo.InvariantCulture,
+					"The binary key cannot have an odd number of digits: {0}",
+					hexString));
+			}
+
+			var hexAsBytes = new byte[hexString.Length / 2];
+			for (int index = 0; index < hexAsBytes.Length; index++)
+			{
+				string byteValue = "";
+				byteValue += hexString[index * 2];
+				byteValue += hexString[index * 2 + 1];
+				hexAsBytes[index] = byte.Parse(
+					byteValue, NumberStyles.HexNumber, CultureInfo.InvariantCulture);
+			}
+			return hexAsBytes;
+		}
 	}
 }