/********************************************************************************************************** * HashedPasswordDisplayWindow(HashedPassword) Password * Purpose: Constructor. * * Parameters: * HashedPassword Password * The Password to display. **********************************************************************************************************/ public HashedPasswordDisplayWindow(HashedPassword Password) { InitializeComponent(); uxPasswordDisplay.Text = Password.Password; uxDateDisplay.Text = Password.DateCreated.ToString(); uxSeedDisplay.Text = Password.Seed.ToString(); }
/********************************************************************************************************** * void uxNewHashedPasswordButton_Click(...) * Purpose: Creates a new hashed password and adds it to the displayed passwords. * * Parameters: * Standard MouseButtonEvent Parameters. **********************************************************************************************************/ private void uxNewHashedPasswordButton_Click(object sender, RoutedEventArgs e) { HashedPassword newPassword = Application.GeneratePassword(MasterPassword); HashedPasswordCompactDisplay newPasswordDispay = new HashedPasswordCompactDisplay(newPassword); newPasswordDispay.DeletePasswordEvent += DeletePasswordEventListener; uxHashedPassContainer.Children.Add(newPasswordDispay); }
/********************************************************************************************************** * UserData LoadUserData(string MasterPassword) * Purpose: Loads data, if it exists, from the disk. The data is encrypted using AES using the * master password's hash as the secret key. **********************************************************************************************************/ private UserData LoadUserData(string MasterPassword) { // Need 128 bits password for the encryption key. ApplicationEntry self = new ApplicationEntry("MasterPass", 128 / sizeof(char) / 8, 0, true, true, true, false); HashedPassword fileName = self.GeneratePassword(MasterPassword); HashedPassword aesKey = self.GeneratePassword(MasterPassword); HashedPassword aesIV = self.GeneratePassword(MasterPassword); System.Security.Cryptography.Aes aes = System.Security.Cryptography.Aes.Create(); // Even if aes is broken the master password is unrecoverable. aes.Key = Encoding.Unicode.GetBytes(aesKey.Password); aes.IV = Encoding.Unicode.GetBytes(aesIV.Password); aes.Padding = System.Security.Cryptography.PaddingMode.PKCS7; ICryptoTransform decryptor = aes.CreateDecryptor(); UserData loadedData = null; // If there is no data don't load it. if (File.Exists(fileName.Password + ".pass") == false) { return(loadedData); } // Open the file using (FileStream outputStream = new FileStream(fileName.Password + ".pass", FileMode.Open)) { // Use a safe to file encryption method using (CryptoStream csDecrypt = new CryptoStream(outputStream, decryptor, CryptoStreamMode.Read)) { // Convert the object to a byte array using (MemoryStream objectStream = new MemoryStream()) { byte[] buffer = new byte[1024]; int bytesRead = csDecrypt.Read(buffer, 0, buffer.Length); while (bytesRead > 0) { objectStream.Write(buffer, 0, bytesRead); bytesRead = csDecrypt.Read(buffer, 0, buffer.Length); } csDecrypt.Flush(); objectStream.Position = 0; IFormatter formatter = new BinaryFormatter(); loadedData = formatter.Deserialize(objectStream) as UserData; } } } return(loadedData); }
/********************************************************************************************************** * void DeletePasswordEventListener(HashedPassword Password) * Purpose: Custom event listener that listens for when a password is deleted. Updates the UI and * removes the entry for the password. * * Parameters: * HashedPassword Password * The password to remove. **********************************************************************************************************/ private void DeletePasswordEventListener(HashedPassword Password) { foreach (HashedPasswordCompactDisplay element in uxHashedPassContainer.Children) { if (element.Password == Password) { uxHashedPassContainer.Children.Remove(element); break; } } Application.Passwords.Remove(Password); }
/********************************************************************************************************** * HashedPasswordCompactDisplay(HashedPassword Password) * Purpose: Constructor. * * Parameters: * HashedPassword Password * The password to display. **********************************************************************************************************/ public HashedPasswordCompactDisplay(HashedPassword Password) { InitializeComponent(); this.Password = Password; StringBuilder sb = new StringBuilder(); sb.Append(this.Password.DateCreated.Month.ToString()); sb.Append('/'); sb.Append(this.Password.DateCreated.Day.ToString()); sb.Append('/'); sb.Append(this.Password.DateCreated.Year.ToString()); uxDateCreated.Text = sb.ToString(); }
/********************************************************************************************************** * void MainWindow_Closing * Purpose: Fires when the window is to be closed. Prompts the user to save changes. * Encrypts the file using AES using a SHA-3 key derived from the MasterPassword. **********************************************************************************************************/ void MainWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e) { MessageBoxResult save = MessageBox.Show("Save your data?", "Save Prompt", MessageBoxButton.YesNoCancel); if (save == MessageBoxResult.No) { return; } else if (save == MessageBoxResult.Cancel) { e.Cancel = true; return; } // Need 128 bits password for the encryption key. ApplicationEntry self = new ApplicationEntry("MasterPass", 128 / sizeof(char) / 8, 0, true, true, true, false); HashedPassword fileName = self.GeneratePassword(MasterPassword); HashedPassword aesKey = self.GeneratePassword(MasterPassword); HashedPassword aesIV = self.GeneratePassword(MasterPassword); System.Security.Cryptography.Aes aes = System.Security.Cryptography.Aes.Create(); // Even if aes is broken the master password is unrecoverable. aes.Key = Encoding.Unicode.GetBytes(aesKey.Password); aes.IV = Encoding.Unicode.GetBytes(aesIV.Password); aes.Padding = System.Security.Cryptography.PaddingMode.PKCS7; ICryptoTransform encryptor = aes.CreateEncryptor(); // Open the file using (FileStream outputStream = new FileStream(fileName.Password + ".pass", FileMode.OpenOrCreate)) { // Use a safe to file encryption method using (CryptoStream csEncrypt = new CryptoStream(outputStream, encryptor, CryptoStreamMode.Write)) { // Convert the object to a byte array using (MemoryStream objectStream = new MemoryStream()) { // Throw the userData into the object stream. IFormatter formatter = new BinaryFormatter(); formatter.Serialize(objectStream, Data); objectStream.Position = 0; byte[] buffer = new byte[1024]; int bytesRead = objectStream.Read(buffer, 0, buffer.Length); // While there are still more bytes to write while (bytesRead > 0) { // Write them to the file. csEncrypt.Write(buffer, 0, bytesRead); bytesRead = objectStream.Read(buffer, 0, buffer.Length); } // Flush the final block. csEncrypt.FlushFinalBlock(); } } } }
/********************************************************************************************************** * HashedPassword GeneratePassword(string MasterPassword) * Purpose: The name of the application the HashedPass's are for. This is used when generating * unique HashedPasses. * Parameters: * string MasterPassword * The master password to generate the hash with. * * Return: * Returns the HashedPassword generated. **********************************************************************************************************/ public HashedPassword GeneratePassword(string MasterPassword) { //Create character alphabet. List <char> alphabetList = new List <char>(); if (LowerCaseAllowed) { alphabetList.AddRange(LOWERCASEALPHABET); } if (CapitalsAllowed) { alphabetList.AddRange(UPPERCASEALPHABET); } if (NumbersAllowed) { alphabetList.AddRange(NUMBERALPHABET); } if (SpecialCharactersAllowed) { alphabetList.AddRange(SPECIALCHARACTERALPHABET); } char[] alphabet = alphabetList.ToArray(); SHA3Managed SHAHasher = new SHA3Managed(256); // master password in bytes byte[] ByteMasterPass = Encoding.Unicode.GetBytes(MasterPassword); // application name in bytes. byte[] applicationShift = Encoding.Unicode.GetBytes(ApplicationName); // the set of master password + application name + seed byte[] mangledBytes = new byte[PasswordLength * sizeof(char)]; // Modify the bytes so that they are website and instance dependent. for (int i = 0; i < mangledBytes.Length; i++) { // Modify the password to be unique for the website. mangledBytes[i] = ByteMasterPass[i % ByteMasterPass.Length]; mangledBytes[i] += applicationShift[i % applicationShift.Length]; // Modify the password to be unique from each other for the website. mangledBytes[i] += CurrentSeed; } byte[] hashedPassword = new byte[PasswordLength * sizeof(char)]; // mangled bytes fed through a secure hash. for (int i = 0; i < mangledBytes.Length;) { int bytesHashed = Math.Min(mangledBytes.Length - i, 32); byte[] hashedChunk = SHAHasher.ComputeHash(mangledBytes, i, bytesHashed); Array.Copy(hashedChunk, 0, hashedPassword, i, bytesHashed); i += bytesHashed; } StringBuilder languageCompliantPass = new StringBuilder(); for (int i = 0, value = 0; i < hashedPassword.Length; i += sizeof(char)) { for (int j = i; j < i + sizeof(char); j++) { value += hashedPassword[j]; } languageCompliantPass.Append(alphabet[value % alphabet.Length]); } HashedPassword newPassword = new HashedPassword(languageCompliantPass.ToString(), DateTime.Now, CurrentSeed); m_currentSeed++; m_passwords.Add(newPassword); return(newPassword); }