コード例 #1
0
        private async Task AcknowledgeMessageAsync(
            OpenVaspPayload payload,
            string symKey,
            string asymKey,
            string returnTopic = null)
        {
            var envelopeId = Guid.NewGuid().ToString("N");
            var ackPayload = new OpenVaspPayload(
                Instruction.Ack,
                _vaspId, // receiver becomes a sender
                payload.ConnectionId,
                envelopeId)
            {
                EnvelopeAck = payload.EnvelopeId
            };

            var ackEnvelope = new MessageEnvelope
            {
                Topic          = returnTopic ?? payload.ReturnTopic,
                EncryptionKey  = symKey ?? asymKey,
                EncryptionType = symKey != null ? EncryptionType.Symmetric : EncryptionType.Asymmetric,
            };

            await _outboundEnvelopeService.AcknowledgeAsync(ackEnvelope, ackPayload.ToString());

            _logger?.LogInformation(
                $"Sent ACK to {payload.Instruction} with topic {ackEnvelope.Topic} for connection {payload.ConnectionId} from {_vaspId} to {payload.SenderVaspId}");
        }
コード例 #2
0
        private async Task HandleAcceptMessageAsync(OpenVaspPayload payload)
        {
            var connection = _connections[payload.ConnectionId];

            if (connection == null)
            {
                throw new ArgumentException($"Connection with id '{payload.ConnectionId}' was not found");
            }

            var sharedSecret = ECDH_Key.ImportKey(connection.PrivateKey).GenerateSharedSecretHex(payload.EcdhPk);

            (connection.Filter, connection.SymKeyId) = await RegisterConnectionAsync(connection.InboundTopic, sharedSecret);

            connection.SharedPrivateEncryptionKey = sharedSecret;
            connection.OutboundTopic = payload.ReturnTopic;

            await AcknowledgeMessageAsync(
                payload,
                connection.SymKeyId,
                null);

            var senderVaspCode = payload.SenderVaspId.Substring(4, 8);
            var signingKey     = await _vaspCodesService.GetSigningKeyAsync(senderVaspCode);

            await TriggerAsyncEvent(TransportMessageReceived,
                                    new TransportMessageEvent
            {
                ConnectionId = payload.ConnectionId,
                SenderVaspId = payload.SenderVaspId,
                Instruction  = payload.Instruction,
                Payload      = payload.OvMessage,
                Timestamp    = DateTime.UtcNow,
                SigningKey   = signingKey
            });
        }
コード例 #3
0
        private async Task HandleMessageAsync(
            OpenVaspPayload payload,
            bool doAcknowledge,
            Func <Connection, bool> connectionUpdate = null)
        {
            var connection = _connections[payload.ConnectionId];

            if (connection == null)
            {
                throw new ArgumentException($"Connection with id '{payload.ConnectionId}' was not found");
            }

            var originalConnStatus = connection.Status;

            connectionUpdate?.Invoke(connection);;

            if (doAcknowledge)
            {
                var    symKeyId = originalConnStatus == ConnectionStatus.PartiallyActive ? null : connection.SymKeyId;
                string asymKey  = null;
                if (symKeyId == null)
                {
                    asymKey = payload.EcdhPk
                              ?? connection.CounterPartyPublicKey
                              ?? await _vaspCodesService.GetTransportKeyAsync(connection.CounterPartyVaspId.Substring(4));

                    asymKey = asymKey?.DecompressPublicKey().ToHex(true);
                }
                if (string.IsNullOrWhiteSpace(symKeyId) && string.IsNullOrWhiteSpace(asymKey))
                {
                    _logger?.LogWarning($"Can't sent ACK for {payload.Instruction} via connection {payload.ConnectionId}");
                }
                else
                {
                    await AcknowledgeMessageAsync(
                        payload,
                        symKeyId,
                        asymKey,
                        string.IsNullOrWhiteSpace(connection.SymKeyId) && string.IsNullOrWhiteSpace(payload.EcdhPk)
                        ?connection.CounterPartyVaspId.Substring(4)
                        : null);
                }
            }

            var senderVaspCode = payload.SenderVaspId.Substring(4, 8);
            var signingKey     = await _vaspCodesService.GetSigningKeyAsync(senderVaspCode);

            await TriggerAsyncEvent(TransportMessageReceived,
                                    new TransportMessageEvent
            {
                ConnectionId = payload.ConnectionId,
                SenderVaspId = payload.SenderVaspId,
                Instruction  = payload.Instruction,
                Payload      = payload.OvMessage,
                Timestamp    = DateTime.UtcNow,
                SigningKey   = signingKey
            });
        }
