예제 #1
0
        /// <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();
        }
예제 #2
0
        /// <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));
        }