public void BigBytesData(int length) { NetMQMessage plainMessage = new NetMQMessage(); plainMessage.Append(new byte[length]); new Random().NextBytes(plainMessage[0].Buffer); byte[] data = m_serverSecureChannel.EncryptApplicationBytes(plainMessage[0].Buffer); List <NetMQMessage> sslMessages = new List <NetMQMessage>(); int o = 0; bool result = m_clientSecureChannel.ResolveRecordLayer(data, out o, out sslMessages); List <NetMQMessage> plainMessages = new List <NetMQMessage>(); foreach (var netmq in sslMessages) { //大包合并包 plainMessages.Add(m_clientSecureChannel.DecryptApplicationMessage(netmq)); } Assert.AreEqual(plainMessage.Sum(p => p.BufferSize), plainMessages.Sum(f => f.Sum(p => p.BufferSize))); byte[] encryptBytes = new byte[plainMessages.Sum(e => e.Sum(f => f.BufferSize))]; int offset = 0; foreach (var p in plainMessages) { foreach (var frame in p) { Buffer.BlockCopy(frame.Buffer, 0, encryptBytes, offset, frame.BufferSize); offset += frame.BufferSize; } } Assert.AreEqual(plainMessage[0].Buffer, encryptBytes); }
/// <summary> /// Add the given NetMQMessage to the list that this object holds, using the SecureChannel to /// encrypt and wrap it as a Handshake type of content. /// </summary> /// <param name="message">the NetMQMessage to add to the list that this object is holding</param> public void AddHandshakeMessage(NetMQMessage handshakeMessage) { byte[] bytes = new byte[handshakeMessage.Sum(f => f.BufferSize)]; int offset = 0; foreach (var frame in handshakeMessage) { Buffer.BlockCopy(frame.Buffer, 0, bytes, offset, frame.BufferSize); offset += frame.BufferSize; } AddHandshakeMessage(bytes); }
public static byte[] ToBytes(NetMQMessage message) { byte[] data = new byte[message.Sum(f => f.BufferSize)]; int offset = 0; foreach (var frame in message) { Buffer.BlockCopy(frame.Buffer, 0, data, offset, frame.BufferSize); offset += frame.BufferSize; } return(data); }
/// <param name="contentType">This identifies the type of content: ChangeCipherSpec, Handshake, or ApplicationData.</param> /// <param name="plainMessage">The unencrypted form of the message to be encrypted.</param> internal NetMQMessage InternalEncryptAndWrapMessage(ContentType contentType, NetMQMessage plainMessage) { byte[] bytes = new byte[plainMessage.Sum(m => m.BufferSize)]; int offset = 0; foreach (var frame in plainMessage) { Buffer.BlockCopy(frame.Buffer, 0, bytes, offset, frame.BufferSize); offset += frame.BufferSize; } NetMQMessage encryptedMessage = new NetMQMessage(); var encrpytFrameBytes = EncryptFrame(contentType, bytes); encryptedMessage.Append(encrpytFrameBytes); return(encryptedMessage); }
/// <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); }
/// <summary> /// Given an incoming handshake-protocol message, route it to the corresponding handler. /// </summary> /// <param name="incomingMessage">the NetMQMessage that has come in</param> /// <param name="outgoingMessages">a collection of NetMQMessages that are to be sent</param> /// <returns>true if finished - ie, an incoming message of type Finished was received</returns> /// <exception cref="ArgumentNullException"><paramref name="incomingMessage"/> must not be <c>null</c>.</exception> /// <exception cref="ArgumentOutOfRangeException"><paramref name="incomingMessage"/> must have a valid <see cref="HandshakeType"/>.</exception> public bool ProcessMessages(NetMQMessage incomingMessage, OutgoingMessageBag outgoingMessages) { if (incomingMessage == null) { if (m_lastReceivedMessage == m_lastSentMessage && m_lastSentMessage == HandshakeType.HelloRequest && SecurityParameters.Entity == ConnectionEnd.Client) { //客户端发送握手 OnHelloRequest(outgoingMessages); return(false); } else { throw new ArgumentNullException(nameof(incomingMessage)); } } #if DEBUG int size = incomingMessage.Sum(f => f.BufferSize); Debug.WriteLine("[handshake(" + size + ")]:"); byte[] data = new byte[size]; int offset = 0; foreach (var frame in incomingMessage) { Buffer.BlockCopy(frame.Buffer, 0, data, offset, frame.BufferSize); } Debug.WriteLine(BitConverter.ToString(data)); #endif //A Finished message is always sent immediately after a change cipher spec message to verify that the key exchange and authentication processes were successful. //It is essential that a change cipher spec message be received between the other handshake messages and the Finished message. //已经收到ChangeCipherSuite,接下来就是Finish HandshakeType handshakeType; if (m_secureChannel.ChangeSuiteChangeArrived) { handshakeType = HandshakeType.Finished; } else { handshakeType = (HandshakeType)incomingMessage[0].Buffer[0]; ////起始计数从0开始,Finished在解密的时候会添加计数,其他record层都要在这里添加读计数 //m_secureChannel.RecordLayer.GetAndIncreaseReadSequneceNumber(); } switch (handshakeType) { case HandshakeType.HelloRequest: { //接收到对端的HelloRequest重新协商。暂时抛出异常重置连接 NetMQMessage alert = m_secureChannel.HandshakeFailure(AlertLevel.Fatal, m_secureChannel.ProtocolVersion); //抛出异常,返回alert协议,通知客户端断开连接。 throw new AlertException(alert, new Exception(AlertDescription.NoRenegotiation.ToString())); } case HandshakeType.ClientHello: OnClientHello(incomingMessage, outgoingMessages); break; case HandshakeType.ServerHello: OnServerHello(incomingMessage); break; case HandshakeType.Certificate: OnCertificate(incomingMessage); break; case HandshakeType.ServerHelloDone: OnServerHelloDone(incomingMessage, outgoingMessages); break; case HandshakeType.ClientKeyExchange: OnClientKeyExchange(incomingMessage); break; case HandshakeType.Finished: OnFinished(incomingMessage, outgoingMessages); break; default: { NetMQMessage alert = m_secureChannel.HandshakeFailure(AlertLevel.Fatal, m_secureChannel.ProtocolVersion); //抛出异常,返回alert协议,通知客户端断开连接。 throw new AlertException(alert, new Exception(AlertDescription.UnexpectedMessage.ToString())); } } m_lastReceivedMessage = handshakeType; return(m_done); }