public static void SaveSettings() { try { if (File.Exists(_settingsFile)) { var settings = new Dictionary <string, string> { { "Memory Encryption", Globals.MemoryEncryption.ToString() }, { "Anonymous Rename", Globals.AnonymousRename.ToString() }, { "Overwrite Files", Globals.OverwriteFiles.ToString() }, { "Argon2 Memory Size", Invariant.ToString(Globals.MemorySize) }, { "Argon2 Iterations", Invariant.ToString(Globals.Iterations) }, }; using var streamWriter = new StreamWriter(_settingsFile); foreach (var keyValuePair in settings) { streamWriter.WriteLine($"{keyValuePair.Key}: {keyValuePair.Value}"); } } else { File.Create(_settingsFile).Close(); SaveSettings(); } } catch (Exception ex) when(ExceptionFilters.FileAccessExceptions(ex)) { Logging.LogException(ex.ToString(), Logging.Severity.High); DisplayMessage.Error(ex.GetType().Name, "Unable to save settings."); } }
private static void RetrieveArgon2Parameters(string filePath, ref string memorySize, ref string iterations) { try { // Read the first line of the file using var streamReader = new StreamReader(filePath, true); string firstLine = streamReader.ReadLine(); int memorySizeIndex = firstLine.IndexOf(Constants.MemorySizeFlag, StringComparison.Ordinal); if (memorySizeIndex != -1) { int iterationsIndex = firstLine.IndexOf(Constants.IterationsFlag, StringComparison.Ordinal); int endIndex = firstLine.IndexOf(Constants.EndFlag, StringComparison.Ordinal); // If the strings are found on the line if (memorySizeIndex != -1 && iterationsIndex != -1 && endIndex != -1) { memorySize = firstLine.Substring(memorySizeIndex, iterationsIndex - memorySizeIndex); iterations = firstLine.Substring(iterationsIndex, endIndex - iterationsIndex); } } } catch (Exception ex) when(ExceptionFilters.FileAccessExceptions(ex) || ExceptionFilters.CharacterEncodingExceptions(ex)) { Logging.LogException(ex.ToString(), Logging.Severity.High); DisplayMessage.Error(filePath, ex.GetType().Name, "Unable to read Argon2 parameters from the file."); } }
public static void RestoreOriginalFileName(string decryptedFilePath) { try { if (Globals.AnonymousRename == true) { string originalFileName = ReadOriginalFileName(decryptedFilePath); if (!string.IsNullOrEmpty(originalFileName)) { string anonymousFileName = Path.GetFileName(decryptedFilePath); string originalFilePath = Regex.Replace(decryptedFilePath, anonymousFileName, originalFileName); if (File.Exists(originalFilePath)) { // Replace the file File.Delete(originalFilePath); } File.Move(decryptedFilePath, originalFilePath); } } } catch (Exception ex) when(ExceptionFilters.FileAccessExceptions(ex)) { Logging.LogException(ex.ToString(), Logging.Severity.High); DisplayMessage.Error(decryptedFilePath, ex.GetType().Name, "Unable to restore original file name."); } }
public static void ReadSettings() { try { if (File.Exists(_settingsFile)) { string[] settingsLines = File.ReadAllLines(_settingsFile); var settings = new List <string>(); foreach (string line in settingsLines) { string[] splitLine = line.Split(':'); // Ignore the name of each setting - only store values settings.Add(splitLine[1]); } LoadSettings(settings); } else { // Create settings file with default settings SaveSettings(); } } catch (Exception ex) when(ExceptionFilters.FileAccessExceptions(ex)) { Logging.LogException(ex.ToString(), Logging.Severity.High); DisplayMessage.Error(ex.GetType().Name, "Unable to read the settings file."); } }
private static void CallEncryption(bool encryption, string filePath, byte[] passwordBytes) { try { bool kryptorExtension = filePath.EndsWith(Constants.EncryptedExtension, StringComparison.Ordinal); // Prevent Read-Only file attribute causing errors File.SetAttributes(filePath, FileAttributes.Normal); if (encryption == true && kryptorExtension == false) { Encryption.InitializeEncryption(filePath, passwordBytes); OverwriteDisabled(filePath); } else if (encryption == false && kryptorExtension == true) { Decryption.InitializeDecryption(filePath, passwordBytes); } else { DisplayMessage.FileError(filePath, encryption, kryptorExtension); } } catch (Exception ex) when(ExceptionFilters.FileAccessExceptions(ex)) { Logging.LogException(ex.ToString(), Logging.Severity.High); DisplayMessage.Error(filePath, ex.GetType().Name, "Unable to set file attributes to normal."); } }
public static void RestoreDirectoryName(string folderPath) { try { NullChecks.Strings(folderPath); string anonymisedDirectoryName = Path.GetFileName(folderPath); // Get the path where the original directory name is stored string storageFileName = $"{anonymisedDirectoryName}.txt"; string storageFilePath = Path.Combine(folderPath, storageFileName); if (File.Exists(storageFilePath)) { string originalDirectoryName = File.ReadAllText(storageFilePath); string originalDirectoryPath = folderPath.Replace(anonymisedDirectoryName, originalDirectoryName); Directory.Move(folderPath, originalDirectoryPath); storageFilePath = Path.Combine(originalDirectoryPath, storageFileName); if (File.Exists(storageFilePath)) { File.Delete(storageFilePath); } } } catch (Exception ex) when(ExceptionFilters.FileAccessExceptions(ex)) { Logging.LogException(ex.ToString(), Logging.Severity.High); DisplayMessage.Error(folderPath, ex.GetType().Name, "Unable to restore original directory name."); } }
public static bool AuthenticateFile(string filePath, byte[] macKey, out byte[] storedHash) { try { bool tampered = true; storedHash = ReadStoredHash(filePath); if (storedHash != null) { byte[] computedHash = new byte[Constants.HashLength]; using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.Read, Constants.FileBufferSize, FileOptions.SequentialScan)) { // Remove the stored MAC from the file before computing the MAC fileStream.SetLength(fileStream.Length - computedHash.Length); MemoryEncryption.DecryptByteArray(ref macKey); computedHash = HashingAlgorithms.Blake2(fileStream, macKey); MemoryEncryption.EncryptByteArray(ref macKey); } // Invert result tampered = !Sodium.Utilities.Compare(storedHash, computedHash); if (tampered == true) { // Restore the stored MAC AppendHash(filePath, storedHash); } } return(tampered); } catch (Exception ex) when(ExceptionFilters.FileAccessExceptions(ex)) { Logging.LogException(ex.ToString(), Logging.Severity.High); DisplayMessage.Error(filePath, ex.GetType().Name, "Unable to authenticate the file."); storedHash = null; return(true); } }
private static string[] GetRandomWords(string wordListFilePath, int[] lineNumbers, int wordCount, bool upperCase, bool numbers) { try { string[] words = new string[wordCount]; for (int i = 0; i < wordCount; i++) { words[i] = File.ReadLines(wordListFilePath).Skip(lineNumbers[i]).Take(1).First(); // Remove any numbers/spaces on the line words[i] = Regex.Replace(words[i], @"[\d-]", string.Empty).Trim(); if (upperCase == true) { words[i] = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(words[i].ToLower(CultureInfo.CurrentCulture)); } if (numbers == true) { words[i] += words[i].Length; } } return(words); } catch (Exception ex) when(ExceptionFilters.FileAccessExceptions(ex) || ex is RegexMatchTimeoutException) { Logging.LogException(ex.ToString(), Logging.Severity.Medium); DisplayMessage.Error(ex.GetType().Name, "Unable to retrieve words from the wordlist."); return(null); } }
public static char[] GenerateRandomPassphrase(int wordCount, bool uppercase, bool numbers) { try { string wordlistFilePath = Path.Combine(Constants.KryptorDirectory, "wordlist.txt"); if (File.Exists(wordlistFilePath)) { List <char> passphrase = new List <char>(); int wordlistLength = File.ReadLines(wordlistFilePath).Count(); int[] lineNumbers = GenerateLineNumbers(wordlistLength, wordCount); string[] words = GetRandomWords(wordlistFilePath, lineNumbers, wordCount, uppercase, numbers); Array.Clear(lineNumbers, 0, lineNumbers.Length); if (words != null) { FormatPassphrase(words, ref passphrase, wordCount); Array.Clear(words, 0, words.Length); } return(passphrase.ToArray()); } else { File.WriteAllText(wordlistFilePath, Properties.Resources.wordlist); return(GenerateRandomPassphrase(wordCount, uppercase, numbers)); } } catch (Exception ex) when(ExceptionFilters.FileAccessExceptions(ex)) { Logging.LogException(ex.ToString(), Logging.Severity.Medium); DisplayMessage.Error(ex.GetType().Name, "Unable to generate a random passphrase."); return(Array.Empty <char>()); } }
public static void MakeFileReadOnly(string filePath) { try { File.SetAttributes(filePath, FileAttributes.ReadOnly); } catch (Exception ex) when(ExceptionFilters.FileAccessExceptions(ex)) { Logging.LogException(ex.ToString(), Logging.Severity.Medium); DisplayMessage.Error(filePath, ex.GetType().Name, "Unable to make the file read-only."); } }
private static string[] GetAllDirectories(string folderPath) { try { return(Directory.GetDirectories(folderPath, "*", SearchOption.AllDirectories)); } catch (Exception ex) when(ExceptionFilters.FileAccessExceptions(ex)) { Logging.LogException(ex.ToString(), Logging.Severity.High); DisplayMessage.Error(folderPath, ex.GetType().Name, "Unable to get subdirectories in selected folder."); return(null); } }
public static void OverwriteFile(string fileToDelete, string fileToCopy) { try { File.Copy(fileToCopy, fileToDelete, true); File.Delete(fileToDelete); } catch (Exception ex) when(ExceptionFilters.FileAccessExceptions(ex)) { Logging.LogException(ex.ToString(), Logging.Severity.Medium); DisplayMessage.Error(fileToDelete, ex.GetType().Name, "Unable to overwrite and/or delete."); } }
public static void LogException(string exceptionMessage, Severity severity) { try { const string logFileName = "error log.txt"; string logFilePath = Path.Combine(Constants.KryptorDirectory, logFileName); string logMessage = $"[Error] Severity = {severity}" + Environment.NewLine + exceptionMessage + Environment.NewLine; File.AppendAllText(logFilePath, logMessage); } catch (Exception ex) when(ExceptionFilters.FileAccessExceptions(ex)) { DisplayMessage.Error(ex.GetType().Name, "Unable to log exception."); } }
public static bool?IsDirectory(string filePath) { try { var fileAttributes = File.GetAttributes(filePath); return(fileAttributes.HasFlag(FileAttributes.Directory)); } catch (Exception ex) when(ExceptionFilters.FileAccessExceptions(ex)) { Logging.LogException(ex.ToString(), Logging.Severity.High); DisplayMessage.Error(filePath, ex.GetType().Name, "Unable to check if file path is a directory."); return(null); } }
public static void DeleteFile(string filePath) { try { if (File.Exists(filePath)) { File.Delete(filePath); } } catch (Exception ex) when(ExceptionFilters.FileAccessExceptions(ex)) { Logging.LogException(ex.ToString(), Logging.Severity.Medium); DisplayMessage.Error(filePath, ex.GetType().Name, "Unable to delete the file."); } }
public static string ReadOriginalFileName(string filePath) { try { // Read the last line of the decrypted file string originalFileName = File.ReadLines(filePath).Last().Trim('\0'); RemoveStoredFileName(filePath, originalFileName); return(originalFileName); } catch (Exception ex) when(ExceptionFilters.FileAccessExceptions(ex) || ex is InvalidOperationException) { Logging.LogException(ex.ToString(), Logging.Severity.High); DisplayMessage.Error(filePath, ex.GetType().Name, "Unable to read original file name."); return(string.Empty); } }
public static void GenerateKeyfile(string filePath) { try { byte[] keyfileBytes = SodiumCore.GetRandomBytes(Constants.MACKeySize); File.WriteAllBytes(filePath, keyfileBytes); File.SetAttributes(filePath, FileAttributes.ReadOnly); Utilities.ZeroArray(keyfileBytes); Console.WriteLine("Keyfile successfully generated."); } catch (Exception ex) when(ExceptionFilters.FileAccessExceptions(ex)) { Logging.LogException(ex.ToString(), Logging.Severity.Low); DisplayMessage.Error(ex.GetType().Name, "Keyfile generation failed."); } }
private static void RestoreMAC(string filePath, byte[] macBackup) { bool restored = FileAuthentication.AppendHash(filePath, macBackup); if (restored == false) { try { File.WriteAllBytes($"{filePath}.backup", macBackup); } catch (Exception ex) when(ExceptionFilters.FileAccessExceptions(ex)) { Logging.LogException(ex.ToString(), Logging.Severity.High); DisplayMessage.Error(filePath, ex.GetType().Name, "Failed to backup the MAC. This data is required for decryption."); } } Utilities.ZeroArray(macBackup); }
public static bool AppendHash(string filePath, byte[] fileHash) { try { NullChecks.ByteArray(fileHash); using (var fileStream = new FileStream(filePath, FileMode.Append, FileAccess.Write, FileShare.Read, Constants.FileBufferSize, FileOptions.RandomAccess)) { fileStream.Write(fileHash, 0, fileHash.Length); } return(true); } catch (Exception ex) when(ExceptionFilters.FileAccessExceptions(ex)) { Logging.LogException(ex.ToString(), Logging.Severity.High); DisplayMessage.Error(filePath, ex.GetType().Name, "Unable to append the MAC to the file. This data is required for decryption of the file."); return(false); } }
private static void RemoveStoredFileName(string filePath, string originalFileName) { try { int fileNameLength = GetFileNameLength(filePath, originalFileName); if (fileNameLength != 0) { using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.Read, Constants.FileBufferSize, FileOptions.RandomAccess)) { fileStream.SetLength(fileStream.Length - fileNameLength); } } } catch (Exception ex) when(ExceptionFilters.FileAccessExceptions(ex)) { Logging.LogException(ex.ToString(), Logging.Severity.High); DisplayMessage.Error(filePath, ex.GetType().Name, "Unable to remove the original file name stored in the decrypted file. The file should be decrypted, but there is a leftover string at the end of the file."); } }
private static string AnonymiseDirectoryName(string folderPath) { try { string originalDirectoryName = Path.GetFileName(folderPath); string anonymisedPath = GetAnonymousFileName(folderPath); Directory.Move(folderPath, anonymisedPath); // Store the original directory name in a text file inside the directory string storageFilePath = Path.Combine(anonymisedPath, $"{Path.GetFileName(anonymisedPath)}.txt"); File.WriteAllText(storageFilePath, originalDirectoryName); return(anonymisedPath); } catch (Exception ex) when(ExceptionFilters.FileAccessExceptions(ex)) { Logging.LogException(ex.ToString(), Logging.Severity.High); DisplayMessage.Error(folderPath, ex.GetType().Name, "Unable to anonymise directory name."); return(folderPath); } }
private static byte[] ReadHeader(string filePath, int headerLength, int offset) { try { byte[] header = new byte[headerLength]; using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read, Constants.FileBufferSize, FileOptions.RandomAccess)) { fileStream.Seek(offset, SeekOrigin.Begin); fileStream.Read(header, 0, header.Length); } return(header); } catch (Exception ex) when(ExceptionFilters.FileAccessExceptions(ex)) { Logging.LogException(ex.ToString(), Logging.Severity.High); DisplayMessage.Error(filePath, ex.GetType().Name, "Unable to read salt from the selected file."); return(null); } }
public static bool AppendOriginalFileName(string filePath) { try { string fileName = Path.GetFileName(filePath); EncodeFileName(filePath, fileName, out byte[] newLineBytes, out byte[] fileNameBytes); using (var fileStream = new FileStream(filePath, FileMode.Append, FileAccess.Write, FileShare.Read, Constants.FileBufferSize, FileOptions.RandomAccess)) { fileStream.Write(newLineBytes, 0, newLineBytes.Length); fileStream.Write(fileNameBytes, 0, fileNameBytes.Length); } return(true); } catch (Exception ex) when(ExceptionFilters.FileAccessExceptions(ex) || ex is EncoderFallbackException) { Logging.LogException(ex.ToString(), Logging.Severity.High); DisplayMessage.Error(filePath, ex.GetType().Name, "Could not store original file name."); return(false); } }
private static byte[] ComputeFileHash(string encryptedFilePath, byte[] macKey) { try { byte[] computedHash = new byte[Constants.HashLength]; using (var fileStream = new FileStream(encryptedFilePath, FileMode.Open, FileAccess.Read, FileShare.Read, Constants.FileBufferSize, FileOptions.SequentialScan)) { MemoryEncryption.DecryptByteArray(ref macKey); computedHash = HashingAlgorithms.Blake2(fileStream, macKey); MemoryEncryption.EncryptByteArray(ref macKey); } return(computedHash); } catch (Exception ex) when(ExceptionFilters.FileAccessExceptions(ex)) { Logging.LogException(ex.ToString(), Logging.Severity.High); DisplayMessage.Error(encryptedFilePath, ex.GetType().Name, "Unable to compute MAC."); return(null); } }
private static byte[] ReadStoredHash(string filePath) { try { byte[] storedHash = new byte[Constants.HashLength]; using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read, Constants.FileBufferSize, FileOptions.RandomAccess)) { // Read the last 64 bytes of the file fileStream.Seek(fileStream.Length - storedHash.Length, SeekOrigin.Begin); fileStream.Read(storedHash, 0, storedHash.Length); } return(storedHash); } catch (Exception ex) when(ExceptionFilters.FileAccessExceptions(ex)) { Logging.LogException(ex.ToString(), Logging.Severity.High); DisplayMessage.Error(filePath, ex.GetType().Name, "Unable to read the MAC stored in the file."); return(null); } }
public static byte[] ReadKeyfile(string keyfilePath) { try { File.SetAttributes(keyfilePath, FileAttributes.Normal); byte[] keyfileBytes = new byte[Constants.MACKeySize]; // Read the first 64 bytes of a keyfile using (var fileStream = new FileStream(keyfilePath, FileMode.Open, FileAccess.Read, FileShare.Read)) { fileStream.Read(keyfileBytes, 0, keyfileBytes.Length); } File.SetAttributes(keyfilePath, FileAttributes.ReadOnly); return(keyfileBytes); } catch (Exception ex) when(ExceptionFilters.FileAccessExceptions(ex)) { Logging.LogException(ex.ToString(), Logging.Severity.Medium); DisplayMessage.Error(ex.GetType().Name, "Unable to read keyfile. The selected keyfile has not been used."); return(null); } }
public static string MoveFile(string filePath, bool file) { try { string anonymisedFilePath = GetAnonymousFileName(filePath); if (file == true) { File.Move(filePath, anonymisedFilePath); } else { Directory.Move(filePath, anonymisedFilePath); } return(anonymisedFilePath); } catch (Exception ex) when(ExceptionFilters.FileAccessExceptions(ex)) { Logging.LogException(ex.ToString(), Logging.Severity.Medium); DisplayMessage.Error(filePath, ex.GetType().Name, "Unable to anonymously rename file/folder."); return(filePath); } }
private static bool?CheckForUpdates(string kryptorVersion) { try { bool?updateAvailable = false; // Compare assembly version to online version file string downloadFilePath = Path.Combine(Constants.KryptorDirectory, "version.txt"); DownloadVersionFile(downloadFilePath); // Remove new line char & any leading/trailing whitespace string latestVersion = File.ReadAllText(downloadFilePath).Trim('\n').Trim(); if (kryptorVersion != latestVersion) { updateAvailable = true; } File.Delete(downloadFilePath); return(updateAvailable); } catch (Exception ex) when(ExceptionFilters.FileAccessExceptions(ex) || ex is WebException) { Logging.LogException(ex.ToString(), Logging.Severity.Medium); return(null); } }
private static void DirectoryEncryption(bool encryption, string folderPath, byte[] passwordBytes) { try { // Anonymise directory names before encryption (if enabled) folderPath = AnonymousRename.AnonymiseDirectories(encryption, folderPath); // Get all files in all directories string[] files = Directory.GetFiles(folderPath, "*.*", SearchOption.AllDirectories); // -1 for the selected directory Globals.TotalCount += files.Length - 1; foreach (string filePath in files) { CallEncryption(encryption, filePath, passwordBytes); } // Deanonymise directory names after decryption (if enabled) AnonymousRename.DeanonymiseDirectories(encryption, folderPath); } catch (Exception ex) when(ExceptionFilters.FileAccessExceptions(ex)) { Logging.LogException(ex.ToString(), Logging.Severity.High); DisplayMessage.Error(folderPath, ex.GetType().Name, "Unable to get files in the directory."); } }