コード例 #4
0
 private Task HandleDenyMessageAsync(OpenVaspPayload payload)
 {
     return(HandleMessageAsync(
                payload,
                false,
                connectionUpdate: c =>
     {
         c.Status = ConnectionStatus.Passive;
         return true;
     }));
 }
コード例 #5
0
 private Task HandleCloseMessageAsync(OpenVaspPayload payload)
 {
     return(HandleMessageAsync(
                payload,
                true,
                c =>
     {
         c.Status = ConnectionStatus.Passive;
         return true;
     }));
 }
コード例 #6
0
        private async Task ProcessReceivedMessageAsync(
            string topic,
            string messagePayload)
        {
            var payload = OpenVaspPayload.Create(messagePayload);

            _logger?.LogInformation(
                $"Received {payload.Instruction} with topic {topic} for connection {payload.ConnectionId} from {payload.SenderVaspId} to {_vaspId}");

            switch (payload.Instruction)
            {
            case Instruction.Ack:
                await HandleAcknowledgementMessageAsync(payload);

                break;

            case Instruction.Invite:
                await HandleInviteMessageAsync(payload);

                break;

            case Instruction.Accept:
                await HandleAcceptMessageAsync(payload);

                break;

            case Instruction.Deny:
                await HandleDenyMessageAsync(payload);

                break;

            case Instruction.Update:
                await HandleUpdateMessageAsync(payload);

                break;

            case Instruction.Close:
                await HandleCloseMessageAsync(payload);

                break;

            default:
                throw new ArgumentOutOfRangeException();
            }

            if (!_openVaspPayloads.ContainsKey(payload.EnvelopeId))
            {
                _openVaspPayloads[payload.EnvelopeId] = payload;
            }
        }
コード例 #7
0
        private Task HandleUpdateMessageAsync(OpenVaspPayload payload)
        {
            return(HandleMessageAsync(
                       payload,
                       true,
                       c =>
            {
                if (c.Status != ConnectionStatus.PartiallyActive)
                {
                    return false;
                }

                c.Status = ConnectionStatus.Active;
                return true;
            }));
        }
コード例 #8
0
        private async Task HandleAcknowledgementMessageAsync(OpenVaspPayload payload)
        {
            await _outboundEnvelopeService.RemoveQueuedEnvelopeAsync(payload.EnvelopeAck);

            var ackedMessage = _openVaspPayloads[payload.EnvelopeAck];

            if (ackedMessage?.Instruction == Instruction.Close)
            {
                await DeactivateAsync(payload.ConnectionId);
            }

            var connection = _connections[payload.ConnectionId];

            if (connection == null)
            {
                throw new ArgumentException($"Connection with id '{payload.ConnectionId}' was not found");
            }
            if (connection.Status == ConnectionStatus.PartiallyActive)
            {
                connection.Status = ConnectionStatus.Active;
            }
        }
