/// <summary> /// Processes a complete handshake message from server. /// </summary> /// <param name="message">Deserialized WireMessage that contains a plain or encrypted Session ID</param> private void ProcessCompleteHandshakeMessage(WireMessage message) { if (MessageEncryption) { var signedMessageData = Serializer.Deserialize <SignedMessageData>(message.Data); var encryptedSecret = Serializer.Deserialize <EncryptedSecret>(signedMessageData.MessageRawData); _serverPublicKeyBlob = encryptedSecret.SendersPublicKeyBlob; if (!RsaSignature.VerifySignature( keySize: _keyPair?.KeySize ?? 0, sendersPublicKeyBlob: _serverPublicKeyBlob, rawData: signedMessageData.MessageRawData, signature: signedMessageData.Signature)) { throw new SecurityException("Verification of message signature failed."); } _sessionId = new Guid( RsaKeyExchange.DecrpytSecret( keySize: _config.KeySize, // ReSharper disable once PossibleNullReferenceException receiversPrivateKeyBlob: _keyPair.PrivateKey, encryptedSecret: encryptedSecret)); } else { _sessionId = new Guid(message.Data); } _handshakeCompletedWaitHandle.Set(); }
/// <summary> /// Creates a new instance of the RemotingSession class. /// </summary> /// <param name="keySize">Key size of the RSA keys for asymmetric encryption</param> /// <param name="clientPublicKey">Public key of this session's client</param> /// <param name="server">Server instance, that hosts this session</param> /// <param name="rawMessageTransport">Component, that does the raw message transport (send and receive)</param> internal RemotingSession(int keySize, byte[] clientPublicKey, IRemotingServer server, IRawMessageTransport rawMessageTransport) { _sessionId = Guid.NewGuid(); _lastActivityTimestamp = DateTime.Now; _isAuthenticated = false; _keyPair = new RsaKeyPair(keySize); CreatedOn = DateTime.Now; _remoteDelegateInvocationEventAggregator = new RemoteDelegateInvocationEventAggregator(); _server = server ?? throw new ArgumentNullException(nameof(server)); _delegateProxyFactory = _server.ServiceRegistry.GetService <IDelegateProxyFactory>(); _delegateProxyCache = new ConcurrentDictionary <Guid, IDelegateProxy>(); _rawMessageTransport = rawMessageTransport ?? throw new ArgumentNullException(nameof(rawMessageTransport)); _clientPublicKeyBlob = clientPublicKey; _rawMessageTransport.ReceiveMessage += OnReceiveMessage; _rawMessageTransport.ErrorOccured += OnErrorOccured; MessageEncryption = clientPublicKey != null; WireMessage completeHandshakeMessage; if (MessageEncryption) { var encryptedSessionId = RsaKeyExchange.EncryptSecret( keySize: _server.SessionRepository.KeySize, receiversPublicKeyBlob: clientPublicKey, secretToEncrypt: _sessionId.ToByteArray(), sendersPublicKeyBlob: _keyPair.PublicKey); var rawContent = _server.Serializer.Serialize(encryptedSessionId); var signedMessageData = new SignedMessageData() { MessageRawData = rawContent, Signature = RsaSignature.CreateSignature( keySize: keySize, sendersPrivateKeyBlob: _keyPair.PrivateKey, rawData: rawContent) }; var rawData = _server.Serializer.Serialize(typeof(SignedMessageData), signedMessageData); completeHandshakeMessage = new WireMessage { MessageType = "complete_handshake", Data = rawData }; } else { completeHandshakeMessage = new WireMessage { MessageType = "complete_handshake", Data = _sessionId.ToByteArray() }; } _remoteDelegateInvocationEventAggregator.RemoteDelegateInvocationNeeded += (delegateType, uniqueCallKey, handlerKey, arguments) => { var sharedSecret = MessageEncryption ? _sessionId.ToByteArray() : null; var remoteDelegateInvocationMessage = new RemoteDelegateInvocationMessage { UniqueCallKey = uniqueCallKey, HandlerKey = handlerKey, DelegateArguments = arguments }; var remoteDelegateInvocationWebsocketMessage = _server.MessageEncryptionManager .CreateWireMessage( serializedMessage: _server.Serializer.Serialize(remoteDelegateInvocationMessage), serializer: _server.Serializer, sharedSecret: sharedSecret, keyPair: _keyPair, messageType: "invoke"); // Invoke remote delegate on client _rawMessageTransport.SendMessage( _server.Serializer.Serialize(remoteDelegateInvocationWebsocketMessage)); return(null); }; _rawMessageTransport.SendMessage(_server.Serializer.Serialize(completeHandshakeMessage)); }