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);
        }
Пример #4
0
        /// <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);
        }
Пример #5
0
        /// <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);
        }
Пример #6
0
        /// <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);
        }