private void AddFinished(OutgoingMessageBag outgoingMessages) { m_localHash.TransformFinalBlock(new byte[0], 0, 0); byte[] seed = m_localHash.Hash; m_localHash.Dispose(); m_localHash = null; string label; if (SecurityParameters.Entity == ConnectionEnd.Server) { label = ServerFinishedLabel; } else { label = ClientFinshedLabel; } FinishedMessage finishedMessage = new FinishedMessage(); finishedMessage.VerifyData = PRF.Get(SecurityParameters.MasterSecret, label, seed, FinishedMessage.VerifyDataLength); NetMQMessage outgoingMessage = finishedMessage.ToNetMQMessage(); outgoingMessages.AddHandshakeMessage(outgoingMessage); m_lastSentMessage = HandshakeType.Finished; if (SecurityParameters.Entity == ConnectionEnd.Client) { HashRemote(outgoingMessage); } }
private void OnHelloRequest(OutgoingMessageBag outgoingMessages) { //客户端根据配置决定握手层版本号 SubProtocolVersion = GetSubProtocol(); var clientHelloMessage = SubProtocolVersion.SequenceEqual(Constants.V3_3) ? new V0_2.HandshakeMessages.ClientHelloMessage() : new ClientHelloMessage(); clientHelloMessage.RandomNumber = new byte[RandomNumberLength]; clientHelloMessage.SessionID = SessionID; m_rng.GetBytes(clientHelloMessage.RandomNumber); ////TODO: 测试 //string random = "5e c2 54 f6 fa cc f1 40 be ec 3b 43 44 1c 72 c3 25 ed 43 7a 5d cf a2 17 33 26 94 48 f7 cb 34 f9"; //clientHelloMessage.RandomNumber = random.ConvertHexToByteArray(); SecurityParameters.ClientRandom = clientHelloMessage.RandomNumber; clientHelloMessage.CipherSuites = AllowedCipherSuites; NetMQMessage outgoingMessage = clientHelloMessage.ToNetMQMessage(); HashLocalAndRemote(outgoingMessage); //第一个record的seqnum从0开始 outgoingMessages.AddHandshakeMessage(outgoingMessage); m_lastSentMessage = HandshakeType.ClientHello; }
private void AddFinished(OutgoingMessageBag outgoingMessages) { m_localHash.TransformFinalBlock(EmptyArray <byte> .Instance, 0, 0); byte[] seed = m_localHash.Hash; #if NET40 m_localHash.Dispose(); #endif m_localHash = null; var label = SecurityParameters.Entity == ConnectionEnd.Server ? ServerFinishedLabel : ClientFinshedLabel; var finishedMessage = SubProtocolVersion.SequenceEqual(Constants.V3_3)? new V0_2.HandshakeMessages.FinishedMessage(): new FinishedMessage(); finishedMessage.VerifyData = PRF.Get(SecurityParameters.MasterSecret, label, seed, FinishedMessage.VerifyDataLength); #if DEBUG Debug.WriteLine("[verify_data]:" + BitConverter.ToString(finishedMessage.VerifyData)); #endif NetMQMessage outgoingMessage = finishedMessage.ToNetMQMessage(); outgoingMessages.AddHandshakeMessage(outgoingMessage); m_lastSentMessage = HandshakeType.Finished; if (SecurityParameters.Entity == ConnectionEnd.Client) { HashRemote(outgoingMessage); } }
private void AddServerHelloMessage(OutgoingMessageBag outgoingMessages, CipherSuite[] cipherSuites) { var serverHelloMessage = new ServerHelloMessage { RandomNumber = new byte[RandomNumberLength] }; m_rng.GetBytes(serverHelloMessage.RandomNumber); SecurityParameters.ServerRandom = serverHelloMessage.RandomNumber; // in case there is no match the server will return this default serverHelloMessage.CipherSuite = CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA; foreach (var cipherSuite in cipherSuites) { if (AllowedCipherSuites.Contains(cipherSuite)) { serverHelloMessage.CipherSuite = cipherSuite; SetCipherSuite(cipherSuite); break; } } NetMQMessage outgoingMessage = serverHelloMessage.ToNetMQMessage(); HashLocalAndRemote(outgoingMessage); outgoingMessages.AddHandshakeMessage(outgoingMessage); m_lastSentMessage = HandshakeType.ServerHello; }
private void AddFinished(OutgoingMessageBag outgoingMessages) { m_localHash.TransformFinalBlock(EmptyArray <byte> .Instance, 0, 0); byte[] seed = m_localHash.Hash; m_localHash.Dispose(); m_localHash = null; var label = SecurityParameters.Entity == ConnectionEnd.Server ? ServerFinishedLabel : ClientFinshedLabel; var finishedMessage = new FinishedMessage { VerifyData = PRF.Get(SecurityParameters.MasterSecret, label, seed, FinishedMessage.VerifyDataLength) }; NetMQMessage outgoingMessage = finishedMessage.ToNetMQMessage(); outgoingMessages.AddHandshakeMessage(outgoingMessage); m_lastSentMessage = HandshakeType.Finished; if (SecurityParameters.Entity == ConnectionEnd.Client) { HashRemote(outgoingMessage); } }
/// <summary> /// Create a new SecureChannel with the given <see cref="ConnectionEnd"/>. /// </summary> /// <param name="connectionEnd">the ConnectionEnd that this channel is to talk to</param> public SecureChannel(ConnectionEnd connectionEnd) { m_handshakeLayer = new HandshakeLayer(this, connectionEnd); m_handshakeLayer.CipherSuiteChange += OnCipherSuiteChangeFromHandshakeLayer; m_recordLayer = new RecordLayer(m_protocolVersion); m_outgoingMessageBag = new OutgoingMessageBag(this); }
/// <exception cref="NetMQSecurityException">The Finished message must not be received while expecting a another message.</exception> /// <exception cref="NetMQSecurityException">The peer verification data must be valid.</exception> private void OnFinished(NetMQMessage incomingMessage, OutgoingMessageBag outgoingMessages) { if ( (SecurityParameters.Entity == ConnectionEnd.Client && (!m_secureChannel.ChangeSuiteChangeArrived || m_lastReceivedMessage != HandshakeType.ServerHelloDone || m_lastSentMessage != HandshakeType.Finished)) || (SecurityParameters.Entity == ConnectionEnd.Server && (!m_secureChannel.ChangeSuiteChangeArrived || m_lastReceivedMessage != HandshakeType.ClientKeyExchange || m_lastSentMessage != HandshakeType.ServerHelloDone))) { throw new NetMQSecurityException(NetMQSecurityErrorCode.HandshakeUnexpectedMessage, "Finished received when expecting another message"); } if (SecurityParameters.Entity == ConnectionEnd.Server) { HashLocal(incomingMessage); } var finishedMessage = SubProtocolVersion.SequenceEqual(Constants.V3_3)? new V0_2.HandshakeMessages.FinishedMessage(): new FinishedMessage(); finishedMessage.SetFromNetMQMessage(incomingMessage); m_remoteHash.TransformFinalBlock(EmptyArray <byte> .Instance, 0, 0); byte[] seed = m_remoteHash.Hash; #if NET40 m_remoteHash.Dispose(); #else m_remoteHash.Clear(); #endif m_remoteHash = null; var label = SecurityParameters.Entity == ConnectionEnd.Client ? ServerFinishedLabel : ClientFinshedLabel; var verifyData = PRF.Get(SecurityParameters.MasterSecret, label, seed, FinishedMessage.VerifyDataLength); #if DEBUG Debug.WriteLine("[verify_data]:" + BitConverter.ToString(verifyData)); #endif if (!verifyData.SequenceEqual(finishedMessage.VerifyData)) { throw new NetMQSecurityException(NetMQSecurityErrorCode.HandshakeVerifyData, "peer verify data wrong"); } if (SecurityParameters.Entity == ConnectionEnd.Server) { AddFinished(outgoingMessages); #if DEBUG Debug.WriteLine("[finish]"); #endif } m_done = true; }
public SecureChannel(ConnectionEnd connectionEnd) { m_handshakeLayer = new HandshakeLayer(this, connectionEnd); m_handshakeLayer.CipherSuiteChange += OnCipherSuiteChangeFromHandshakeLayer; m_recordLayer = new RecordLayer(m_protocolVersion); m_outgoingMessageBag = new OutgoingMessageBag(this); }
private void AddServerHelloDone(OutgoingMessageBag outgoingMessages) { var serverHelloDoneMessage = new ServerHelloDoneMessage(); NetMQMessage outgoingMessage = serverHelloDoneMessage.ToNetMQMessage(); HashLocalAndRemote(outgoingMessage); outgoingMessages.AddHandshakeMessage(outgoingMessage); m_lastSentMessage = HandshakeType.ServerHelloDone; }
private void OnFinished(NetMQMessage incomingMessage, OutgoingMessageBag outgoingMessages) { if ( (SecurityParameters.Entity == ConnectionEnd.Client && (!m_secureChannel.ChangeSuiteChangeArrived || m_lastReceivedMessage != HandshakeType.ServerHelloDone || m_lastSentMessage != HandshakeType.Finished)) || (SecurityParameters.Entity == ConnectionEnd.Server && (!m_secureChannel.ChangeSuiteChangeArrived || m_lastReceivedMessage != HandshakeType.ClientKeyExchange || m_lastSentMessage != HandshakeType.ServerHelloDone))) { throw new NetMQSecurityException(NetMQSecurityErrorCode.HandshakeUnexpectedMessage, "Finished received when expecting another message"); } if (SecurityParameters.Entity == ConnectionEnd.Server) { HashLocal(incomingMessage); } FinishedMessage finishedMessage = new FinishedMessage(); finishedMessage.SetFromNetMQMessage(incomingMessage); m_remoteHash.TransformFinalBlock(new byte[0], 0, 0); byte[] seed = m_remoteHash.Hash; m_remoteHash.Dispose(); m_remoteHash = null; string label; if (SecurityParameters.Entity == ConnectionEnd.Client) { label = ServerFinishedLabel; } else { label = ClientFinshedLabel; } byte[] verifyData = PRF.Get(SecurityParameters.MasterSecret, label, seed, FinishedMessage.VerifyDataLength); if (!verifyData.SequenceEqual(finishedMessage.VerifyData)) { throw new NetMQSecurityException(NetMQSecurityErrorCode.HandshakeVerifyData, "peer verify data wrong"); } if (SecurityParameters.Entity == ConnectionEnd.Server) { AddFinished(outgoingMessages); } m_done = true; }
private void AddServerHelloDone(OutgoingMessageBag outgoingMessages) { var serverHelloDoneMessage = SubProtocolVersion.SequenceEqual(Constants.V3_3)? new V0_2.HandshakeMessages.ServerHelloDoneMessage(): new ServerHelloDoneMessage(); NetMQMessage outgoingMessage = serverHelloDoneMessage.ToNetMQMessage(); HashLocalAndRemote(outgoingMessage); outgoingMessages.AddHandshakeMessage(outgoingMessage); m_lastSentMessage = HandshakeType.ServerHelloDone; }
private void AddCertificateMessage(OutgoingMessageBag outgoingMessages) { var certificateMessage = new CertificateMessage { Certificate = LocalCertificate }; NetMQMessage outgoingMessage = certificateMessage.ToNetMQMessage(); HashLocalAndRemote(outgoingMessage); outgoingMessages.AddHandshakeMessage(outgoingMessage); m_lastSentMessage = HandshakeType.Certificate; }
/// <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)); } } var handshakeType = (HandshakeType)incomingMessage[0].Buffer[0]; switch (handshakeType) { 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: throw new ArgumentOutOfRangeException(); } m_lastReceivedMessage = handshakeType; return(m_done); }
private void AddCertificateMessage(OutgoingMessageBag outgoingMessages) { var certificateMessage = SubProtocolVersion.SequenceEqual(Constants.V3_3)? new V0_2.HandshakeMessages.CertificateMessage(): new CertificateMessage(); certificateMessage.Certificate = LocalCertificate; NetMQMessage outgoingMessage = certificateMessage.ToNetMQMessage(); HashLocalAndRemote(outgoingMessage); outgoingMessages.AddHandshakeMessage(outgoingMessage); m_lastSentMessage = HandshakeType.Certificate; }
private void AddServerHelloMessage(OutgoingMessageBag outgoingMessages, CipherSuite[] cipherSuites) { var serverHelloMessage = SubProtocolVersion.SequenceEqual(Constants.V3_3)? new V0_2.HandshakeMessages.ServerHelloMessage(): new ServerHelloMessage(); serverHelloMessage.RandomNumber = new byte[RandomNumberLength]; m_rng.GetBytes(serverHelloMessage.RandomNumber); ////TODO: 测试 //string random = "ae f1 ba 12 3a 54 3c 51 7b 3d 49 87 05 80 6e 67 45 c5 76 77 74 26 01 d9 b9 da 69 79 e2 84 1d 37"; //serverHelloMessage.RandomNumber = random.ConvertHexToByteArray(); SecurityParameters.ServerRandom = serverHelloMessage.RandomNumber; //客户端没有传sessionid则生成一个新的sessionid if (this.SessionID.Length == 0) { this.SessionID = Encoding.ASCII.GetBytes(Guid.NewGuid().ToString("N")); } ////TODO: 测试 //this.SessionID = "37 61 36 36 35 64 37 38 36 62 61 36 34 32 62 64 38 36 61 62 32 61 63 39 36 31 35 34 37 34 33 61".ConvertHexToByteArray(); serverHelloMessage.SessionID = this.SessionID; // in case there is no match the server will return this default serverHelloMessage.CipherSuite = CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA; foreach (var cipherSuite in cipherSuites) { if (AllowedCipherSuites.Contains(cipherSuite)) { serverHelloMessage.CipherSuite = cipherSuite; SetCipherSuite(cipherSuite); break; } } NetMQMessage outgoingMessage = serverHelloMessage.ToNetMQMessage(); HashLocalAndRemote(outgoingMessage); outgoingMessages.AddHandshakeMessage(outgoingMessage); m_lastSentMessage = HandshakeType.ServerHello; }
/// <summary> /// Create a new SecureChannel with the given <see cref="ConnectionEnd"/>. /// </summary> /// <param name="connectionEnd">the ConnectionEnd that this channel is to talk to</param> private SecureChannel(ConnectionEnd connectionEnd, Configuration configuration = null) { Configuration = configuration ?? new Configuration(); n_ConnectionEnd = connectionEnd; m_handshakeLayer = new HandshakeLayer(this, connectionEnd); m_handshakeLayer.CipherSuiteChange += OnCipherSuiteChangeFromHandshakeLayer; RecordLayer = new RecordLayer(); m_outgoingMessageBag = new OutgoingMessageBag(this); if (!Configuration.VerifyCertificate) { //若不验证证书,则直接返回true SetVerifyCertificate(c => true); } }
private void OnServerHello(NetMQMessage incomingMessage, OutgoingMessageBag outgoingMessages) { if (m_lastReceivedMessage != HandshakeType.HelloRequest || m_lastSentMessage != HandshakeType.ClientHello) { throw new NetMQSecurityException(NetMQSecurityErrorCode.HandshakeUnexpectedMessage, "Server Hello received when expecting another message"); } HashLocalAndRemote(incomingMessage); ServerHelloMessage serverHelloMessage = new ServerHelloMessage(); serverHelloMessage.SetFromNetMQMessage(incomingMessage); SecurityParameters.ServerRandom = serverHelloMessage.RandomNumber; SetCipherSuite(serverHelloMessage.CipherSuite); }
private void AddClientKeyExchange(OutgoingMessageBag outgoingMessages) { var clientKeyExchangeMessage = SubProtocolVersion.SequenceEqual(Constants.V3_3) ? new V0_2.HandshakeMessages.ClientKeyExchangeMessage() : new ClientKeyExchangeMessage(); //struct { // ProtocolVersion client_version; // opaque random[46]; //}PreMasterSecret; var premasterSecret = new byte[ClientKeyExchangeMessage.PreMasterSecretLength]; // The version number in the PreMasterSecret is the version // offered by the client in the ClientHello.client_version, not the // version negotiated for the connection. This feature is designed to // prevent rollback attacks.Unfortunately, some old implementations // use the negotiated version instead, and therefore checking the // version number may lead to failure to interoperate with such // incorrect client implementations. // Client implementations MUST always send the correct version number in // PreMasterSecret.If ClientHello.client_version is TLS 1.1 or higher, // server implementations MUST check the version number as described in // the note below.If the version number is TLS 1.0 or earlier, server // implementations SHOULD check the version number, but MAY have a // configuration option to disable the check. premasterSecret[0] = 3; premasterSecret[1] = 3; byte[] random = new byte[46]; m_rng.GetBytes(random); Buffer.BlockCopy(random, 0, premasterSecret, 2, random.Length); ////TODO :测试 //premasterSecret = "03-03-11-41-D4-8F-8C-62-6F-31-12-40-D8-1D-F3-1C-8C-E3-6D-2F-0E-87-C6-DA-D1-17-96-CF-91-CD-EC-DB-F9-B5-52-FB-66-B6-E6-EB-65-71-1F-7A-05-25-0B-03".ConvertHexToByteArray('-'); var rsa = RemoteCertificate.PublicKey.Key as RSACryptoServiceProvider; clientKeyExchangeMessage.EncryptedPreMasterSecret = rsa.Encrypt(premasterSecret, false); GenerateMasterSecret(premasterSecret); NetMQMessage outgoingMessage = clientKeyExchangeMessage.ToNetMQMessage(); HashLocalAndRemote(outgoingMessage); outgoingMessages.AddHandshakeMessage(outgoingMessage); m_lastSentMessage = HandshakeType.ClientKeyExchange; }
private void OnHelloRequest(OutgoingMessageBag outgoingMessages) { ClientHelloMessage clientHelloMessage = new ClientHelloMessage(); clientHelloMessage.RandomNumber = new byte[RandomNumberLength]; m_rng.GetBytes(clientHelloMessage.RandomNumber); SecurityParameters.ClientRandom = clientHelloMessage.RandomNumber; clientHelloMessage.CipherSuites = AllowedCipherSuites; NetMQMessage outgoingMessage = clientHelloMessage.ToNetMQMessage(); HashLocalAndRemote(outgoingMessage); outgoingMessages.AddHandshakeMessage(outgoingMessage); m_lastSentMessage = HandshakeType.ClientHello; }
/// <exception cref="NetMQSecurityException">The client hello message must not be received while expecting a different message.</exception> private void OnClientHello(NetMQMessage incomingMessage, OutgoingMessageBag outgoingMessages) { if (m_lastReceivedMessage != HandshakeType.HelloRequest || m_lastSentMessage != HandshakeType.HelloRequest) { throw new NetMQSecurityException(NetMQSecurityErrorCode.HandshakeUnexpectedMessage, "Client Hello received when expecting another message"); } HashLocalAndRemote(incomingMessage); var handShakeTypeFrame = incomingMessage.Pop(); //服务端根据主版本号先判断 if (m_secureChannel.ProtocolVersion.SequenceEqual(Constants.V0_1)) { //没有长度,没有子版本号,使用Record的版本号一致 SubProtocolVersion = m_secureChannel.ProtocolVersion; } else { //标准的获取长度和版本号,并校验 var handShakeLengthFrame = incomingMessage.Pop(); NetMQFrame versionFrame = incomingMessage.Pop(); SubProtocolVersion = versionFrame.Buffer; } if (!Constants.SupposeSubVersions.Any(v => v.SequenceEqual(SubProtocolVersion))) { throw new NetMQSecurityException(NetMQSecurityErrorCode.InvalidProtocolVersion, "the hand shake protocol version is not supposed"); } //获取保存子协议版本 var clientHelloMessage = SubProtocolVersion.SequenceEqual(Constants.V3_3) ? new V0_2.HandshakeMessages.ClientHelloMessage() : new ClientHelloMessage(); clientHelloMessage.SetFromNetMQMessage(incomingMessage); //获取到客户端的sessionid this.SessionID = clientHelloMessage.SessionID; SecurityParameters.ClientRandom = clientHelloMessage.RandomNumber; AddServerHelloMessage(outgoingMessages, clientHelloMessage.CipherSuites); AddCertificateMessage(outgoingMessages); AddServerHelloDone(outgoingMessages); }
private void AddClientKeyExchange(OutgoingMessageBag outgoingMessages) { ClientKeyExchangeMessage clientKeyExchangeMessage = new ClientKeyExchangeMessage(); byte[] premasterSecret = new byte[ClientKeyExchangeMessage.PreMasterSecretLength]; m_rng.GetBytes(premasterSecret); RSACryptoServiceProvider rsa = RemoteCertificate.PublicKey.Key as RSACryptoServiceProvider; clientKeyExchangeMessage.EncryptedPreMasterSecret = rsa.Encrypt(premasterSecret, false); GenerateMasterSecret(premasterSecret); NetMQMessage outgoingMessage = clientKeyExchangeMessage.ToNetMQMessage(); HashLocalAndRemote(outgoingMessage); outgoingMessages.AddHandshakeMessage(outgoingMessage); m_lastSentMessage = HandshakeType.ClientKeyExchange; }
private void OnCertificate(NetMQMessage incomingMessage, OutgoingMessageBag outgoingMessages) { if (m_lastReceivedMessage != HandshakeType.ServerHello || m_lastSentMessage != HandshakeType.ClientHello) { throw new NetMQSecurityException(NetMQSecurityErrorCode.HandshakeUnexpectedMessage, "Certificate received when expecting another message"); } HashLocalAndRemote(incomingMessage); CertificateMessage certificateMessage = new CertificateMessage(); certificateMessage.SetFromNetMQMessage(incomingMessage); if (!VerifyCertificate(certificateMessage.Certificate)) { throw new NetMQSecurityException(NetMQSecurityErrorCode.HandshakeUnexpectedMessage, "Unable to verify certificate"); } RemoteCertificate = certificateMessage.Certificate; }
/// <exception cref="NetMQSecurityException">The server hello message must not be received while expecting another message.</exception> private void OnServerHelloDone(NetMQMessage incomingMessage, OutgoingMessageBag outgoingMessages) { if (m_lastReceivedMessage != HandshakeType.Certificate || m_lastSentMessage != HandshakeType.ClientHello) { throw new NetMQSecurityException(NetMQSecurityErrorCode.HandshakeUnexpectedMessage, "Server Hello Done received when expecting another message"); } HashLocalAndRemote(incomingMessage); var serverHelloDoneMessage = new ServerHelloDoneMessage(); serverHelloDoneMessage.SetFromNetMQMessage(incomingMessage); AddClientKeyExchange(outgoingMessages); InvokeChangeCipherSuite(); AddFinished(outgoingMessages); }
private void OnClientKeyExchange(NetMQMessage incomingMessage, OutgoingMessageBag outgoingMessages) { if (m_lastReceivedMessage != HandshakeType.ClientHello || m_lastSentMessage != HandshakeType.ServerHelloDone) { throw new NetMQSecurityException(NetMQSecurityErrorCode.HandshakeUnexpectedMessage, "Client Key Exchange received when expecting another message"); } HashLocalAndRemote(incomingMessage); ClientKeyExchangeMessage clientKeyExchangeMessage = new ClientKeyExchangeMessage(); clientKeyExchangeMessage.SetFromNetMQMessage(incomingMessage); RSACryptoServiceProvider rsa = LocalCertificate.PrivateKey as RSACryptoServiceProvider; byte[] premasterSecret = rsa.Decrypt(clientKeyExchangeMessage.EncryptedPreMasterSecret, false); GenerateMasterSecret(premasterSecret); InvokeChangeCipherSuite(); }
/// <exception cref="NetMQSecurityException">The client hello message must not be received while expecting a different message.</exception> private void OnClientHello(NetMQMessage incomingMessage, OutgoingMessageBag outgoingMessages) { if (m_lastReceivedMessage != HandshakeType.HelloRequest || m_lastSentMessage != HandshakeType.HelloRequest) { throw new NetMQSecurityException(NetMQSecurityErrorCode.HandshakeUnexpectedMessage, "Client Hello received when expecting another message"); } HashLocalAndRemote(incomingMessage); var clientHelloMessage = new ClientHelloMessage(); clientHelloMessage.SetFromNetMQMessage(incomingMessage); SecurityParameters.ClientRandom = clientHelloMessage.RandomNumber; AddServerHelloMessage(outgoingMessages, clientHelloMessage.CipherSuites); AddCertificateMessage(outgoingMessages); AddServerHelloDone(outgoingMessages); }
private void AddClientKeyExchange(OutgoingMessageBag outgoingMessages) { var clientKeyExchangeMessage = new ClientKeyExchangeMessage(); var premasterSecret = new byte[ClientKeyExchangeMessage.PreMasterSecretLength]; m_rng.GetBytes(premasterSecret); using (var rsa = RemoteCertificate.GetRSAPublicKey()) // .PublicKey.Key as RSA; //RSACryptoServiceProvider; { clientKeyExchangeMessage.EncryptedPreMasterSecret = rsa.Encrypt(premasterSecret, RSAEncryptionPadding.Pkcs1); // false); } GenerateMasterSecret(premasterSecret); NetMQMessage outgoingMessage = clientKeyExchangeMessage.ToNetMQMessage(); HashLocalAndRemote(outgoingMessage); outgoingMessages.AddHandshakeMessage(outgoingMessage); m_lastSentMessage = HandshakeType.ClientKeyExchange; }
/// <exception cref="NetMQSecurityException">The server hello message must not be received while expecting another message.</exception> private void OnServerHelloDone(NetMQMessage incomingMessage, OutgoingMessageBag outgoingMessages) { if (m_lastReceivedMessage != HandshakeType.Certificate || m_lastSentMessage != HandshakeType.ClientHello) { throw new NetMQSecurityException(NetMQSecurityErrorCode.HandshakeUnexpectedMessage, "Server Hello Done received when expecting another message"); } HashLocalAndRemote(incomingMessage); var handShakeTypeFrame = incomingMessage.Pop(); var serverHelloDoneMessage = SubProtocolVersion.SequenceEqual(Constants.V3_3) ? new V0_2.HandshakeMessages.ServerHelloDoneMessage() : new ServerHelloDoneMessage(); serverHelloDoneMessage.SetFromNetMQMessage(incomingMessage); AddClientKeyExchange(outgoingMessages); InvokeChangeCipherSuite(); AddFinished(outgoingMessages); }
private void AddFinished(OutgoingMessageBag outgoingMessages) { m_localHash.TransformFinalBlock(EmptyArray<byte>.Instance, 0, 0); byte[] seed = m_localHash.Hash; m_localHash.Dispose(); m_localHash = null; var label = SecurityParameters.Entity == ConnectionEnd.Server ? ServerFinishedLabel : ClientFinshedLabel; var finishedMessage = new FinishedMessage { VerifyData = PRF.Get(SecurityParameters.MasterSecret, label, seed, FinishedMessage.VerifyDataLength) }; NetMQMessage outgoingMessage = finishedMessage.ToNetMQMessage(); outgoingMessages.AddHandshakeMessage(outgoingMessage); m_lastSentMessage = HandshakeType.Finished; if (SecurityParameters.Entity == ConnectionEnd.Client) { HashRemote(outgoingMessage); } }
private void AddFinished(OutgoingMessageBag outgoingMessages) { m_localHash.TransformFinalBlock(new byte[0], 0, 0); byte[] seed = m_localHash.Hash; m_localHash.Dispose(); m_localHash = null; string label; if (SecurityParameters.Entity == ConnectionEnd.Server) { label = ServerFinishedLabel; } else { label = ClientFinshedLabel; } FinishedMessage finishedMessage = new FinishedMessage(); finishedMessage.VerifyData = PRF.Get(SecurityParameters.MasterSecret, label, seed, FinishedMessage.VerifyDataLength); NetMQMessage outgoingMessage = finishedMessage.ToNetMQMessage(); outgoingMessages.AddHandshakeMessage(outgoingMessage); m_lastSentMessage = HandshakeType.Finished; if (SecurityParameters.Entity == ConnectionEnd.Client) { HashRemote(outgoingMessage); } }
private void AddServerHelloMessage(OutgoingMessageBag outgoingMessages, CipherSuite[] cipherSuites) { ServerHelloMessage serverHelloMessage = new ServerHelloMessage(); serverHelloMessage.RandomNumber = new byte[RandomNumberLength]; m_rng.GetBytes(serverHelloMessage.RandomNumber); SecurityParameters.ServerRandom = serverHelloMessage.RandomNumber; // in case their is no much the server will return this defaul serverHelloMessage.CipherSuite = CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA; foreach (CipherSuite cipherSuite in cipherSuites) { if (AllowedCipherSuites.Contains(cipherSuite)) { serverHelloMessage.CipherSuite = cipherSuite; SetCipherSuite(cipherSuite); break; } } NetMQMessage outgoingMessage = serverHelloMessage.ToNetMQMessage(); HashLocalAndRemote(outgoingMessage); outgoingMessages.AddHandshakeMessage(outgoingMessage); m_lastSentMessage = HandshakeType.ServerHello; }
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("handshakeMessage is null"); } } HandshakeType handshakeType = (HandshakeType)incomingMessage[0].Buffer[0]; switch (handshakeType) { case HandshakeType.ClientHello: OnClientHello(incomingMessage, outgoingMessages); break; case HandshakeType.ServerHello: OnServerHello(incomingMessage, outgoingMessages); break; case HandshakeType.Certificate: OnCertificate(incomingMessage, outgoingMessages); break; case HandshakeType.ServerHelloDone: OnServerHelloDone(incomingMessage, outgoingMessages); break; case HandshakeType.ClientKeyExchange: OnClientKeyExchange(incomingMessage, outgoingMessages); break; case HandshakeType.Finished: OnFinished(incomingMessage, outgoingMessages); break; default: throw new ArgumentOutOfRangeException(); } m_lastReceivedMessage = handshakeType; return m_done; }
private void OnClientHello(NetMQMessage incomingMessage, OutgoingMessageBag outgoingMessages) { if (m_lastReceivedMessage != HandshakeType.HelloRequest || m_lastSentMessage != HandshakeType.HelloRequest) { throw new NetMQSecurityException(NetMQSecurityErrorCode.HandshakeUnexpectedMessage, "Client Hello received when expecting another message"); } HashLocalAndRemote(incomingMessage); ClientHelloMessage clientHelloMessage = new ClientHelloMessage(); clientHelloMessage.SetFromNetMQMessage(incomingMessage); SecurityParameters.ClientRandom = clientHelloMessage.RandomNumber; AddServerHelloMessage(outgoingMessages, clientHelloMessage.CipherSuites); AddCertificateMessage(outgoingMessages); AddServerHelloDone(outgoingMessages); }
private void OnCertificate(NetMQMessage incomingMessage, OutgoingMessageBag outgoingMessages) { if (m_lastReceivedMessage != HandshakeType.ServerHello || m_lastSentMessage != HandshakeType.ClientHello) { throw new NetMQSecurityException(NetMQSecurityErrorCode.HandshakeUnexpectedMessage, "Certificate received when expecting another message"); } HashLocalAndRemote(incomingMessage); CertificateMessage certificateMessage = new CertificateMessage(); certificateMessage.SetFromNetMQMessage(incomingMessage); if (!VerifyCertificate(certificateMessage.Certificate)) { throw new NetMQSecurityException(NetMQSecurityErrorCode.HandshakeUnexpectedMessage, "Unable to verify certificate"); } RemoteCertificate = certificateMessage.Certificate; }
private void OnServerHelloDone(NetMQMessage incomingMessage, OutgoingMessageBag outgoingMessages) { if (m_lastReceivedMessage != HandshakeType.Certificate || m_lastSentMessage != HandshakeType.ClientHello) { throw new NetMQSecurityException(NetMQSecurityErrorCode.HandshakeUnexpectedMessage, "Server Hello Done received when expecting another message"); } HashLocalAndRemote(incomingMessage); ServerHelloDoneMessage serverHelloDoneMessage = new ServerHelloDoneMessage(); serverHelloDoneMessage.SetFromNetMQMessage(incomingMessage); AddClientKeyExchange(outgoingMessages); InvokeChangeCipherSuite(); AddFinished(outgoingMessages); }
private void OnServerHello(NetMQMessage incomingMessage, OutgoingMessageBag outgoingMessages) { if (m_lastReceivedMessage != HandshakeType.HelloRequest || m_lastSentMessage != HandshakeType.ClientHello) { throw new NetMQSecurityException(NetMQSecurityErrorCode.HandshakeUnexpectedMessage, "Server Hello received when expecting another message"); } HashLocalAndRemote(incomingMessage); ServerHelloMessage serverHelloMessage = new ServerHelloMessage(); serverHelloMessage.SetFromNetMQMessage(incomingMessage); SecurityParameters.ServerRandom = serverHelloMessage.RandomNumber; SetCipherSuite(serverHelloMessage.CipherSuite); }
private void OnHelloRequest(OutgoingMessageBag outgoingMessages) { ClientHelloMessage clientHelloMessage = new ClientHelloMessage(); clientHelloMessage.RandomNumber = new byte[RandomNumberLength]; m_rng.GetBytes(clientHelloMessage.RandomNumber); SecurityParameters.ClientRandom = clientHelloMessage.RandomNumber; clientHelloMessage.CipherSuites = AllowedCipherSuites; NetMQMessage outgoingMessage = clientHelloMessage.ToNetMQMessage(); HashLocalAndRemote(outgoingMessage); outgoingMessages.AddHandshakeMessage(outgoingMessage); m_lastSentMessage = HandshakeType.ClientHello; }
private void OnFinished(NetMQMessage incomingMessage, OutgoingMessageBag outgoingMessages) { if ( (SecurityParameters.Entity == ConnectionEnd.Client && (!m_secureChannel.ChangeSuiteChangeArrived || m_lastReceivedMessage != HandshakeType.ServerHelloDone || m_lastSentMessage != HandshakeType.Finished)) || (SecurityParameters.Entity == ConnectionEnd.Server && (!m_secureChannel.ChangeSuiteChangeArrived || m_lastReceivedMessage != HandshakeType.ClientKeyExchange || m_lastSentMessage != HandshakeType.ServerHelloDone))) { throw new NetMQSecurityException(NetMQSecurityErrorCode.HandshakeUnexpectedMessage, "Finished received when expecting another message"); } if (SecurityParameters.Entity == ConnectionEnd.Server) { HashLocal(incomingMessage); } FinishedMessage finishedMessage = new FinishedMessage(); finishedMessage.SetFromNetMQMessage(incomingMessage); m_remoteHash.TransformFinalBlock(new byte[0], 0, 0); byte[] seed = m_remoteHash.Hash; m_remoteHash.Dispose(); m_remoteHash = null; string label; if (SecurityParameters.Entity == ConnectionEnd.Client) { label = ServerFinishedLabel; } else { label = ClientFinshedLabel; } byte[] verifyData = PRF.Get(SecurityParameters.MasterSecret, label, seed, FinishedMessage.VerifyDataLength); if (!verifyData.SequenceEqual(finishedMessage.VerifyData)) { throw new NetMQSecurityException(NetMQSecurityErrorCode.HandshakeVerifyData, "peer verify data wrong"); } if (SecurityParameters.Entity == ConnectionEnd.Server) { AddFinished(outgoingMessages); } m_done = true; }
private void OnClientKeyExchange(NetMQMessage incomingMessage, OutgoingMessageBag outgoingMessages) { if (m_lastReceivedMessage != HandshakeType.ClientHello || m_lastSentMessage != HandshakeType.ServerHelloDone) { throw new NetMQSecurityException(NetMQSecurityErrorCode.HandshakeUnexpectedMessage, "Client Key Exchange received when expecting another message"); } HashLocalAndRemote(incomingMessage); ClientKeyExchangeMessage clientKeyExchangeMessage = new ClientKeyExchangeMessage(); clientKeyExchangeMessage.SetFromNetMQMessage(incomingMessage); RSACryptoServiceProvider rsa = LocalCertificate.PrivateKey as RSACryptoServiceProvider; byte[] premasterSecret = rsa.Decrypt(clientKeyExchangeMessage.EncryptedPreMasterSecret, false); GenerateMasterSecret(premasterSecret); InvokeChangeCipherSuite(); }
private void AddCertificateMessage(OutgoingMessageBag outgoingMessages) { CertificateMessage certificateMessage = new CertificateMessage(); certificateMessage.Certificate = LocalCertificate; NetMQMessage outgoingMessage = certificateMessage.ToNetMQMessage(); HashLocalAndRemote(outgoingMessage); outgoingMessages.AddHandshakeMessage(outgoingMessage); m_lastSentMessage = HandshakeType.Certificate; }
private void AddServerHelloDone(OutgoingMessageBag outgoingMessages) { ServerHelloDoneMessage serverHelloDoneMessage = new ServerHelloDoneMessage(); NetMQMessage outgoingMessage = serverHelloDoneMessage.ToNetMQMessage(); HashLocalAndRemote(outgoingMessage); outgoingMessages.AddHandshakeMessage(outgoingMessage); m_lastSentMessage = HandshakeType.ServerHelloDone; }
private void AddClientKeyExchange(OutgoingMessageBag outgoingMessages) { ClientKeyExchangeMessage clientKeyExchangeMessage = new ClientKeyExchangeMessage(); byte[] premasterSecret = new byte[ClientKeyExchangeMessage.PreMasterSecretLength]; m_rng.GetBytes(premasterSecret); RSACryptoServiceProvider rsa = RemoteCertificate.PublicKey.Key as RSACryptoServiceProvider; clientKeyExchangeMessage.EncryptedPreMasterSecret = rsa.Encrypt(premasterSecret, false); GenerateMasterSecret(premasterSecret); NetMQMessage outgoingMessage = clientKeyExchangeMessage.ToNetMQMessage(); HashLocalAndRemote(outgoingMessage); outgoingMessages.AddHandshakeMessage(outgoingMessage); m_lastSentMessage = HandshakeType.ClientKeyExchange; }
/// <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); }