コード例 #9
0
        private async Task HandleInviteMessageAsync(OpenVaspPayload payload)
        {
            var senderVaspCode   = payload.SenderVaspId.Substring(4, 8);
            var vaspTransportKey = await _vaspCodesService.GetTransportKeyAsync(senderVaspCode);

            if (vaspTransportKey == null)
            {
                _logger?.LogError($"Transport key for vasp code {senderVaspCode} cannot be found during invitation processing");
                return;
            }

            _connections.TryGetValue(payload.ConnectionId, out var connection);
            if (connection != null)
            {
                bool isSameData = connection.CounterPartyVaspId == payload.SenderVaspId &&
                                  connection.OutboundTopic == payload.ReturnTopic;
                if (isSameData)
                {
                    _logger?.LogWarning(
                        $"Received invite for already existing connectionId {payload.ConnectionId} with the same data. Skipping.");

                    await AcknowledgeMessageAsync(
                        payload,
                        null,
                        payload.EcdhPk.DecompressPublicKey().ToHex(true));
                }
                else
                {
                    _logger?.LogWarning(
                        $"Received invite for already existing connectionId {payload.ConnectionId} with the different data:{Environment.NewLine}"
                        + $"SenderVaspId: {connection.CounterPartyVaspId} - {payload.SenderVaspId},{Environment.NewLine}"
                        + $"Topic: {connection.OutboundTopic} - {payload.ReturnTopic},{Environment.NewLine}");
                }
                return;
            }

            var topic        = TopicGenerator.GenerateConnectionTopic();
            var sessionKey   = ECDH_Key.GenerateKey();
            var sharedSecret = sessionKey.GenerateSharedSecretHex(payload.EcdhPk);

            var(filter, symKeyId) = await RegisterConnectionAsync(topic, sharedSecret);

            var newConnection = new Connection
            {
                Id                         = payload.ConnectionId,
                Filter                     = filter,
                InboundTopic               = topic,
                OutboundTopic              = payload.ReturnTopic,
                Status                     = ConnectionStatus.PartiallyActive,
                CounterPartyVaspId         = payload.SenderVaspId,
                SymKeyId                   = symKeyId,
                SharedPrivateEncryptionKey = sharedSecret,
                PrivateKey                 = sessionKey.PrivateKey,
                CounterPartyPublicKey      = payload.EcdhPk,
            };

            _connections[newConnection.Id] = newConnection;

            await AcknowledgeMessageAsync(
                payload,
                null,
                payload.EcdhPk.DecompressPublicKey().ToHex(true));

            var signingKey = await _vaspCodesService.GetSigningKeyAsync(senderVaspCode);

            await TriggerAsyncEvent(TransportMessageReceived,
                                    new TransportMessageEvent
            {
                ConnectionId = payload.ConnectionId,
                SenderVaspId = payload.SenderVaspId,
                Instruction  = payload.Instruction,
                Payload      = payload.OvMessage,
                Timestamp    = DateTime.UtcNow,
                SigningKey   = signingKey
            });
        }
コード例 #10
0
        public async Task SendAsync(string connectionId, string message, Instruction instruction, string receiverVaspId)
        {
            var connection = _connections[connectionId];

            var receiverVaspCode = (receiverVaspId ?? connection.CounterPartyVaspId).Substring(4, 8);

            var envelopeId = Guid.NewGuid().ToString("N");

            var payload = new OpenVaspPayload(
                instruction,
                _vaspId,
                connection.Id,
                envelopeId)
            {
                ReturnTopic = connection.InboundTopic,
                OvMessage   = message
            };

            if (instruction == Instruction.Invite || instruction == Instruction.Accept || instruction == Instruction.Deny)
            {
                payload.EcdhPk = ECDH_Key.ImportKey(connection.PrivateKey).PublicKey;
            }

            var topic = connection.OutboundTopic ?? receiverVaspCode;

            if (string.IsNullOrWhiteSpace(topic))
            {
                throw new InvalidOperationException($"Topic is empty for connection {connection.Id}");
            }

            var envelope = new MessageEnvelope
            {
                Topic = topic,
            };

            if (instruction == Instruction.Invite || instruction == Instruction.Close && string.IsNullOrWhiteSpace(connection.SymKeyId))
            {
                envelope.EncryptionType = EncryptionType.Asymmetric;

                var vaspTransportKey = await _vaspCodesService.GetTransportKeyAsync(receiverVaspCode);

                if (vaspTransportKey == null)
                {
                    throw new InvalidOperationException($"Transport key for vasp code {receiverVaspCode} cannot be found during message sending");
                }

                envelope.EncryptionKey = vaspTransportKey.DecompressPublicKey().ToHex(true);
            }
            else if (instruction == Instruction.Accept || instruction == Instruction.Deny ||
                     instruction == Instruction.Close && connection.Status == ConnectionStatus.PartiallyActive)
            {
                envelope.EncryptionType = EncryptionType.Asymmetric;
                envelope.EncryptionKey  = connection.CounterPartyPublicKey.DecompressPublicKey().ToHex(true);
            }
            else
            {
                envelope.EncryptionType = EncryptionType.Symmetric;
                envelope.EncryptionKey  = connection.SymKeyId;
            }

            var outboundEnvelope = new OutboundEnvelope
            {
                Id           = envelopeId,
                ConnectionId = connectionId,
                Envelope     = envelope,
                TotalResents = 0,
                Payload      = payload.ToString()
            };

            _openVaspPayloads[payload.EnvelopeId] = payload;

            await _outboundEnvelopeService.SendEnvelopeAsync(outboundEnvelope, instruction != Instruction.Deny);

            if (instruction == Instruction.Deny)
            {
                await DeactivateAsync(connectionId);
            }
        }