public bool ProcessMessage(NetMQMessage incomingMessage, IList <NetMQMessage> outgoingMesssages) { ContentType contentType = ContentType.Handshake; if (incomingMessage != null) { NetMQFrame protocolVersionFrame = incomingMessage.Pop(); byte[] protocolVersionBytes = protocolVersionFrame.ToByteArray(); if (protocolVersionBytes.Length != 2) { throw new NetMQSecurityException(NetMQSecurityErrorCode.InvalidFrameLength, "Wrong length for protocol version frame"); } if (!protocolVersionBytes.SequenceEqual(m_protocolVersion)) { throw new NetMQSecurityException(NetMQSecurityErrorCode.InvalidProtocolVersion, "Wrong protocol version"); } NetMQFrame contentTypeFrame = incomingMessage.Pop(); if (contentTypeFrame.MessageSize != 1) { throw new NetMQSecurityException(NetMQSecurityErrorCode.InvalidFrameLength, "wrong length for message size"); } contentType = (ContentType)contentTypeFrame.Buffer[0]; if (contentType != ContentType.ChangeCipherSpec && contentType != ContentType.Handshake) { throw new NetMQSecurityException(NetMQSecurityErrorCode.InvalidContentType, "Unkown content type"); } if (ChangeSuiteChangeArrived) { incomingMessage = m_recordLayer.DecryptMessage(contentType, incomingMessage); } } bool result = false; if (contentType == ContentType.Handshake) { result = m_handshakeLayer.ProcessMessages(incomingMessage, m_outgoingMessageBag); foreach (NetMQMessage outgoingMesssage in m_outgoingMessageBag.Messages) { outgoingMesssages.Add(outgoingMesssage); } m_outgoingMessageBag.Clear(); } else { ChangeSuiteChangeArrived = true; } return(SecureChannelReady = result && ChangeSuiteChangeArrived); }
/// <summary> /// Process handshake and change cipher suite messages. This method should be called for every incoming message until the method returns true. /// You cannot encrypt or decrypt messages until the method return true. /// Each call to the method may include outgoing messages that need to be sent to the other peer. /// </summary> /// <param name="incomingMessage">the incoming message from the other peer</param> /// <param name="outgoingMesssages">the list of outgoing messages that need to be sent to the other peer</param> /// <returns>true when the method completes the handshake stage and the SecureChannel is ready to encrypt and decrypt messages</returns> /// <exception cref="NetMQSecurityException">NetMQSecurityErrorCode.InvalidContentType: Unknown content type.</exception> /// <exception cref="NetMQSecurityException">NetMQSecurityErrorCode.InvalidFrameLength: Wrong length for protocol version frame.</exception> /// <exception cref="NetMQSecurityException">NetMQSecurityErrorCode.InvalidFrameLength: Wrong length for message size.</exception> /// <exception cref="NetMQSecurityException">NetMQSecurityErrorCode.InvalidProtocolVersion: Wrong protocol version.</exception> /// <remarks> /// Note: Within this library, this method is ONLY called from within the unit-tests. /// </remarks> public bool ProcessMessage(NetMQMessage incomingMessage, IList <NetMQMessage> outgoingMesssages) { #if DEBUG if (incomingMessage != null) { Debug.WriteLine("[record layer(" + incomingMessage.Sum(f => f.BufferSize) + ")]"); } #endif ContentType contentType = ContentType.Handshake; if (incomingMessage != null) { // Verify that the first two frames are the protocol-version and the content-type, NetMQFrame contentTypeFrame = incomingMessage.Pop(); if (contentTypeFrame.MessageSize != 1) { throw new NetMQSecurityException(NetMQSecurityErrorCode.InvalidFrameLength, "wrong length for Content Type size"); } // Verify that the content-type is either handshake, or change-cipher-suit.. contentType = (ContentType)contentTypeFrame.Buffer[0]; if (contentType != ContentType.ChangeCipherSpec && contentType != ContentType.Handshake && contentType != ContentType.Alert) { throw new NetMQSecurityException(NetMQSecurityErrorCode.InvalidContentType, "Unknown content type"); } NetMQFrame protocolVersionFrame = incomingMessage.Pop(); byte[] protocolVersionBytes = protocolVersionFrame.ToByteArray(); if (protocolVersionBytes.Length != 2) { throw new NetMQSecurityException(NetMQSecurityErrorCode.InvalidFrameLength, "Wrong length for protocol version frame"); } if (n_ConnectionEnd == ConnectionEnd.Server && contentType == ContentType.Handshake) { //第一次握手时 if (ProtocolVersion == null) { //校验记录层版本号是否支持 if (Constants.SupposeVersions.Any(p => p.SequenceEqual(protocolVersionBytes))) { //支持版本 ProtocolVersion = protocolVersionBytes; } else { throw new NetMQSecurityException(NetMQSecurityErrorCode.InvalidFrameLength, "the protocol version is not supposed"); } } } //作为服务端首次接收到客户端 if (!protocolVersionBytes.SequenceEqual(ProtocolVersion)) { throw new NetMQSecurityException(NetMQSecurityErrorCode.InvalidProtocolVersion, "Wrong protocol version"); } RemoveLength(incomingMessage); if (ChangeSuiteChangeArrived) { RecordLayer.SetSubProtocolVersion(m_handshakeLayer.SubProtocolVersion); //已经收到ChangeCipherSuite,接下来就是Finish //Finished报文是第一个解密报文。需要解密。 incomingMessage = RecordLayer.DecryptMessage(contentType, incomingMessage); } if (contentType == ContentType.Alert) { throw new NetMQSecurityException(NetMQSecurityErrorCode.HandshakeException, "peer response alert[" + (AlertDescription)incomingMessage.Last.Buffer[0] + "]"); } } else { //作为客户端确定使用的版本号,后续客户端和服务端通讯都要校验版本号一致性。 //客户端使用3,3版本 ProtocolVersion = GetVersion(Configuration.StandardTLSFormat); } bool result = false; if (contentType == ContentType.Handshake) { result = m_handshakeLayer.ProcessMessages(incomingMessage, m_outgoingMessageBag); this.SessionId = m_handshakeLayer.SessionID; if (m_outgoingMessageBag.Messages.Count() > 1) { // Move the messages from the saved list over to the outgoing Messages collection.. foreach (NetMQMessage outgoingMesssage in m_outgoingMessageBag.Messages) { outgoingMesssages.Add(outgoingMesssage); } } else { // Move the messages from the saved list over to the outgoing Messages collection.. foreach (NetMQMessage outgoingMesssage in m_outgoingMessageBag.Messages) { outgoingMesssages.Add(outgoingMesssage); } } m_outgoingMessageBag.Clear(); } else { ////每个record计数都+1 //RecordLayer.GetAndIncreaseReadSequneceNumber(); //接下去的是Finished,需要加密。 ChangeSuiteChangeArrived = true; } return(SecureChannelReady = result && ChangeSuiteChangeArrived); }