//Converts JSON object into byte array object containing representing C# JSON object // with the sender name and message public static byte[] buildMessageBytes(JObject dataToGetBytes, CryptographicKey encryptionKey = null) { string objectString = dataToGetBytes.ToString(); if (encryptionKey == null) { return(System.Text.Encoding.UTF8.GetBytes(objectString)); } else { return(System.Text.Encoding.UTF8.GetBytes(AppServices.EncryptString(objectString, encryptionKey))); } }
public static JObject decodeMessageBytes(byte[] update, CryptographicKey encryptionKey = null) { string dataString = System.Text.Encoding.UTF8.GetString(update, 0, update.Length); if (encryptionKey == null) { return(JObject.Parse(dataString)); } else { return(JObject.Parse(AppServices.DecryptString(dataString, encryptionKey))); } //return new MessageBuilder(jsonObj["sender"].ToString(), jsonObj["message"].ToString()); }
/* This function will be used to send JSON objects (JObjects) with the following format Keys: * string updateType: This will be one of the following choices: * "chat" if we are receiving a new chat message. * "onlineStatus" if a friend is notifying us of an online status change * "ipInfo" if this contains information about the friends IP address and port * "request" if this contains information about a new friend request or update to a friend request or friend relationship * * var data: This will be different types of data depending on the update type: * "chat" - this will be a string containing the message * "onlineStatus" - this will be a bool onlineStatus and a string sessionID * "ipInfo" - this will be 2 strings ipAddr and port. * "request" - this will be a string requestStatus, if we have no pending requests already from the sender (either ones we sent or received) * then this is a new friend request and the string will be "new". If a friend accepted our request this will be "accepted" * If a friend removed us from their list then this will be "removed" */ public async void onPrivateUpdateReceived(string sender, byte[] update, bool fromUdp) { FriendsListEntry sendingFriend = AppServices.friendsData.FindFriend(sender); JObject updateData; // Decrypt the data using the session key if we have one already or the default if we have no session with the sender if (sendingFriend != null && sendingFriend.sessionEstablished) { updateData = MessageBuilder.decodeMessageBytes(update, sendingFriend.encryptionKey); } else { updateData = MessageBuilder.decodeMessageBytes(update, AppServices.defaultEncryptionKey); } string updateType = updateData["updateType"].ToString(); if (updateType.Equals("chat")) { string chatMessage = updateData["message"].ToString(); // The currently open chat is the one we are receiving a message from we do not need to update the unread count if (sender.Equals(AppServices.friendsData.currFriendsName)) { await AppServices.friendsData._page.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => { FriendsListEntry currFriend = AppServices.friendsData.FindFriend(sender); currFriend.history.Add(new ChatEntry() { message = chatMessage, sender = sender }); }); } else { await AppServices.friendsData._page.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => { FriendsListEntry currFriend = AppServices.friendsData.FindFriend(sender); int currUnreadCount = System.Convert.ToInt32(currFriend.unreadCount); currUnreadCount++; currFriend.unreadCount = currUnreadCount.ToString(); currFriend.history.Add(new ChatEntry() { message = chatMessage, sender = sender }); }); } } // A friend has sent a change in their online status so we get the data and update the friendsList in the ViewModel else if (updateType.Equals("onlineStatus")) { bool friendOnlineStatus = (bool)JsonConvert.DeserializeObject(updateData["onlineStatus"].ToString(), typeof(bool)); string friendSessionID = updateData["sessionID"].ToString(); //_page.PrintMessageAsync("Received new status update\n" + "Sender: " + sender + "\nOnline: " + friendOnlineStatus.ToString()); await AppServices.friendsData._page.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => { FriendsListEntry friend = AppServices.friendsData.FindFriend(sender); friend.isOnline = friendOnlineStatus; friend.sessionID = friendSessionID; // If we are chatting with the current user and they logout then we disable the send button if (AppServices.friendsData.currFriendsName != null && AppServices.friendsData.currFriendsName.Equals(friend.username)) { if (friendOnlineStatus == false) { AppServices.friendsData.sendButtonEnabled = false; } } }); } else if (updateType.Equals("ipInfo")) { } else if (updateType.Equals("request")) { string requestStatus = updateData["requestStatus"].ToString(); // This is a new friend request so add it to the request list if (requestStatus.Equals("new")) { await AppServices.mainPage.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => { AppServices.friendsData.friendRequests.Add(new FriendRequest() { username = sender }); AppServices.mainPage.DisplayFriendRequestsList(); }); } // This will be an accepted friend request so add them to the friends list and check if they are online else if (requestStatus.Equals("accepted")) { AppServices.operationComplete = false; AppServices.isFriendOnline = false; string encryptedName = AppServices.EncryptString(sender, AppServices.secretKey); AppServices.sessionService.GetSession(encryptedName, false, new GetFriendSessionCallback(encryptedName)); while (AppServices.operationComplete == false) { ; } // The friend is online if (AppServices.operationSuccessful && AppServices.isFriendOnline) { await AppServices.mainPage.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => { //AppServices.friendsData.friendsList.Add(new FriendsListEntry() { username = sender, isOnline = true }); AppServices.mainPage.DisplayFriendsList(); }); } // The friend is offline else { await AppServices.mainPage.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => { AppServices.friendsData.friendsList.Add(new FriendsListEntry() { username = sender, isOnline = false }); AppServices.mainPage.DisplayFriendsList(); }); } } // This is a remove request when a friend has removed the local user from their friends list else { await AppServices.mainPage.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => { AppServices.friendsData.friendsList.Remove(AppServices.friendsData.FindFriend(sender)); AppServices.mainPage.DisplayFriendsList(); }); } } // A friend is informing us that they are establishing a secure session with us so we should generate an encryption key else if (updateType.Equals("session")) { // If I already have a session this is a duplicate if (sendingFriend.sessionEstablished) { return; } int compareResult = string.Compare(AppServices.localUsernameEncrypted, sendingFriend.encryptedUsername); // Use my session ID as the encryption key if (compareResult > 0) { IBuffer keyBuff = CryptographicBuffer.ConvertStringToBinary(AppServices.localSessionId, BinaryStringEncoding.Utf8); await AppServices.friendsData._page.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => { sendingFriend.encryptionKey = AppServices.encryptionAlgorithim.CreateSymmetricKey(keyBuff); sendingFriend.sessionEstablished = true; sendingFriend.chatButtonsVisible = false; }); } // Use friend's session ID as the encryption key else { IBuffer keyBuff = CryptographicBuffer.ConvertStringToBinary(sendingFriend.sessionID, BinaryStringEncoding.Utf8); CoreDispatcher dispatcher = AppServices.friendsData._page.Dispatcher; await dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => { sendingFriend.encryptionKey = AppServices.encryptionAlgorithim.CreateSymmetricKey(keyBuff); sendingFriend.sessionEstablished = true; sendingFriend.chatButtonsVisible = false; }); } } }
private async void loginButton_Click(object sender, RoutedEventArgs e) { // Set the progress indicator, disable input, and authenticate the username and password entered by the user if it is not empty if (string.IsNullOrWhiteSpace(usernameTextBox.Text) == false && string.IsNullOrWhiteSpace(passwordBox.Password) == false) { /***** Authenticate the input *****/ if (AppServices.app42Authenticated) { AppServices.app42Authenticated = false; } // Disable Input, Set the status message, and set the AsyncOperationSuccess variable to false this.StartAsyncOperations("Authenticating..."); AppServices.localUsername = usernameTextBox.Text; AppServices.localUsernameEncrypted = AppServices.EncryptString(AppServices.localUsername, AppServices.secretKey); string encryptedPassword = AppServices.EncryptString(passwordBox.Password, AppServices.secretKey); AppServices.userService.Authenticate(AppServices.localUsernameEncrypted, encryptedPassword, new LoginCallback(this)); // Wait for Authentication to complete await Task.Run(() => { while (AppServices.app42Authenticated == false) { ; } }); // If the Authentication failed. Enable input and show an error message if (AppServices.operationSuccessful == false) { AppServices.app42Authenticated = false; this.EndAsyncOperationsError(); return; } // Temporary: Print the connection state and wait for a few seconds //AppServices.warpClient.GetConnectionState(); /***** Create a session for the authenticated user *****/ if (AppServices.app42LoggedIn) { AppServices.app42LoggedIn = false; AppServices.sessionService.Invalidate(AppServices.localSessionId, new LogoutSessionCallback()); } // Reset the operation status before starting the next operation this.StartAsyncOperations("Creating a session..."); // Create a session for the local user if (AppServices.app42LoggedIn == false) { AppServices.sessionService.GetSession(AppServices.localUsernameEncrypted, true, new LoginSessionCallback(this)); } // Wait for creating a session to complete await Task.Run(() => { while (AppServices.app42LoggedIn == false) { ; } }); if (AppServices.operationSuccessful == false) { AppServices.app42LoggedIn = false; this.EndAsyncOperationsError(); return; } /***** Load App42 Friends for the authenticated user *****/ // Load the friends list from the App42 Database, then get which friends are online, then send all the online friends an update // telling them that you have signed on if (AppServices.app42LoadedFriends) { AppServices.app42LoadedFriends = false; AppServices.friendsData.friendsList.Clear(); } this.StartAsyncOperations("Loading friends list..."); AppServices.friendsData.GetFriendsFromCloud(); await Task.Run(() => { while (AppServices.app42LoadedFriends == false) { ; } }); if (AppServices.operationSuccessful == false) { AppServices.app42LoadedFriends = false; this.EndAsyncOperationsError(); return; } AppServices.app42LoadedFriends = false; this.StartAsyncOperations("Getting friends online statuses"); if (AppServices.friendsData.friendsList.Count > 0) { foreach (FriendsListEntry friend in AppServices.friendsData.friendsList) { AppServices.sessionService.GetSession(friend.encryptedUsername, false, new GetFriendSessionsCallback(friend.username)); } await Task.Run(() => { while (AppServices.app42LoadedFriends == false) { ; } }); if (AppServices.operationSuccessful == false) { AppServices.app42LoadedFriends = false; this.EndAsyncOperationsError(); return; } } else { AppServices.app42LoadedFriends = true; } /***** Load friend requests for the user *****/ if (AppServices.app42LoadedRequests) { AppServices.app42LoadedRequests = false; AppServices.friendsData.friendRequests.Clear(); } this.StartAsyncOperations("Loading friend requests..."); AppServices.friendsData.GetFriendRequestsFromCloud(); await Task.Run(() => { while (AppServices.app42LoadedRequests == false) { ; } }); if (AppServices.operationSuccessful == false) { AppServices.app42LoadedRequests = false; this.EndAsyncOperationsError(); return; } // If we reach this point then both authentication and creating a session were successful so we // go to the next page this.Frame.Navigate(typeof(MainPage)); } else { PrintMessage("ERROR: Username and/or Password cannnot be empty. Please try again."); } }
private async void addFriendButton_Click(object sender, RoutedEventArgs e) { this.StartAsyncOperations("Sending friend request..."); string friendNameEncrypted = AppServices.EncryptString(friendUsernameBox.Text, AppServices.secretKey); AppServices.operationComplete = false; AppServices.buddyService.SendFriendRequest(AppServices.localUsernameEncrypted, friendNameEncrypted, "Friend Request", new FriendRequestCallback()); await Task.Run(() => { while (AppServices.operationComplete == false) { ; } }); if (AppServices.operationSuccessful == false) { this.EndAsyncOperationsError(); return; } // Once the friend request has been sent successfully we check if the user is online, and then send them an update to say they have a request AppServices.operationComplete = false; AppServices.isFriendOnline = false; this.StartAsyncOperations("Sending friend request..."); AppServices.sessionService.GetSession(friendNameEncrypted, false, new GetFriendSessionCallback()); await Task.Run(() => { while (AppServices.operationComplete == false) { ; } }); // An error occured and the friend may or may not be online. This is needed because the App42 callback will call the onException callback // even if no error occured but the friend is offline. We just use isFriendOnline to either mark an error occuring if the operation // wasn't successful. Or the friend's online status if the operation was successful if (AppServices.operationSuccessful == false && AppServices.isFriendOnline == true) { this.EndAsyncOperationsError(); return; } // The friend is online so send them an update saying there is a new friend request if (AppServices.operationSuccessful && AppServices.isFriendOnline) { AppServices.appWarpLastSentToUsername = friendUsernameBox.Text; AppServices.warpClient.sendPrivateUpdate(friendUsernameBox.Text, MessageBuilder.buildNewFriendRequestBytes(AppServices.defaultEncryptionKey)); //this.StartAsyncOperations("Sending friend request..."); //bool sendSuccessful = await AppServices.SendDataToUser(friendUsernameBox.Text, MessageBuilder.buildNewFriendRequestBytes()); //if (sendSuccessful == false) //{ // this.EndAsyncOperationsError(); /// return; //} } // The friend is offline this.EndAsyncOperationsSuccess(); return; }
// Check the form for errors and then register a new user with the App42 cloud user base private async void signUpButton_Click(object sender, RoutedEventArgs e) { // Disable the user from making any changes and check for errors DisableInput(); ClearErrorBoxes(); string nameErrorMsg = CheckInput(usernameBox.Text); string pwdErrorMsg = CheckInput(passwordBox.Password); string chkPwdErrorMsg = ""; if (confirmPasswordBox.Password.Equals(passwordBox.Password) == false) { chkPwdErrorMsg = "- Passwords do not match"; } // Check for email entry errors (different checks than the others so it has no function) UInt32 atCount = 0; string emailErrorMsg = ""; bool emailErrorOccured = false, firstBadChar = true; foreach (char c in emailBox.Text) { if (c.Equals('@')) { atCount++; } if (atCount > 1) { break; } } if (atCount != 1) { emailErrorOccured = true; emailErrorMsg = "- Incorrect format. Please use the format [email protected]"; } foreach (char c in badChars) { if (emailBox.Text.Contains(c) && c != '@') { // If this is not the first error, first add a newline if (emailErrorOccured) { emailErrorMsg += "\n"; } // Only add the error message part if this is the first bad character detected if (firstBadChar) { emailErrorMsg += "- Cannot contain character(s):"; firstBadChar = false; } emailErrorMsg += " " + c.ToString(); emailErrorOccured = true; } } if (string.IsNullOrWhiteSpace(emailBox.Text)) { if (emailErrorOccured) { emailErrorMsg += "\n"; } emailErrorMsg += "- Email cannot be empty or spaces."; emailErrorOccured = true; } // If there are errors, print the message and re-enable input. Otherwise register the user if (nameErrorMsg.Length > 0 || pwdErrorMsg.Length > 0 || chkPwdErrorMsg.Length > 0 || emailErrorOccured) { ShowErrorBoxes(nameErrorMsg, pwdErrorMsg, chkPwdErrorMsg, emailErrorMsg); PrintMessage("There are errors in the form. Please check your entries and try again."); EnableInput(); } else { // Clear the error boxes, setup the progress bar, and create a user ClearErrorBoxes(); SetProgressIndicator(true, "Encrypting your data"); // Encrypt the input in a different thread await this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { encryptedUsername = AppServices.EncryptString(usernameBox.Text, AppServices.secretKey); encryptedPassword = AppServices.EncryptString(passwordBox.Password, AppServices.secretKey); // Add @email.com to the encrypted email string so that it is recognized as valid encryptedEmail = AppServices.EncryptString(emailBox.Text, AppServices.secretKey) + "@email.com"; }); this.StartAsyncOperations("Connecting and registering..."); AppServices.operationComplete = false; AppServices.userService.CreateUser(encryptedUsername, encryptedPassword, encryptedEmail, new SignUpCallBack()); await Task.Run(() => { while (AppServices.operationComplete == false) { ; } }); if (AppServices.operationSuccessful) { this.Login(); return; } else { this.EndAsyncOperationsError(); return; } } }