コード例 #1
0
        internal async Task <string> ReceiveShortSingleMessageAsync(UserCertificate senderUserCertificate)
        {
            if (Logger.WriteToLog_detail_enabled)
            {
                Logger.WriteToLog_detail(">>InviteSession.ReceiveShortSingleMessageAsync()");
            }
            if (!DerivedDirectChannelSharedDhSecretsAE)
            {
                throw new InvalidOperationException("DerivedDirectChannelSharedDhSecretsAE = false");
            }

            var messageSession = new MessageSession();

            // wait for msgstart
            if (Logger.WriteToLog_detail_enabled)
            {
                Logger.WriteToLog_detail("waiting for MSGSTART");
            }
            var messageStartUdpData = await _localDrpPeer.Engine.OptionallySendUdpRequestAsync_Retransmit_WaitForResponse("msgstart 480", "remote user", null, RemoteSessionDescription.DirectChannelEndPoint,
                                                                                                                          MessageStartPacket.GetScanner(LocalDirectChannelToken32, this) // scanner verifies MessageHMAC
                                                                                                                          );

            var messageStart = MessageStartPacket.Decode(messageStartUdpData);

            if (Logger.WriteToLog_detail_enabled)
            {
                Logger.WriteToLog_detail("decoded MSGSTART");
            }

            messageSession.DeriveKeys(_localDrpPeer.CryptoLibrary, SharedPingPongHmacKey, messageStart, DirectChannelSharedDhSecret);

            // decrypt
            var receivedMessage = messageSession.DecryptShortSingleMessage(_localDrpPeer.CryptoLibrary, messageStart.EncryptedMessageData);

            // respond with msgack + ReceiverFinalNonce
            if (messageSession.Status != MessageSessionStatusCode.encryptionDecryptionCompleted)
            {
                throw new InvalidOperationException();
            }
            var messageAck = new MessageAckPacket
            {
                MessageId32        = messageStart.MessageId32,
                ReceiverStatus     = messageSession.Status,
                ReceiverFinalNonce = _localDrpPeer.CryptoLibrary.GetRandomBytes(MessageAckPacket.ReceiverFinalNonceSize),
            };

            messageAck.MessageHMAC = GetMessageHMAC(messageAck.GetSignedFieldsForMessageHMAC);
            var messageAckUdpData = messageAck.Encode();

            if (Logger.WriteToLog_detail_enabled)
            {
                Logger.WriteToLog_detail("responding with MSGACK to MSGSTART");
            }
            _localDrpPeer.Engine.RespondToRequestAndRetransmissions(messageStart.DecodedUdpData, messageAckUdpData, RemoteSessionDescription.DirectChannelEndPoint);

            // wait for msgpart with status=encryptionDecryptionCompleted
            if (Logger.WriteToLog_detail_enabled)
            {
                Logger.WriteToLog_detail("waiting for with MSGPART");
            }
            var messagePartUdpData = await _localDrpPeer.Engine.OptionallySendUdpRequestAsync_Retransmit_WaitForResponse("msgpart 42486", "remote user", null,
                                                                                                                         RemoteSessionDescription.DirectChannelEndPoint,
                                                                                                                         MessagePartPacket.GetScanner(messageStart.MessageId32, this, MessageSessionStatusCode.encryptionDecryptionCompleted)
                                                                                                                         // scanner verifies MessageHMAC
                                                                                                                         );

            var messagePart = MessagePartPacket.Decode(messagePartUdpData);

            // verify signature of sender user
            if (!messagePart.SenderSignature.Verify(_localDrpPeer.CryptoLibrary, w =>
            {
                w.Write(MessageHMACkey);
                w.Write(messageSession.AesKey);
                w.Write(messageStart.EncryptedMessageData);
                w.Write(messageAck.ReceiverFinalNonce);
            }, senderUserCertificate))
            {
                throw new BadSignatureException("bad MSGPART sender signature 3408");
            }
            if (Logger.WriteToLog_detail_enabled)
            {
                Logger.WriteToLog_detail("verified sender signature");
            }

            // send msgack status=finalSignatureVerified
            messageSession.Status = MessageSessionStatusCode.finalSignatureVerified;
            var messageAck_finalSignatureVerified = new MessageAckPacket
            {
                MessageId32    = messageStart.MessageId32,
                ReceiverStatus = messageSession.Status,
            };

            messageAck_finalSignatureVerified.MessageHMAC = GetMessageHMAC(messageAck_finalSignatureVerified.GetSignedFieldsForMessageHMAC);
            var messageAck_finalSignatureVerified_UdpData = messageAck_finalSignatureVerified.Encode();

            if (Logger.WriteToLog_detail_enabled)
            {
                Logger.WriteToLog_detail("sending MSGACK response to MSGPART");
            }
            _localDrpPeer.Engine.RespondToRequestAndRetransmissions(messagePart.DecodedUdpData, messageAck_finalSignatureVerified_UdpData, RemoteSessionDescription.DirectChannelEndPoint);

            return(receivedMessage);
        }