private void button6_Click(object sender, EventArgs e) { const string webSiteName = "www.facebook.com/login"; string hashName = SessionCrypto.DigestMessage(webSiteName); Bitmap qrCode = qrCodeGenerator.GenerateQRCode($"storpw-{hashName}"); qrCodeGenerator.DismissIfOpen(); qrCodeGenerator.DisplayQRCode(qrCode, "Scan QR Code to store website credentials"); }
/// <summary> /// Check if the key sent by the device if correct /// </summary> /// <param name="logonKey">The key sent by the device</param> /// <returns>True if the keys match, otherwise false</returns> internal static bool IsLogonValid(string logonKey) { if (!File.Exists("logon.hash")) { return(false); } string digestedKey = SessionCrypto.DigestMessage(logonKey); string validLogonHash = File.ReadAllText("logon.hash"); return(validLogonHash == digestedKey); }
/// <summary> /// Create a new window logon key /// </summary> /// <returns>The non-hashed key to send to the device</returns> internal static string RegisterLogon() { if (File.Exists("logon.hash")) { return(null); } using (RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider()) { byte[] logonKey = new byte[32]; //32 bytes are 256 bits rng.GetBytes(logonKey); string strKey = Convert.ToBase64String(logonKey); string digestedKey = SessionCrypto.DigestMessage(strKey); File.WriteAllText("logon.hash", digestedKey); return(strKey); } }
/// <summary> /// Display a QR Code requsting to store a password on the android device /// </summary> /// <param name="url">The plain text url to store</param> /// <param name="username">The username to store</param> /// <param name="password">The password to store</param> internal void RequestPasswordStore(string url, string username, string password) { Action displayQRCode = new Action(() => { string hashName = SessionCrypto.DigestMessage(url); Bitmap qrCode = qrCodeGenerator.GenerateQRCode($"storpw-{hashName}"); qrCodeGenerator.DismissIfOpen(); qrCodeGenerator.DisplayQRCode(qrCode, "Scan QR Code to store website credentials"); qrCodeGenerator.PushToTop(); }); if (InvokeRequired) { Invoke(displayQRCode); } else { displayQRCode(); } }
/// <summary> /// Handle a full HTTP Request /// </summary> /// <param name="headers">Headers of the request</param> /// <param name="readObject">The client's session data</param> /// <param name="method">The method of the request</param> /// <param name="resource">The requested function</param> /// <param name="requestData">The body of the request</param> private void HandleRequest(List <string> headers, ReadObject readObject, string method, string resource, string requestData) { bool gotTracker = false; //True if client sent tracker in the headers //Check if client sent header foreach (string header in headers) { if (header.StartsWith("Client-Tracker")) { int delimiter = header.IndexOf(':') + 2; //The : and the space => 2 string value = header.Substring(delimiter); if (int.TryParse(value, out int tracker)) { lock (trackerLockObject) { if (trackers.TryGetValue(tracker, out ReadObject tempReadObject)) { readObject = tempReadObject; gotTracker = true; } else { Form1.WriteLine("Client not registered with this ID"); } } } else { Form1.WriteLine("Can't parse client tracker"); } break; } } if (method == "POST" && gotTracker) //POST Functions { if (resource == "stor-pw") //Store password on phone { string userName = null; string password = null; int userNameLength = int.Parse(requestData.Substring(0, 10)); userName = requestData.Substring(10, userNameLength); int passwordLength = int.Parse(requestData.Substring(10 + userNameLength, 10)); password = requestData.Substring(20 + userNameLength, passwordLength); string url = requestData.Substring(20 + userNameLength + passwordLength); if (password != null && userName != null) { Form1.WriteLine($"Requested Password Storage: usr:{userName} ; pwd:{password}; url:{url}"); readObject.urlHash = SessionCrypto.DigestMessage(url); readObject.userName = userName; readObject.password = password; ctx.RequestPasswordStore(url, userName, password); SendMessage(readObject.client, "stor-init"); } } else if (resource == "getpw") //Get password from phone { readObject.urlHash = SessionCrypto.DigestMessage(requestData); getPasswordQueue.Add(readObject.urlHash); ctx.RequestPasswordGet(readObject.urlHash); SendMessage(readObject.client, "ok"); } else if (resource == "getkey") { readObject.urlHash = SessionCrypto.DigestMessage(requestData); getKeyQueue.Add(readObject.urlHash); ctx.RequestKeyGet(readObject.urlHash); SendMessage(readObject.client, "get-ok"); } else if (resource == "pushkey") { int urlLength = int.Parse(requestData.Substring(0, 10)); string url = requestData.Substring(10, urlLength); int tokenLength = int.Parse(requestData.Substring(10 + urlLength, 10)); string token = requestData.Substring(20 + urlLength, tokenLength); readObject.urlHash = SessionCrypto.DigestMessage(url); storeKeyQueue.Add(readObject.urlHash); storeKeyQueue.UpdateExtraData(readObject.urlHash, token); ctx.RequestKeyStore(readObject.urlHash); SendMessage(readObject.client, "push-ok"); Form1.WriteLine($"ReadObject url hashed: {readObject.urlHash}"); } readObject.contentLength = 0; } else if (method == "GET") //Get functions { if (resource == "tracker") //Client requested a new tracker ID { lock (idLockerObject) { readObject.cTracker = clientTracker; SendMessage(readObject.client, clientTracker.ToString()); clientTracker++; } } else if (!gotTracker) //Drop if not setting tracker and tracker is not set { Form1.WriteLine("GET without tracker and not setting tracker"); } else if (resource == "stor-state") //Get the state of storing the password on the phone { CredentialTransferState state = (storeQueue.TryGetValue(readObject.urlHash, out CredentialTransferState cts)) ? cts : CredentialTransferState.Pending; string message; switch (state) { case CredentialTransferState.Success: message = "stor-completed"; break; case CredentialTransferState.Failed: message = "stor-fail"; break; default: message = "stor-pending"; break; } SendMessage(readObject.client, message); Form1.WriteLine("Stor get state"); } else if (resource == "get-state") //Get the state of getting hte password from the phone { CredentialTransferState qState = getPasswordQueue.GetQueueState(readObject.urlHash); switch (qState) { case CredentialTransferState.Success: object[] extraData = getPasswordQueue.GetQueueData(readObject.urlHash); Tuple <string, string> credentials = new Tuple <string, string>((string)extraData[0], (string)extraData[1]); getPasswordQueue.Remove(readObject.urlHash); SendMessage(readObject.client, $"get-ok{EncodeBodyData(new string[] { credentials.Item1, credentials.Item2 })}"); Form1.WriteLine("Password sent to browser"); break; case CredentialTransferState.Failed: SendMessage(readObject.client, "get-fail"); getPasswordQueue.Remove(readObject.urlHash); Form1.WriteLine("Password fail alert sent to the browser"); break; default: SendMessage(readObject.client, "get-pending"); break; } } else if (resource == "kget-state") { CredentialTransferState qState = getKeyQueue.GetQueueState(readObject.urlHash); switch (qState) { case CredentialTransferState.Success: object[] extraData = getKeyQueue.GetQueueData(readObject.urlHash); string keyToken = (string)extraData[0]; getKeyQueue.Remove(readObject.urlHash); SendMessage(readObject.client, $"get-ok{keyToken}"); Form1.WriteLine("Key sent to browser"); break; case CredentialTransferState.Failed: SendMessage(readObject.client, "get-fail"); getKeyQueue.Remove(readObject.urlHash); Form1.WriteLine("Key fail alert sent to the browser"); break; default: SendMessage(readObject.client, "get-pending"); break; } } else if (resource == "kpush-state") { Form1.WriteLine($"ReadObject url hash: {readObject.urlHash}"); Form1.WriteLine($"ReadObject client tracker: {readObject.cTracker}"); CredentialTransferState qState = storeKeyQueue.GetQueueState(readObject.urlHash); switch (qState) { case CredentialTransferState.Success: object[] extraData = storeKeyQueue.GetQueueData(readObject.urlHash); storeKeyQueue.Remove(readObject.urlHash); SendMessage(readObject.client, $"push-ok"); Form1.WriteLine("Key installed on android"); break; case CredentialTransferState.Failed: SendMessage(readObject.client, "push-fail"); storeKeyQueue.Remove(readObject.urlHash); Form1.WriteLine("Key install failed in android"); break; default: SendMessage(readObject.client, "push-pending"); break; } } readObject.contentLength = 0; } else if (method == "OPTIONS") { SendMessage(readObject.client, "", "\r\nAccess-Control-Allow-Headers: Client-Tracker"); Form1.WriteLine("Options response sent"); readObject.contentLength = 0; return; } else if (!gotTracker) //POST Request (or other?) without tracker { Form1.WriteLine("Tracker not sent with!"); readObject.contentLength = 0; return; } else //Invalid request but tracker is set? wierd { Form1.WriteLine("Invalid Request Type"); readObject.contentLength = 0; return; } //Store the session data lock (trackerLockObject) { if (trackers.ContainsKey(readObject.cTracker)) { trackers[readObject.cTracker] = readObject; } else { trackers.Add(readObject.cTracker, readObject); } } }