diff --git a/src/KryptorCLI/FileEncryption/DirectoryDecryption.cs b/src/KryptorCLI/FileEncryption/DirectoryDecryption.cs index d42b80d..3c20e89 100644 --- a/src/KryptorCLI/FileEncryption/DirectoryDecryption.cs +++ b/src/KryptorCLI/FileEncryption/DirectoryDecryption.cs @@ -39,12 +39,7 @@ public static void UsingPassword(string directoryPath, byte[] passwordBytes) } catch (Exception ex) when (ExceptionFilters.FileAccess(ex)) { - if (ex is ArgumentException || ex is FileNotFoundException) - { - DisplayMessage.FilePathError(directoryPath, ex.Message); - return; - } - DisplayMessage.FilePathException(directoryPath, ex.GetType().Name, "Unable to decrypt the directory."); + DirectoryException(directoryPath, ex); } } @@ -53,11 +48,7 @@ private static void DecryptEachFileWithPassword(string[] filePaths, byte[] keyEn foreach (string inputFilePath in filePaths) { bool validFilePath = FilePathValidation.FileDecryption(inputFilePath); - if (!validFilePath) - { - --Globals.TotalCount; - continue; - } + if (!validFilePath) { continue; } try { using var inputFile = new FileStream(inputFilePath, FileMode.Open, FileAccess.Read, FileShare.Read, Constants.FileStreamBufferSize, FileOptions.RandomAccess); @@ -92,13 +83,14 @@ public static void UsingPublicKey(string directoryPath, byte[] sharedSecret, byt { try { + FilePathValidation.DirectoryDecryption(directoryPath); string[] filePaths = GetFiles(directoryPath); DecryptEachFileWithPublicKey(filePaths, sharedSecret, recipientPrivateKey); Finalize(directoryPath); } catch (Exception ex) when (ExceptionFilters.FileAccess(ex)) { - DisplayMessage.FilePathException(directoryPath, ex.GetType().Name, "Unable to decrypt the directory."); + DirectoryException(directoryPath, ex); } } @@ -107,11 +99,7 @@ private static void DecryptEachFileWithPublicKey(string[] filePaths, byte[] shar foreach (string inputFilePath in filePaths) { bool validFilePath = FilePathValidation.FileDecryption(inputFilePath); - if (!validFilePath) - { - --Globals.TotalCount; - continue; - } + if (!validFilePath) { continue; } try { using var inputFile = new FileStream(inputFilePath, FileMode.Open, FileAccess.Read, FileShare.Read, Constants.FileStreamBufferSize, FileOptions.RandomAccess); @@ -133,13 +121,14 @@ public static void UsingPrivateKey(string directoryPath, byte[] privateKey) { try { + FilePathValidation.DirectoryDecryption(directoryPath); string[] filePaths = GetFiles(directoryPath); DecryptEachFileWithPrivateKey(filePaths, privateKey); Finalize(directoryPath); } catch (Exception ex) when (ExceptionFilters.FileAccess(ex)) { - DisplayMessage.FilePathException(directoryPath, ex.GetType().Name, "Unable to decrypt the directory."); + DirectoryException(directoryPath, ex); } } @@ -148,11 +137,7 @@ private static void DecryptEachFileWithPrivateKey(string[] filePaths, byte[] pri foreach (string inputFilePath in filePaths) { bool validFilePath = FilePathValidation.FileDecryption(inputFilePath); - if (!validFilePath) - { - --Globals.TotalCount; - continue; - } + if (!validFilePath) { continue; } try { using var inputFile = new FileStream(inputFilePath, FileMode.Open, FileAccess.Read, FileShare.Read, Constants.FileStreamBufferSize, FileOptions.RandomAccess); @@ -192,6 +177,16 @@ private static void Finalize(string directoryPath) } } + private static void DirectoryException(string directoryPath, Exception ex) + { + if (ex is ArgumentException || ex is FileNotFoundException) + { + DisplayMessage.FilePathError(directoryPath, ex.Message); + return; + } + DisplayMessage.FilePathException(directoryPath, ex.GetType().Name, "Unable to decrypt the directory."); + } + private static void FileException(string inputFilePath, Exception ex) { if (ex is ArgumentException) diff --git a/src/KryptorCLI/FileEncryption/DirectoryEncryption.cs b/src/KryptorCLI/FileEncryption/DirectoryEncryption.cs index 4e0508c..91199ed 100644 --- a/src/KryptorCLI/FileEncryption/DirectoryEncryption.cs +++ b/src/KryptorCLI/FileEncryption/DirectoryEncryption.cs @@ -29,6 +29,7 @@ public static void UsingPassword(string directoryPath, byte[] passwordBytes) bool overwriteOption = Globals.Overwrite; try { + FilePathValidation.DirectoryEncryption(directoryPath); // Always overwrite directories string backupDirectoryPath = BackupDirectory(directoryPath); Globals.Overwrite = true; @@ -43,7 +44,7 @@ public static void UsingPassword(string directoryPath, byte[] passwordBytes) } catch (Exception ex) when (ExceptionFilters.FileAccess(ex)) { - DisplayMessage.FilePathException(directoryPath, ex.GetType().Name, "Unable to encrypt the directory."); + DirectoryException(directoryPath, ex); } finally { @@ -96,11 +97,7 @@ private static void EncryptEachFileWithPassword(string[] filePaths, byte[] salt, foreach (string inputFilePath in filePaths) { bool validFilePath = FilePathValidation.FileEncryption(inputFilePath); - if (!validFilePath) - { - --Globals.TotalCount; - continue; - } + if (!validFilePath) { continue; } // Fill unused header with random public key byte[] ephemeralPublicKey = Generate.EphemeralPublicKeyHeader(); string outputFilePath = FileEncryption.GetOutputFilePath(inputFilePath); @@ -135,6 +132,7 @@ public static void UsingPublicKey(string directoryPath, byte[] sharedSecret, byt bool overwriteOption = Globals.Overwrite; try { + FilePathValidation.DirectoryEncryption(directoryPath); // Always overwrite directories string backupDirectoryPath = BackupDirectory(directoryPath); Globals.Overwrite = true; @@ -144,7 +142,7 @@ public static void UsingPublicKey(string directoryPath, byte[] sharedSecret, byt } catch (Exception ex) when (ExceptionFilters.FileAccess(ex)) { - DisplayMessage.FilePathException(directoryPath, ex.GetType().Name, "Unable to encrypt the directory."); + DirectoryException(directoryPath, ex); } finally { @@ -157,11 +155,7 @@ private static void EncryptEachFileWithPublicKey(string[] filePaths, byte[] shar foreach (string inputFilePath in filePaths) { bool validFilePath = FilePathValidation.FileEncryption(inputFilePath); - if (!validFilePath) - { - --Globals.TotalCount; - continue; - } + if (!validFilePath) { continue; } // Derive a unique KEK per file byte[] ephemeralSharedSecret = KeyExchange.GetEphemeralSharedSecret(recipientPublicKey, out byte[] ephemeralPublicKey); byte[] salt = Generate.Salt(); @@ -177,6 +171,7 @@ public static void UsingPrivateKey(string directoryPath, byte[] privateKey) bool overwriteOption = Globals.Overwrite; try { + FilePathValidation.DirectoryEncryption(directoryPath); // Always overwrite directories string backupDirectoryPath = BackupDirectory(directoryPath); Globals.Overwrite = true; @@ -186,7 +181,7 @@ public static void UsingPrivateKey(string directoryPath, byte[] privateKey) } catch (Exception ex) when (ExceptionFilters.FileAccess(ex)) { - DisplayMessage.FilePathException(directoryPath, ex.GetType().Name, "Unable to encrypt the directory."); + DirectoryException(directoryPath, ex); } finally { @@ -199,11 +194,7 @@ private static void EncryptEachFileWithPrivateKey(string[] filePaths, byte[] pri foreach (string inputFilePath in filePaths) { bool validFilePath = FilePathValidation.FileEncryption(inputFilePath); - if (!validFilePath) - { - --Globals.TotalCount; - continue; - } + if (!validFilePath) { continue; } // Derive a unique KEK per file byte[] ephemeralSharedSecret = KeyExchange.GetPrivateKeySharedSecret(privateKey, out byte[] ephemeralPublicKey); byte[] salt = Generate.Salt(); @@ -213,5 +204,15 @@ private static void EncryptEachFileWithPrivateKey(string[] filePaths, byte[] pri CryptographicOperations.ZeroMemory(keyEncryptionKey); } } + + private static void DirectoryException(string directoryPath, Exception ex) + { + if (ex is ArgumentException) + { + DisplayMessage.FilePathError(directoryPath, ex.Message); + return; + } + DisplayMessage.FilePathException(directoryPath, ex.GetType().Name, "Unable to encrypt the directory."); + } } } diff --git a/src/KryptorCLI/FileEncryption/FileDecryption.cs b/src/KryptorCLI/FileEncryption/FileDecryption.cs index a9b6acd..15fbb53 100644 --- a/src/KryptorCLI/FileEncryption/FileDecryption.cs +++ b/src/KryptorCLI/FileEncryption/FileDecryption.cs @@ -29,12 +29,6 @@ public static void DecryptEachFileWithPassword(string[] filePaths, byte[] passwo Globals.TotalCount = filePaths.Length; foreach (string inputFilePath in filePaths) { - bool validFilePath = FilePathValidation.FileDecryption(inputFilePath); - if (!validFilePath) - { - --Globals.TotalCount; - continue; - } UsingPassword(inputFilePath, passwordBytes); } CryptographicOperations.ZeroMemory(passwordBytes); @@ -74,12 +68,6 @@ public static void DecryptEachFileWithPublicKey(string[] filePaths, byte[] recip byte[] sharedSecret = KeyExchange.GetSharedSecret(recipientPrivateKey, senderPublicKey); foreach (string inputFilePath in filePaths) { - bool validFilePath = FilePathValidation.FileDecryption(inputFilePath); - if (!validFilePath) - { - --Globals.TotalCount; - continue; - } UsingPublicKey(inputFilePath, sharedSecret, recipientPrivateKey); } CryptographicOperations.ZeroMemory(recipientPrivateKey); @@ -120,12 +108,6 @@ public static void DecryptEachFileWithPrivateKey(string[] filePaths, byte[] priv if (privateKey == null) { return; } foreach (string inputFilePath in filePaths) { - bool validFilePath = FilePathValidation.FileDecryption(inputFilePath); - if (!validFilePath) - { - --Globals.TotalCount; - continue; - } UsingPrivateKey(inputFilePath, privateKey); } CryptographicOperations.ZeroMemory(privateKey); diff --git a/src/KryptorCLI/FileEncryption/FileEncryption.cs b/src/KryptorCLI/FileEncryption/FileEncryption.cs index ec216e0..bead856 100644 --- a/src/KryptorCLI/FileEncryption/FileEncryption.cs +++ b/src/KryptorCLI/FileEncryption/FileEncryption.cs @@ -29,12 +29,6 @@ public static void EncryptEachFileWithPassword(string[] filePaths, byte[] passwo Globals.TotalCount = filePaths.Length; foreach (string inputFilePath in filePaths) { - bool validFilePath = FilePathValidation.FileEncryption(inputFilePath); - if (!validFilePath) - { - --Globals.TotalCount; - continue; - } UsingPassword(inputFilePath, passwordBytes); } CryptographicOperations.ZeroMemory(passwordBytes); @@ -76,12 +70,6 @@ public static void EncryptEachFileWithPublicKey(string[] filePaths, byte[] sende CryptographicOperations.ZeroMemory(senderPrivateKey); foreach (string inputFilePath in filePaths) { - bool validFilePath = FilePathValidation.FileEncryption(inputFilePath); - if (!validFilePath) - { - --Globals.TotalCount; - continue; - } UsingPublicKey(inputFilePath, sharedSecret, recipientPublicKey); } CryptographicOperations.ZeroMemory(sharedSecret); @@ -120,12 +108,6 @@ public static void EncryptEachFileWithPrivateKey(string[] filePaths, byte[] priv if (privateKey == null) { return; } foreach (string inputFilePath in filePaths) { - bool validFilePath = FilePathValidation.FileEncryption(inputFilePath); - if (!validFilePath) - { - --Globals.TotalCount; - continue; - } UsingPrivateKey(inputFilePath, privateKey); } CryptographicOperations.ZeroMemory(privateKey); diff --git a/src/KryptorCLI/Validation/FilePathValidation.cs b/src/KryptorCLI/Validation/FilePathValidation.cs index bbaf7be..41861fd 100644 --- a/src/KryptorCLI/Validation/FilePathValidation.cs +++ b/src/KryptorCLI/Validation/FilePathValidation.cs @@ -26,6 +26,7 @@ public static class FilePathValidation { private static readonly string _fileDoesNotExist = "This file/folder doesn't exist."; private static readonly string _fileInaccessible = "Unable to access the file."; + private static readonly string _directoryEmpty = "This directory is empty."; public static bool FileEncryption(string inputFilePath) { @@ -37,7 +38,14 @@ public static bool FileEncryption(string inputFilePath) public static string GetFileEncryptionError(string inputFilePath) { - if (Directory.Exists(inputFilePath)) { return null; } + if (Directory.Exists(inputFilePath)) + { + if (FileHandling.IsDirectoryEmpty(inputFilePath)) + { + return _directoryEmpty; + } + return null; + } if (!File.Exists(inputFilePath)) { return _fileDoesNotExist; } bool? validMagicBytes = FileHandling.IsKryptorFile(inputFilePath); if (validMagicBytes == null) { return _fileInaccessible; } @@ -75,6 +83,18 @@ public static string KeyfilePath(string keyfilePath) } } + public static void DirectoryEncryption(string directoryPath) + { + string saltFilePath = Path.Combine(directoryPath, Constants.SaltFile); + if (File.Exists(saltFilePath)) { throw new ArgumentException("This directory has already been encrypted."); } + } + + public static void DirectoryDecryption(string directoryPath) + { + string saltFilePath = Path.Combine(directoryPath, Constants.SaltFile); + if (File.Exists(saltFilePath)) { throw new ArgumentException("This directory was encrypted using a password."); } + } + public static bool FileDecryption(string inputFilePath) { if (inputFilePath.Contains(Constants.SaltFile)) @@ -90,7 +110,14 @@ public static bool FileDecryption(string inputFilePath) public static string GetFileDecryptionError(string inputFilePath) { - if (Directory.Exists(inputFilePath)) { return null; } + if (Directory.Exists(inputFilePath)) + { + if (FileHandling.IsDirectoryEmpty(inputFilePath)) + { + return _directoryEmpty; + } + return null; + } if (!File.Exists(inputFilePath)) { return _fileDoesNotExist; } bool? validMagicBytes = FileHandling.IsKryptorFile(inputFilePath); if (validMagicBytes == null) { return _fileInaccessible; }