Exemple #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);
        }
Exemple #2
0
        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
                                                                                                );
        }