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); }
internal async Task SendShortSingleMessageAsync(string messageText, UserCertificate senderUserCertificateWithPrivateKeys) { if (!DerivedDirectChannelSharedDhSecretsAE) { throw new InvalidOperationException("DerivedDirectChannelSharedDhSecretsAE = false"); } if (Logger.WriteToLog_detail_enabled) { Logger.WriteToLog_detail(">> InviteSession.SendShortSingleMessageAsync()"); } var messageSession = new MessageSession(); var messageStart = new MessageStartPacket() { MessageId32 = (uint)_insecureRandom.Next(), DirectChannelToken32 = RemoteSessionDescription.DirectChannelToken32, MessageTimestamp64 = _localDrpPeer.Engine.Timestamp64, }; messageSession.DeriveKeys(_localDrpPeer.CryptoLibrary, SharedPingPongHmacKey, messageStart, DirectChannelSharedDhSecret); messageStart.EncryptedMessageData = messageSession.EncryptShortSingleMessage(_localDrpPeer.CryptoLibrary, messageText); // sign with HMAC messageStart.MessageHMAC = GetMessageHMAC(w => messageStart.GetSignedFieldsForMessageHMAC(w, true)); // send msgstart, wait for msgack var messageStartUdpData = messageStart.Encode(); if (Logger.WriteToLog_detail_enabled) { Logger.WriteToLog_detail("sending MSGSTART and waiting for MSGACK"); } var messageAckUdpData = await _localDrpPeer.Engine.OptionallySendUdpRequestAsync_Retransmit_WaitForResponse("msgstart 4582", "remote user", messageStartUdpData, RemoteSessionDescription.DirectChannelEndPoint, MessageAckPacket.GetScanner(messageStart.MessageId32, this, MessageSessionStatusCode.encryptionDecryptionCompleted) // scanner also verifies HMAC ); var messageAck = MessageAckPacket.Decode(messageAckUdpData); if (Logger.WriteToLog_detail_enabled) { Logger.WriteToLog_detail("decoded MSGACK"); } // send msgpart with status=encryptionDecryptionCompleted and signature if (messageSession.Status != MessageSessionStatusCode.encryptionDecryptionCompleted) { throw new InvalidOperationException(); } var messagePart = new MessagePartPacket { MessageId32 = messageStart.MessageId32, SenderStatus = messageSession.Status, SenderSignature = UserCertificateSignature.Sign(_localDrpPeer.CryptoLibrary, w => { w.Write(MessageHMACkey); w.Write(messageSession.AesKey); w.Write(messageStart.EncryptedMessageData); w.Write(messageAck.ReceiverFinalNonce); }, senderUserCertificateWithPrivateKeys) }; messagePart.MessageHMAC = GetMessageHMAC(messagePart.GetSignedFieldsForMessageHMAC); var messagePartUdpData = messagePart.Encode(); // wait for msgack status=finalSignatureVerified if (Logger.WriteToLog_detail_enabled) { Logger.WriteToLog_detail("sending MSGPART with message data, waiting for MSGACK"); } await _localDrpPeer.Engine.OptionallySendUdpRequestAsync_Retransmit_WaitForResponse("msgpart 3681", "remote user", messagePartUdpData, RemoteSessionDescription.DirectChannelEndPoint, MessageAckPacket.GetScanner(messageStart.MessageId32, this, MessageSessionStatusCode.finalSignatureVerified) // scanner also verifies HMAC ); }