private int ProcessCHandshake(Protocol _p) { Handshake.CHandshake p = (Handshake.CHandshake)_p; int group = p.Argument.dh_group; if (false == Config.HandshakeOptions.DhGroups.Contains(group)) { p.Sender.Close(new Exception("dhGroup Not Supported")); return(0); } Array.Reverse(p.Argument.dh_data); BigInteger data = new BigInteger(p.Argument.dh_data); BigInteger rand = Handshake.Helper.makeDHRandom(); byte[] material = Handshake.Helper.computeDHKey(group, data, rand).ToByteArray(); Array.Reverse(material); System.Net.IPAddress ipaddress = ((IPEndPoint)p.Sender.Socket.LocalEndPoint).Address; //logger.Debug(ipaddress); if (ipaddress.IsIPv4MappedToIPv6) { ipaddress = ipaddress.MapToIPv4(); } byte[] key = Config.HandshakeOptions.SecureIp != null ? Config.HandshakeOptions.SecureIp : ipaddress.GetAddressBytes(); logger.Debug("{0} localip={1}", p.Sender.SessionId, BitConverter.ToString(key)); int half = material.Length / 2; byte[] hmacMd5 = Digest.HmacMd5(key, material, 0, half); p.Sender.SetInputSecurityCodec(hmacMd5, Config.HandshakeOptions.C2sNeedCompress); byte[] response = Handshake.Helper.generateDHResponse(group, rand).ToByteArray(); Array.Reverse(response); new Handshake.SHandshake(response, Config.HandshakeOptions.S2cNeedCompress, Config.HandshakeOptions.C2sNeedCompress) .Send(p.Sender); hmacMd5 = Digest.HmacMd5(key, material, half, material.Length - half); p.Sender.SetOutputSecurityCodec(hmacMd5, Config.HandshakeOptions.S2cNeedCompress); // 为了防止服务器在Handshake以后马上发送数据, // 导致未加密数据和加密数据一起到达Client,这种情况很难处理。 // 这个本质上是协议相关的问题:就是前面一个协议的处理结果影响后面数据处理。 // 所以增加CHandshakeDone协议,在Client进入加密以后发送给Server。 // OnHandshakeDone(p.Sender); return(0); }
protected void AddHandshakeServerFactoryHandle() { { var tmp = new Handshake.CHandshake(); HandshakeProtocols.Add(tmp.TypeId); AddFactoryHandle(tmp.TypeId, new Service.ProtocolFactoryHandle() { Factory = () => new Handshake.CHandshake(), Handle = ProcessCHandshake, NoProcedure = true, }); } { var tmp = new Handshake.CHandshakeDone(); HandshakeProtocols.Add(tmp.TypeId); AddFactoryHandle(tmp.TypeId, new Service.ProtocolFactoryHandle() { Factory = () => new Handshake.CHandshakeDone(), Handle = ProcessCHandshakeDone, NoProcedure = true, }); } }