private static void EncryptFile(string filePath, string encryptedFilePath, byte[] salt, byte[] encryptionKey, byte[] macKey) { try { using (var ciphertext = new FileStream(encryptedFilePath, FileMode.Create, FileAccess.ReadWrite, FileShare.Read, Constants.FileBufferSize, FileOptions.SequentialScan)) using (var plaintext = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.Read, Constants.FileBufferSize, FileOptions.SequentialScan)) { WriteFileHeaders.WriteHeaders(ciphertext, salt); byte[] fileBytes = FileHandling.GetBufferSize(plaintext.Length); // Generate a counter starting at 0 byte[] counter = Generate.Counter(); int bytesRead; MemoryEncryption.DecryptByteArray(ref encryptionKey); while ((bytesRead = plaintext.Read(fileBytes, 0, fileBytes.Length)) > 0) { byte[] encryptedBytes = StreamEncryption.EncryptXChaCha20(fileBytes, counter, encryptionKey); ciphertext.Write(encryptedBytes, 0, bytesRead); counter = Sodium.Utilities.Increment(counter); } } Utilities.ZeroArray(encryptionKey); CompleteEncryption(filePath, encryptedFilePath, macKey); } catch (Exception ex) when(ExceptionFilters.FileEncryptionExceptions(ex)) { Logging.LogException(ex.ToString(), Logging.Severity.High); DisplayMessage.Error(filePath, ex.GetType().Name, "Unable to encrypt the file."); FileHandling.DeleteFile(encryptedFilePath); Utilities.ZeroArray(encryptionKey); Utilities.ZeroArray(macKey); } }
private static void CreateSaltFile(string directoryPath, byte[] salt) { string saltFilePath = Path.Combine(directoryPath, Constants.SaltFile); File.WriteAllBytes(saltFilePath, salt); FileHandling.SetFileAttributesReadOnly(saltFilePath); }
private static void UsingPassword(string inputFilePath, byte[] passwordBytes) { try { bool fileIsDirectory = FileHandling.IsDirectory(inputFilePath); if (fileIsDirectory) { DirectoryEncryption.UsingPassword(inputFilePath, passwordBytes); return; } // Derive a unique KEK per file byte[] salt = Generate.Salt(); byte[] keyEncryptionKey = Argon2.DeriveKey(passwordBytes, salt); // Fill the ephemeral public key header with random key (since not in use) byte[] randomEphemeralPublicKeyHeader = Generate.EphemeralPublicKeyHeader(); string outputFilePath = GetOutputFilePath(inputFilePath); EncryptFile.Initialize(inputFilePath, outputFilePath, randomEphemeralPublicKeyHeader, salt, keyEncryptionKey); Utilities.ZeroArray(keyEncryptionKey); EncryptionSuccessful(inputFilePath, outputFilePath); } catch (Exception ex) when(ExceptionFilters.FileAccess(ex)) { Logging.LogException(ex.ToString(), Logging.Severity.Error); DisplayMessage.FilePathException(inputFilePath, ex.GetType().Name, "Unable to encrypt the file."); } }
private static void UsingPublicKey(string inputFilePath, byte[] sharedSecret, byte[] recipientPrivateKey) { try { bool fileIsDirectory = FileHandling.IsDirectory(inputFilePath); if (fileIsDirectory) { DirectoryDecryption.UsingPublicKey(inputFilePath, sharedSecret, recipientPrivateKey); return; } using var inputFile = new FileStream(inputFilePath, FileMode.Open, FileAccess.Read, FileShare.Read, Constants.FileStreamBufferSize, FileOptions.RandomAccess); byte[] ephemeralPublicKey = FileHeaders.ReadEphemeralPublicKey(inputFile); byte[] ephemeralSharedSecret = KeyExchange.GetSharedSecret(recipientPrivateKey, ephemeralPublicKey); byte[] salt = FileHeaders.ReadSalt(inputFile); byte[] keyEncryptionKey = Generate.KeyEncryptionKey(sharedSecret, ephemeralSharedSecret, salt); string outputFilePath = GetOutputFilePath(inputFilePath); DecryptFile.Initialize(inputFile, outputFilePath, ephemeralPublicKey, keyEncryptionKey); CryptographicOperations.ZeroMemory(keyEncryptionKey); DecryptionSuccessful(inputFilePath, outputFilePath); } catch (Exception ex) when(ExceptionFilters.Cryptography(ex)) { FileException(inputFilePath, ex); } }
private static void UsingPublicKey(string inputFilePath, byte[] sharedSecret, byte[] recipientPublicKey) { try { bool fileIsDirectory = FileHandling.IsDirectory(inputFilePath); if (fileIsDirectory) { DirectoryEncryption.UsingPublicKey(inputFilePath, sharedSecret, recipientPublicKey); return; } // Derive a unique KEK per file (byte[] ephemeralSharedSecret, byte[] ephemeralPublicKey) = KeyExchange.GetEphemeralSharedSecret(recipientPublicKey); byte[] salt = Generate.Salt(); byte[] keyEncryptionKey = Generate.KeyEncryptionKey(sharedSecret, ephemeralSharedSecret, salt); string outputFilePath = GetOutputFilePath(inputFilePath); EncryptFile.Initialize(inputFilePath, outputFilePath, ephemeralPublicKey, salt, keyEncryptionKey); Utilities.ZeroArray(keyEncryptionKey); EncryptionSuccessful(inputFilePath, outputFilePath); } catch (Exception ex) when(ExceptionFilters.FileAccess(ex)) { Logging.LogException(ex.ToString(), Logging.Severity.Error); DisplayMessage.FilePathException(inputFilePath, ex.GetType().Name, "Unable to encrypt the file."); } }
private static void UsingPassword(string inputFilePath, byte[] passwordBytes) { try { bool fileIsDirectory = FileHandling.IsDirectory(inputFilePath); if (fileIsDirectory) { DirectoryDecryption.UsingPassword(inputFilePath, passwordBytes); return; } byte[] salt = FileHeaders.ReadSalt(inputFilePath); byte[] keyEncryptionKey = Argon2.DeriveKey(passwordBytes, salt); string outputFilePath = GetOutputFilePath(inputFilePath); DecryptFile.Initialize(inputFilePath, outputFilePath, keyEncryptionKey); Utilities.ZeroArray(keyEncryptionKey); DecryptionSuccessful(inputFilePath, outputFilePath); } catch (Exception ex) when(ExceptionFilters.FileAccess(ex)) { Logging.LogException(ex.ToString(), Logging.Severity.Error); if (ex is ArgumentException || ex is ArgumentOutOfRangeException) { DisplayMessage.FilePathMessage(inputFilePath, ex.Message); return; } DisplayMessage.FilePathException(inputFilePath, ex.GetType().Name, "Unable to decrypt the file."); } }
private static void UsingPrivateKey(string inputFilePath, byte[] sharedSecret, byte[] recipientPrivateKey) { try { bool fileIsDirectory = FileHandling.IsDirectory(inputFilePath); if (fileIsDirectory) { DirectoryDecryption.UsingPrivateKey(inputFilePath, sharedSecret, recipientPrivateKey); return; } byte[] ephemeralPublicKey = FileHeaders.ReadEphemeralPublicKey(inputFilePath); byte[] ephemeralSharedSecret = KeyExchange.GetSharedSecret(recipientPrivateKey, ephemeralPublicKey); byte[] salt = FileHeaders.ReadSalt(inputFilePath); byte[] keyEncryptionKey = Generate.KeyEncryptionKey(sharedSecret, ephemeralSharedSecret, salt); string outputFilePath = GetOutputFilePath(inputFilePath); DecryptFile.Initialize(inputFilePath, outputFilePath, keyEncryptionKey); Utilities.ZeroArray(keyEncryptionKey); DecryptionSuccessful(inputFilePath, outputFilePath); } catch (Exception ex) when(ExceptionFilters.FileAccess(ex)) { Logging.LogException(ex.ToString(), Logging.Severity.Error); if (ex is ArgumentException || ex is ArgumentOutOfRangeException) { DisplayMessage.FilePathMessage(inputFilePath, ex.Message); return; } DisplayMessage.FilePathException(inputFilePath, ex.GetType().Name, "Unable to decrypt the file."); } }
private static byte[] GetCommentBytes(FileStream signatureFile) { int offset = Constants.SignatureMagicBytes.Length + Constants.SignatureVersion.Length + _preHashedHeaderLength + Constants.SignatureLength; int length = (int)(signatureFile.Length - offset - Constants.SignatureLength); return(FileHandling.ReadFileHeader(signatureFile, length)); }
private static void RestoreDirectoryName(string obfuscatedDirectoryPath) { try { string obfuscatedDirectoryName = Path.GetFileName(obfuscatedDirectoryPath); // Get the path where the original directory name is stored string storageFileName = $"{obfuscatedDirectoryName}.txt"; string storageFilePath = Path.Combine(obfuscatedDirectoryPath, storageFileName); if (!File.Exists(storageFilePath)) { return; } string directoryName = File.ReadAllText(storageFilePath); string directoryPath = obfuscatedDirectoryPath.Replace(obfuscatedDirectoryName, directoryName); directoryPath = FileHandling.GetUniqueDirectoryPath(directoryPath); Directory.Move(obfuscatedDirectoryPath, directoryPath); DisplayMessage.FileEncryptionResult(obfuscatedDirectoryName, directoryName); storageFilePath = Path.Combine(directoryPath, storageFileName); FileHandling.DeleteFile(storageFilePath); } catch (Exception ex) when(ExceptionFilters.FileAccess(ex)) { Logging.LogException(ex.ToString(), Logging.Severity.Error); DisplayMessage.FilePathException(obfuscatedDirectoryPath, ex.GetType().Name, "Unable to restore the directory name."); } }
private static string[] GetFiles(string directoryPath) { string[] filePaths = FileHandling.GetAllFiles(directoryPath); // -1 for the selected directory Globals.TotalCount += filePaths.Length - 1; return(filePaths); }
private static void UsingPassword(string inputFilePath, byte[] passwordBytes) { try { bool fileIsDirectory = FileHandling.IsDirectory(inputFilePath); if (fileIsDirectory) { DirectoryEncryption.UsingPassword(inputFilePath, passwordBytes); return; } // Derive a unique KEK per file byte[] salt = Generate.Salt(); byte[] keyEncryptionKey = Argon2.DeriveKey(passwordBytes, salt); // Fill unused header with random public key byte[] ephemeralPublicKey = Generate.EphemeralPublicKeyHeader(); string outputFilePath = GetOutputFilePath(inputFilePath); EncryptFile.Initialize(inputFilePath, outputFilePath, ephemeralPublicKey, salt, keyEncryptionKey); CryptographicOperations.ZeroMemory(keyEncryptionKey); EncryptionSuccessful(inputFilePath, outputFilePath); } catch (Exception ex) when(ExceptionFilters.Cryptography(ex)) { DisplayMessage.FilePathException(inputFilePath, ex.GetType().Name, "Unable to encrypt the file."); } }
private static void DecryptFile(string filePath, int parametersLength, byte[] macBackup, byte[] encryptionKey) { try { string decryptedFilePath = Regex.Replace(filePath, Constants.EncryptedExtension, string.Empty); int headersLength = Constants.SaltLength + parametersLength; using (var plaintext = new FileStream(decryptedFilePath, FileMode.Create, FileAccess.ReadWrite, FileShare.Read, Constants.FileBufferSize, FileOptions.SequentialScan)) using (var ciphertext = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.Read, Constants.FileBufferSize, FileOptions.SequentialScan)) { // Skip the header bytes ciphertext.Seek(headersLength, SeekOrigin.Begin); byte[] fileBytes = FileHandling.GetBufferSize(ciphertext.Length); // Generate a counter starting at 0 byte[] counter = Generate.Counter(); int bytesRead; MemoryEncryption.DecryptByteArray(ref encryptionKey); while ((bytesRead = ciphertext.Read(fileBytes, 0, fileBytes.Length)) > 0) { byte[] decryptedBytes = StreamEncryption.DecryptXChaCha20(fileBytes, counter, encryptionKey); plaintext.Write(decryptedBytes, 0, bytesRead); counter = Sodium.Utilities.Increment(counter); } Utilities.ZeroArray(encryptionKey); } CompleteDecryption(filePath, decryptedFilePath); } catch (Exception ex) when(ExceptionFilters.FileEncryptionExceptions(ex)) { Logging.LogException(ex.ToString(), Logging.Severity.High); DisplayMessage.Error(filePath, ex.GetType().Name, "Unable to decrypt the file."); Utilities.ZeroArray(encryptionKey); RestoreMAC(filePath, macBackup); } }
private static bool IsPreHashingRequired(string filePath) { int oneGibibyte = 1024 * Constants.Mebibyte; long fileSize = FileHandling.GetFileLength(filePath); return(fileSize >= oneGibibyte); }
private static void Finalize(string directoryPath, string saltFilePath) { if (Globals.SuccessfulCount != 0 && Globals.SuccessfulCount == Globals.TotalCount) { FileHandling.DeleteFile(saltFilePath); } Finalize(directoryPath); }
private static void CompleteDecryption(string filePath, string decryptedFilePath) { // Deanonymise file name OriginalFileName.RestoreOriginalFileName(decryptedFilePath); FileHandling.DeleteFile(filePath); Console.WriteLine($"{Path.GetFileName(filePath)}: File decryption successful."); Globals.SuccessfulCount += 1; }
private static void Finalize(string directoryPath, string saltFilePath) { string[] kryptorFiles = Directory.GetFiles(directoryPath, $"*{Constants.EncryptedExtension}", SearchOption.AllDirectories); if (kryptorFiles.Length == 0) { FileHandling.DeleteFile(saltFilePath); } Finalize(directoryPath); }
public static void AppendFileName(string filePath) { Encoding fileEncoding = FileHandling.GetFileEncoding(filePath); string fileName = Path.GetFileName(filePath); byte[] fileNameBytes = fileEncoding.GetBytes(fileName); using var fileStream = new FileStream(filePath, FileMode.Append, FileAccess.Write, FileShare.Read, Constants.FileStreamBufferSize, FileOptions.RandomAccess); fileStream.Write(fileNameBytes, offset: 0, fileNameBytes.Length); }
public static void AllDirectories(string directoryPath) { string[] subdirectories = FileHandling.GetAllDirectories(directoryPath); // Deobfuscate subdirectory names - bottom most first for (int i = subdirectories.Length - 1; i >= 0; i--) { RestoreDirectoryName(subdirectories[i]); } RestoreDirectoryName(directoryPath); }
private static byte[] EncryptFileHeader(string inputFilePath, byte[] ephemeralPublicKey, byte[] dataEncryptionKey, byte[] nonce, byte[] keyEncryptionKey) { long fileLength = FileHandling.GetFileLength(inputFilePath); byte[] lastChunkLength = BitConversion.GetBytes(Convert.ToInt32(fileLength % Constants.FileChunkSize)); byte[] fileNameLength = FileHeaders.GetFileNameLength(inputFilePath); byte[] fileHeader = Arrays.Concat(lastChunkLength, fileNameLength, dataEncryptionKey); byte[] additionalData = HeaderEncryption.ComputeAdditionalData(fileLength, ephemeralPublicKey); return(HeaderEncryption.Encrypt(fileHeader, nonce, keyEncryptionKey, additionalData)); }
public static string AllDirectories(string directoryPath) { string[] subdirectories = FileHandling.GetAllDirectories(directoryPath); // Obfuscate subdirectory names - bottom most first for (int i = subdirectories.Length - 1; i >= 0; i--) { ObfuscateDirectoryName(subdirectories[i]); } // Obfuscate parent directory name return(ObfuscateDirectoryName(directoryPath)); }
private static byte[] EncryptFileHeader(string inputFilePath, byte[] dataEncryptionKey, byte[] nonce, byte[] keyEncryptionKey) { byte[] keyCommitmentBlock = ChunkHandling.GetKeyCommitmentBlock(); long fileLength = FileHandling.GetFileLength(inputFilePath); byte[] lastChunkLength = BitConverter.GetBytes(Convert.ToInt32(fileLength % Constants.FileChunkSize)); byte[] fileNameLength = FileHeaders.GetFileNameLength(inputFilePath); byte[] fileHeader = Utilities.ConcatArrays(keyCommitmentBlock, lastChunkLength, fileNameLength, dataEncryptionKey); byte[] additionalData = HeaderEncryption.ComputeAdditionalData(fileLength); return(HeaderEncryption.Encrypt(fileHeader, nonce, keyEncryptionKey, additionalData)); }
public static byte[] GetAdditionalData(string inputFilePath) { byte[] magicBytes = FileHeaders.ReadMagicBytes(inputFilePath); byte[] formatVersion = FileHeaders.ReadFileFormatVersion(inputFilePath); FileHeaders.ValidateFormatVersion(inputFilePath, formatVersion, Constants.EncryptionVersion); long fileLength = FileHandling.GetFileLength(inputFilePath); int headersLength = FileHeaders.GetHeadersLength(); byte[] ciphertextLength = BitConverter.GetBytes(fileLength - headersLength); return(Utilities.ConcatArrays(magicBytes, formatVersion, ciphertextLength)); }
private static byte[] GetFileBytes(string filePath, bool preHashed) { int oneGibibyte = 1024 * Constants.Mebibyte; long fileSize = FileHandling.GetFileLength(filePath); if (fileSize >= oneGibibyte || preHashed) { using var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.Read, Constants.FileStreamBufferSize, FileOptions.SequentialScan); return(Blake2.Hash(fileStream)); } return(File.ReadAllBytes(filePath)); }
private static void Finalize(string inputFilePath, string outputFilePath) { if (Globals.Overwrite) { FileHandling.OverwriteFile(inputFilePath, outputFilePath); } else if (Globals.ObfuscateFileNames) { RestoreFileName.RemoveAppendedFileName(inputFilePath); } FileHandling.MakeFileReadOnly(outputFilePath); }
private static void CompleteEncryption(string filePath, string encryptedFilePath, byte[] macKey) { // Calculate and append MAC bool fileSigned = FileAuthentication.SignFile(encryptedFilePath, macKey); Utilities.ZeroArray(macKey); if (fileSigned == true && Globals.OverwriteFiles == true) { FileHandling.OverwriteFile(filePath, encryptedFilePath); } FileHandling.MakeFileReadOnly(encryptedFilePath); GetEncryptionResult(filePath, fileSigned); }
private static void CreateSignatureFile(string filePath, string signatureFilePath, byte[] signatureFileBytes, byte[] globalSignature) { const int offset = 0; if (string.IsNullOrEmpty(signatureFilePath)) { signatureFilePath = filePath + Constants.SignatureExtension; } FileHandling.SetFileAttributesNormal(signatureFilePath); using var signatureFile = new FileStream(signatureFilePath, FileMode.Create, FileAccess.ReadWrite, FileShare.Read, Constants.FileStreamBufferSize, FileOptions.SequentialScan); signatureFile.Write(signatureFileBytes, offset, signatureFileBytes.Length); signatureFile.Write(globalSignature, offset, globalSignature.Length); File.SetAttributes(signatureFilePath, FileAttributes.ReadOnly); }
private static string BackupDirectory(string directoryPath) { if (Globals.Overwrite) { return(null); } DisplayMessage.FilePathMessage(directoryPath, "Copying directory because you didn't specify -o|--overwrite..."); string destinationDirectoryPath = FileHandling.GetUniqueDirectoryPath($"{directoryPath} - Copy"); FileHandling.CopyDirectory(directoryPath, destinationDirectoryPath, copySubdirectories: true); if (!Globals.ObfuscateFileNames) { DisplayMessage.FileEncryptionResult(directoryPath, destinationDirectoryPath); } return(destinationDirectoryPath); }
public static void RemoveAppendedFileName(string inputFilePath) { try { File.SetAttributes(inputFilePath, FileAttributes.Normal); Encoding fileEncoding = FileHandling.GetFileEncoding(inputFilePath); string fileName = Path.GetFileName(inputFilePath); byte[] fileNameBytes = fileEncoding.GetBytes(fileName); using var fileStream = new FileStream(inputFilePath, FileMode.Open, FileAccess.ReadWrite, FileShare.Read, Constants.FileStreamBufferSize, FileOptions.RandomAccess); fileStream.SetLength(fileStream.Length - fileNameBytes.Length); } catch (Exception ex) when(ExceptionFilters.FileAccess(ex)) { Logging.LogException(ex.ToString(), Logging.Severity.Error); DisplayMessage.FilePathException(inputFilePath, ex.GetType().Name, "Unable to remove appended file name."); } }
public static string GetOutputFilePath(string inputFilePath) { try { if (Globals.ObfuscateFileNames) { ObfuscateFileName.AppendFileName(inputFilePath); inputFilePath = ObfuscateFileName.ReplaceFilePath(inputFilePath); } } catch (Exception ex) when(ExceptionFilters.FileAccess(ex) || ex is EncoderFallbackException) { DisplayMessage.FilePathException(inputFilePath, ex.GetType().Name, "Unable to store file name."); } string outputFilePath = inputFilePath + Constants.EncryptedExtension; return(FileHandling.GetUniqueFilePath(outputFilePath)); }
private static IEnumerable <string> GetSignatureFileError(string signatureFilePath) { if (string.IsNullOrEmpty(signatureFilePath)) { yield return("Please specify a signature file."); } else { bool?validMagicBytes = FileHandling.IsSignatureFile(signatureFilePath); if (validMagicBytes == null) { yield return("Unable to access signature file."); } if (validMagicBytes == false) { yield return(_invalidSignatureFile); } } }