From c1850d2bdfdbd85e073c88578183f9c699da11a0 Mon Sep 17 00:00:00 2001 From: Rodrigo Appelt Date: Wed, 25 May 2022 17:22:10 -0300 Subject: [PATCH 01/22] changes --- Encryptor.cs | 88 +++++++++++++++++++++++++++++----------- Engine.cs | 112 ++++++++++++++++++++++++++++++++------------------- Header.cs | 11 +++-- Program.cs | 6 +-- Utils.cs | 22 +++++----- 5 files changed, 152 insertions(+), 87 deletions(-) diff --git a/Encryptor.cs b/Encryptor.cs index bbea220..3326271 100644 --- a/Encryptor.cs +++ b/Encryptor.cs @@ -5,14 +5,17 @@ namespace SafeFolder{ public static class Encryptor { - private static readonly int _keySize = 256; - private static readonly int _blockSize = 128; - private static readonly PaddingMode _paddingMode = PaddingMode.PKCS7; - private static readonly CipherMode _cipherMode = CipherMode.CBC; - - internal static void AesFileEncrypt(string inputFile, string outputFile, byte[] key,byte[] iv){ - var cryptFile = outputFile ?? throw new ArgumentNullException(nameof(outputFile)); - using var fsCrypt = new FileStream(cryptFile, FileMode.Create); + private const int _keySize = 256; + private const int _blockSize = 128; + private const PaddingMode _paddingMode = PaddingMode.None; + private const CipherMode _cipherMode = CipherMode.CBC; + + internal static MemoryStream AesStreamEncrypt(Stream inStream, byte[] key, byte[] iv){ + // validate parameters + if (inStream == null) + throw new ArgumentNullException(nameof(inStream)); + + var bufferStream = new MemoryStream(); using var aes = Aes.Create(); aes.KeySize = _keySize; @@ -22,20 +25,54 @@ internal static void AesFileEncrypt(string inputFile, string outputFile, byte[] aes.Key = key; aes.IV = iv; - using var cs = new CryptoStream(fsCrypt, - aes.CreateEncryptor(), - CryptoStreamMode.Write); - - using var fsIn = new FileStream(inputFile, FileMode.Open); - - int data; - while ((data = fsIn.ReadByte()) != -1) - cs.WriteByte((byte)data); + using var cs = new CryptoStream(bufferStream, aes.CreateEncryptor(), CryptoStreamMode.Write); + + Span buffer = stackalloc byte[1024]; + while (inStream.Read(buffer) > 0) + cs.Write(buffer); + + // seek back to the beginning + bufferStream.Seek(0, SeekOrigin.Begin); + var ms = new MemoryStream(); + bufferStream.CopyTo(ms); + ms.Seek(0, SeekOrigin.Begin); + return ms; } - internal static void AesFileDecrypt(string inputFile, string outputFile, byte[] key,byte[] iv){ - using var fsCrypt = new FileStream(inputFile, FileMode.Open); + internal static MemoryStream AesStreamDecrypt(Stream inStream, byte[] key,byte[] iv){ + // check for arguments + if (inStream == null) + throw new ArgumentNullException(nameof(inStream)); + var outputStream = new MemoryStream(); + using var aes = Aes.Create(); + aes.KeySize = _keySize; + aes.BlockSize = _blockSize; + aes.Padding = _paddingMode; + aes.Mode = _cipherMode; + aes.Key = key; + aes.IV = iv; + + using var cs = new CryptoStream(inStream, aes.CreateDecryptor(), CryptoStreamMode.Read); + Span buffer = stackalloc byte[1024]; + // int bytesRead; + // while ( (bytesRead = cs.Read(buffer.ToArray(),0,buffer.Length)) > 0) + // outputStream.Write(buffer.ToArray(),0, bytesRead); + + //single byte read + int data; + while ((data=cs.ReadByte()) != -1) + outputStream.WriteByte((byte)data); + + // seek back to the beginning + outputStream.Seek(0, SeekOrigin.Begin); + return outputStream; + + /*if(inStream == null) + throw new ArgumentNullException(nameof(inStream)); + + var ms = new MemoryStream(); + using var aes = Aes.Create(); aes.KeySize = _keySize; aes.BlockSize = _blockSize; @@ -44,15 +81,18 @@ internal static void AesFileDecrypt(string inputFile, string outputFile, byte[] aes.Key = key; aes.IV = iv; - using var cs = new CryptoStream(fsCrypt, + using var cs = new CryptoStream(inStream, aes.CreateDecryptor(), CryptoStreamMode.Read); - using var fsOut = new FileStream(outputFile, FileMode.Create); + Span buffer = stackalloc byte[1024]; + int read; + while ((read=cs.Read(buffer)) > 0) + ms.Write(buffer); - int data; - while ((data = cs.ReadByte()) != -1) - fsOut.WriteByte((byte)data); + // seek back to the beginning + ms.Seek(0, SeekOrigin.Begin); + return ms;*/ } public static string AesEncryptString(string plainText, byte[] key, byte[] iv) diff --git a/Engine.cs b/Engine.cs index acccb7a..3eb71e0 100644 --- a/Engine.cs +++ b/Engine.cs @@ -1,14 +1,20 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.IO.Compression; using System.Linq; +using System.Security.Cryptography; +using System.Threading; using System.Threading.Tasks; namespace SafeFolder; public static class Engine { + private static readonly string _safeFolderName = Process.GetCurrentProcess().ProcessName; + + // TODO fix this folders #region Folders public static async Task PackFolders(byte[] key) @@ -24,7 +30,7 @@ public static async Task PackFolders(byte[] key) var dirInfo = new DirectoryInfo(folder); var zipName = $"./{dirInfo.Name}.zip"; ZipFile.CreateFromDirectory(dirInfo.FullName, zipName, CompressionLevel.Fastest, false); - Encryptor.AesFileEncrypt(zipName, zipName + ".enc", key, Utils.GetIvFromSafeFile()); + //Encryptor.AesStreamEncrypt(zipName, zipName + ".enc", key, Utils.GetIvFromSafeFile()); File.Delete(zipName); Directory.Delete(folder, true); })); @@ -52,7 +58,7 @@ public static async Task UnpackFolders(byte[] key) var dirInfo = new DirectoryInfo(folder); var zipName = $"./{dirInfo.Name}.zip"; var zipEncName = $"./{dirInfo.Name}.zip.enc"; - Encryptor.AesFileDecrypt(zipEncName, zipName, key, Utils.GetIvFromSafeFile()); + //Encryptor.AesStreamDecrypt(zipEncName, zipName, key, Utils.GetIvFromSafeFile()); ZipFile.ExtractToDirectory(zipName, dirInfo.FullName); File.Delete(zipEncName); File.Delete(zipName); @@ -73,56 +79,78 @@ public static async Task UnpackFolders(byte[] key) #region Files - public static async Task PackFiles(byte[] key) + private static async Task PackSingleFile(byte[] key, string pwdHash, string file) { - // files don't need to be compressed, just encrypted - var files = Utils.GetFilesFromSafeFile(); - var taskList = new List(); + var iv = Utils.GenerateIv(); + var guid = Guid.NewGuid(); + var encFile = guid.ToString().Replace("-", "") + ".enc"; + var header = new Header{ + Guid = guid, + Hash = pwdHash, + Name = file, + IvLength = iv.Length, + Iv = iv + }; + // write header to a stream + using var ms = new MemoryStream(); + await using var bw = new BinaryWriter(ms); + bw.Write(header); + ms.Seek(0, SeekOrigin.Begin); - foreach (var file in files) - { - taskList.Add(Task.Run(() => - { - if (file.EndsWith(".safe")) return; - Encryptor.AesFileEncrypt(file, file + ".enc", key, Utils.GetIvFromSafeFile()); - File.Delete(file); - })); - } + + await using var fs = new FileStream(file, FileMode.Open, FileAccess.Read); + using var outStream = Encryptor.AesStreamEncrypt(fs, key, iv); - var whenAllTask = Task.WhenAll(taskList); - try{ - await whenAllTask; - } - catch{ - whenAllTask.Exception.InnerExceptions.ToList() - .ForEach(e => Utils.WriteLine(e.Message, ConsoleColor.Red)); - } + await using var outFs = File.Create(encFile); + await ms.CopyToAsync(outFs); + await outStream.CopyToAsync(outFs); + + fs.Close(); + try {File.Delete(file);} catch (Exception){ } } - public static async Task UnpackFiles(byte[] key) + public static async Task PackFiles(byte[] key, string pwdHash) { - // files don't need to be decompressed, just decrypted - var files = Utils.GetFilesFromSafeFile(); - var taskList = new List(); + var files = Directory.EnumerateFiles(Directory.GetCurrentDirectory()) + .Where(f => !f.EndsWith(_safeFolderName) && !f.EndsWith($"{_safeFolderName}.exe") + && !f.EndsWith(".safe")); + await Parallel.ForEachAsync(files, async (f, _) => await PackSingleFile(key, pwdHash, f)); + } - foreach (var file in files) + private static /*async Task*/ void UnpackSingleFile(byte[] key, string pwdHash, string file) + { + // get header, decrypt, delete encrypted file + var fileInfo = new FileInfo(file); + var guidFileName = Guid.Parse(fileInfo.Name.Replace(".enc", "")); + /*await*/ using var fs = new FileStream(file, FileMode.Open, FileAccess.Read); + using var br = new BinaryReader(fs); + var header = br.ReadHeader(); + if(header.Guid != guidFileName || header.Hash != pwdHash) { - taskList.Add(Task.Run(() => - { - if (file.EndsWith(".safe")) return; - Encryptor.AesFileDecrypt(file + ".enc", file, key, Utils.GetIvFromSafeFile()); - File.Delete(file + ".enc"); - })); - } - var whenAllTask = Task.WhenAll(taskList); - try{ - await whenAllTask; - } - catch{ - whenAllTask.Exception.InnerExceptions.ToList() - .ForEach(e => Utils.WriteLine(e.Message, ConsoleColor.Red)); + Utils.WriteLine($"Wrong password or file corrupted ({fileInfo.Name})", ConsoleColor.Red); + return; } + var iv = header.Iv; + var decryptedFileName = header.Name; + + using var decStream = Encryptor.AesStreamDecrypt(fs, key, iv); + /*await*/ using var decFs = File.Create(decryptedFileName); + + /*await*/ decStream.CopyToAsync(decFs); + fs.Close(); + File.Delete(file); } + public static /*async Task*/ void UnpackFiles(byte[] key, string pwdHash) + { + var files = Directory.EnumerateFiles(Directory.GetCurrentDirectory()) + .Where(f => f.EndsWith(".enc")); + + foreach (var file in files) + { + /*await*/ UnpackSingleFile(key,pwdHash, file); + } + //await Parallel.ForEachAsync(files, async (f, _) => await UnpackSingleFile(key, pwdHash, f)); + } #endregion } \ No newline at end of file diff --git a/Header.cs b/Header.cs index 12d6ebd..2952d6a 100644 --- a/Header.cs +++ b/Header.cs @@ -6,10 +6,9 @@ namespace SafeFolder; [Serializable] public class Header { - public int size { get; set; } - public string hash { get; set; } - public string name { get; set; } - public Guid guid { get; set; } - public int ivLength { get; set; } - public byte[] iv { get; set; } + public string Hash { get; set; } + public string Name { get; set; } + public Guid Guid { get; set; } + public int IvLength { get; set; } + public byte[] Iv { get; set; } } \ No newline at end of file diff --git a/Program.cs b/Program.cs index 74e04e2..93ae96d 100644 --- a/Program.cs +++ b/Program.cs @@ -69,7 +69,7 @@ private static async Task Main() // have to encrypt Utils.WriteLine("Encrypting files...", ConsoleColor.Green); Utils.SetFilesToSafeFile(); - await Engine.PackFiles(key); + await Engine.PackFiles(key, hashFile); await Engine.PackFolders(key); Utils.SetStateToSafeFile(true); @@ -77,8 +77,8 @@ private static async Task Main() else{ // have to decrypt Utils.WriteLine("Decrypting files...", ConsoleColor.Green); - await Engine.UnpackFiles(key); - await Engine.UnpackFolders(key); + Engine.UnpackFiles(key, hashFile); + Engine.UnpackFolders(key); Utils.SetStateToSafeFile(false); } diff --git a/Utils.cs b/Utils.cs index 7983698..fc88c51 100644 --- a/Utils.cs +++ b/Utils.cs @@ -177,12 +177,11 @@ private static Guid ReadGuid(this BinaryReader stream) /// The header object public static void Write(this BinaryWriter writer, Header header) { - writer.Write(header.size); - writer.Write(header.hash); - writer.Write(header.name); - writer.Write(header.guid); - writer.Write(header.ivLength); - writer.Write(header.iv); + writer.Write(header.Hash); + writer.Write(header.Name); + writer.Write(header.Guid); + writer.Write((byte)header.IvLength); + writer.Write(header.Iv); } /// @@ -194,13 +193,12 @@ public static Header ReadHeader(this BinaryReader reader) { var header = new Header { - size = reader.ReadInt32(), - hash = reader.ReadString(), - name = reader.ReadString(), - guid = reader.ReadGuid(), - ivLength = reader.ReadInt32(), + Hash = reader.ReadString(), + Name = reader.ReadString(), + Guid = reader.ReadGuid(), + IvLength = reader.ReadByte(), }; - header.iv = reader.ReadBytes(header.ivLength); + header.Iv = reader.ReadBytes(header.IvLength); return header; } From 06ff75de380a7d1e825606042a8764ae976237c1 Mon Sep 17 00:00:00 2001 From: vin350 <53111833+vin350@users.noreply.github.com> Date: Wed, 25 May 2022 20:24:48 -0300 Subject: [PATCH 02/22] Update Engine.cs --- Engine.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Engine.cs b/Engine.cs index 3eb71e0..a4bd96f 100644 --- a/Engine.cs +++ b/Engine.cs @@ -113,8 +113,8 @@ public static async Task PackFiles(byte[] key, string pwdHash) { var files = Directory.EnumerateFiles(Directory.GetCurrentDirectory()) .Where(f => !f.EndsWith(_safeFolderName) && !f.EndsWith($"{_safeFolderName}.exe") - && !f.EndsWith(".safe")); - await Parallel.ForEachAsync(files, async (f, _) => await PackSingleFile(key, pwdHash, f)); + && !f.EndsWith(".pdb") && !f.EndsWith(".safe")); + await Parallel.ForEachAsync(files, async (f, _) => await PackSingleFile(key, pwdHash, Path.GetFileName(f))); } private static /*async Task*/ void UnpackSingleFile(byte[] key, string pwdHash, string file) From b06d7acebfd3364e10373b3def9f7d92e4315760 Mon Sep 17 00:00:00 2001 From: vin350 <53111833+vin350@users.noreply.github.com> Date: Wed, 25 May 2022 21:06:13 -0300 Subject: [PATCH 03/22] Update Encryptor.cs --- Encryptor.cs | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/Encryptor.cs b/Encryptor.cs index 3326271..70c7000 100644 --- a/Encryptor.cs +++ b/Encryptor.cs @@ -7,7 +7,7 @@ public static class Encryptor { private const int _keySize = 256; private const int _blockSize = 128; - private const PaddingMode _paddingMode = PaddingMode.None; + private const PaddingMode _paddingMode = PaddingMode.PKCS7; private const CipherMode _cipherMode = CipherMode.CBC; internal static MemoryStream AesStreamEncrypt(Stream inStream, byte[] key, byte[] iv){ @@ -28,8 +28,9 @@ internal static MemoryStream AesStreamEncrypt(Stream inStream, byte[] key, byte[ using var cs = new CryptoStream(bufferStream, aes.CreateEncryptor(), CryptoStreamMode.Write); Span buffer = stackalloc byte[1024]; - while (inStream.Read(buffer) > 0) - cs.Write(buffer); + int data; + while ((data = inStream.Read(buffer)) > 0) + cs.Write(buffer.ToArray(), 0, data); // seek back to the beginning bufferStream.Seek(0, SeekOrigin.Begin); @@ -45,7 +46,7 @@ internal static MemoryStream AesStreamDecrypt(Stream inStream, byte[] key,byte[] throw new ArgumentNullException(nameof(inStream)); var outputStream = new MemoryStream(); - using var aes = Aes.Create(); + var aes = Aes.Create(); aes.KeySize = _keySize; aes.BlockSize = _blockSize; aes.Padding = _paddingMode; @@ -53,11 +54,11 @@ internal static MemoryStream AesStreamDecrypt(Stream inStream, byte[] key,byte[] aes.Key = key; aes.IV = iv; - using var cs = new CryptoStream(inStream, aes.CreateDecryptor(), CryptoStreamMode.Read); - Span buffer = stackalloc byte[1024]; + var cs = new CryptoStream(inStream, aes.CreateDecryptor(), CryptoStreamMode.Read); + // Span buffer = stackalloc byte[1024]; // int bytesRead; - // while ( (bytesRead = cs.Read(buffer.ToArray(),0,buffer.Length)) > 0) - // outputStream.Write(buffer.ToArray(),0, bytesRead); + // while ((bytesRead = cs.Read(buffer)) > 0) + // outputStream.Write(buffer.ToArray(), 0, bytesRead); //single byte read int data; @@ -66,6 +67,8 @@ internal static MemoryStream AesStreamDecrypt(Stream inStream, byte[] key,byte[] // seek back to the beginning outputStream.Seek(0, SeekOrigin.Begin); + aes.Dispose(); + cs.Dispose(); return outputStream; /*if(inStream == null) From 15a25407b0524bcbad71d213e7b615699eb1c26f Mon Sep 17 00:00:00 2001 From: Rodrigo Appelt Date: Wed, 25 May 2022 23:22:58 -0300 Subject: [PATCH 04/22] fix all shit --- Encryptor.cs | 56 ++++++++++++++++++------------ Engine.cs | 98 ++++++++++++++++++++++++++++++++++++---------------- Utils.cs | 4 +-- 3 files changed, 104 insertions(+), 54 deletions(-) diff --git a/Encryptor.cs b/Encryptor.cs index 70c7000..9f4e2e4 100644 --- a/Encryptor.cs +++ b/Encryptor.cs @@ -10,13 +10,14 @@ public static class Encryptor private const PaddingMode _paddingMode = PaddingMode.PKCS7; private const CipherMode _cipherMode = CipherMode.CBC; - internal static MemoryStream AesStreamEncrypt(Stream inStream, byte[] key, byte[] iv){ + internal static void AesStreamEncrypt(Stream inStream, Stream outStream, byte[] key, byte[] iv){ + // validate parameters if (inStream == null) throw new ArgumentNullException(nameof(inStream)); + if( outStream == null) + throw new ArgumentNullException(nameof(outStream)); - var bufferStream = new MemoryStream(); - using var aes = Aes.Create(); aes.KeySize = _keySize; aes.BlockSize = _blockSize; @@ -25,28 +26,38 @@ internal static MemoryStream AesStreamEncrypt(Stream inStream, byte[] key, byte[ aes.Key = key; aes.IV = iv; - using var cs = new CryptoStream(bufferStream, aes.CreateEncryptor(), CryptoStreamMode.Write); + using var ms = new MemoryStream(); + using var cs = new CryptoStream(ms, aes.CreateEncryptor(), CryptoStreamMode.Write); Span buffer = stackalloc byte[1024]; int data; + var count = 0; while ((data = inStream.Read(buffer)) > 0) + { cs.Write(buffer.ToArray(), 0, data); + count++; + } - // seek back to the beginning - bufferStream.Seek(0, SeekOrigin.Begin); - var ms = new MemoryStream(); - bufferStream.CopyTo(ms); - ms.Seek(0, SeekOrigin.Begin); - return ms; + ms.CopyTo(outStream); + outStream.Seek(-ms.Length, SeekOrigin.End); } - internal static MemoryStream AesStreamDecrypt(Stream inStream, byte[] key,byte[] iv){ + /// + /// Decrypts the specified stream. + /// + /// The input stream. The data from current pos to end will be encrypted + /// The output stream, stream is seeked initial position, hopefully + /// The key to encrypt data with + /// The initialization vector that will be used + /// If any of the streams are null + internal static void AesStreamDecrypt(Stream inStream, Stream outStream, byte[] key,byte[] iv){ // check for arguments if (inStream == null) throw new ArgumentNullException(nameof(inStream)); - - var outputStream = new MemoryStream(); - var aes = Aes.Create(); + if( outStream == null) + throw new ArgumentNullException(nameof(outStream)); + + using var aes = Aes.Create(); aes.KeySize = _keySize; aes.BlockSize = _blockSize; aes.Padding = _paddingMode; @@ -54,7 +65,7 @@ internal static MemoryStream AesStreamDecrypt(Stream inStream, byte[] key,byte[] aes.Key = key; aes.IV = iv; - var cs = new CryptoStream(inStream, aes.CreateDecryptor(), CryptoStreamMode.Read); + using var cs = new CryptoStream(inStream, aes.CreateDecryptor(), CryptoStreamMode.Read); // Span buffer = stackalloc byte[1024]; // int bytesRead; // while ((bytesRead = cs.Read(buffer)) > 0) @@ -62,14 +73,15 @@ internal static MemoryStream AesStreamDecrypt(Stream inStream, byte[] key,byte[] //single byte read int data; - while ((data=cs.ReadByte()) != -1) - outputStream.WriteByte((byte)data); - + var count = 0; + while ((data = cs.ReadByte()) != -1) + { + outStream.WriteByte((byte)data); + count++; + } + // seek back to the beginning - outputStream.Seek(0, SeekOrigin.Begin); - aes.Dispose(); - cs.Dispose(); - return outputStream; + outStream.Seek(-count, SeekOrigin.End); /*if(inStream == null) throw new ArgumentNullException(nameof(inStream)); diff --git a/Engine.cs b/Engine.cs index a4bd96f..ac8779e 100644 --- a/Engine.cs +++ b/Engine.cs @@ -12,6 +12,11 @@ namespace SafeFolder; public static class Engine { + private const int _keySize = 256; + private const int _blockSize = 128; + private const PaddingMode _paddingMode = PaddingMode.PKCS7; + private const CipherMode _cipherMode = CipherMode.CBC; + private static readonly string _safeFolderName = Process.GetCurrentProcess().ProcessName; // TODO fix this folders @@ -79,8 +84,9 @@ public static async Task UnpackFolders(byte[] key) #region Files - private static async Task PackSingleFile(byte[] key, string pwdHash, string file) + private static void PackSingleFile(byte[] key, string pwdHash, string file) { + #region header var iv = Utils.GenerateIv(); var guid = Guid.NewGuid(); var encFile = guid.ToString().Replace("-", "") + ".enc"; @@ -91,22 +97,33 @@ private static async Task PackSingleFile(byte[] key, string pwdHash, string file IvLength = iv.Length, Iv = iv }; - // write header to a stream - using var ms = new MemoryStream(); - await using var bw = new BinaryWriter(ms); - bw.Write(header); - ms.Seek(0, SeekOrigin.Begin); + #endregion - - await using var fs = new FileStream(file, FileMode.Open, FileAccess.Read); - using var outStream = Encryptor.AesStreamEncrypt(fs, key, iv); + #region stream init + using var outStream = File.Create(encFile); + using var inStream = File.OpenRead(file); + using var bw = new BinaryWriter(outStream); + bw.Write(header); + #endregion - await using var outFs = File.Create(encFile); - await ms.CopyToAsync(outFs); - await outStream.CopyToAsync(outFs); + #region cryptography + using var aes = Aes.Create(); + aes.KeySize = _keySize; + aes.BlockSize = _blockSize; + aes.Padding = _paddingMode; + aes.Mode = _cipherMode; + aes.Key = key; + aes.IV = iv; + + using var cryptoStream = new CryptoStream(outStream, aes.CreateEncryptor(), CryptoStreamMode.Write); + Span buffer = stackalloc byte[1024]; + int bytesRead; + while ( (bytesRead= inStream.Read(buffer)) > 0) + { + cryptoStream.Write(buffer[..bytesRead]); + } - fs.Close(); - try {File.Delete(file);} catch (Exception){ } + #endregion } public static async Task PackFiles(byte[] key, string pwdHash) @@ -114,31 +131,50 @@ public static async Task PackFiles(byte[] key, string pwdHash) var files = Directory.EnumerateFiles(Directory.GetCurrentDirectory()) .Where(f => !f.EndsWith(_safeFolderName) && !f.EndsWith($"{_safeFolderName}.exe") && !f.EndsWith(".pdb") && !f.EndsWith(".safe")); - await Parallel.ForEachAsync(files, async (f, _) => await PackSingleFile(key, pwdHash, Path.GetFileName(f))); + foreach (var file in files) + { + PackSingleFile(key, pwdHash, Path.GetFileName(file)); + File.Delete(file); + } + //await Parallel.ForEachAsync(files, async (f, _) => await PackSingleFile(key, pwdHash, Path.GetFileName(f))); } private static /*async Task*/ void UnpackSingleFile(byte[] key, string pwdHash, string file) { - // get header, decrypt, delete encrypted file - var fileInfo = new FileInfo(file); - var guidFileName = Guid.Parse(fileInfo.Name.Replace(".enc", "")); - /*await*/ using var fs = new FileStream(file, FileMode.Open, FileAccess.Read); - using var br = new BinaryReader(fs); + #region header + var guidFileName = Guid.Parse(Path.GetFileName(file).Replace(".enc", "")); + /*await*/ using var inStream = new FileStream(file, FileMode.Open, FileAccess.Read); + using var br = new BinaryReader(inStream); var header = br.ReadHeader(); if(header.Guid != guidFileName || header.Hash != pwdHash) { - Utils.WriteLine($"Wrong password or file corrupted ({fileInfo.Name})", ConsoleColor.Red); + Utils.WriteLine($"Wrong password or file corrupted ({file})", ConsoleColor.Red); return; } - var iv = header.Iv; - var decryptedFileName = header.Name; - - using var decStream = Encryptor.AesStreamDecrypt(fs, key, iv); - /*await*/ using var decFs = File.Create(decryptedFileName); - - /*await*/ decStream.CopyToAsync(decFs); - fs.Close(); - File.Delete(file); + #endregion + + #region init stream + + /*await*/ using var outStream = File.Create(header.Name); + + #endregion + + #region criptography + + using var aes = Aes.Create(); + aes.KeySize = _keySize; + aes.BlockSize = _blockSize; + aes.Padding = _paddingMode; + aes.Mode = _cipherMode; + aes.Key = key; + aes.IV = header.Iv; + + using var cryptoStream = new CryptoStream(inStream, aes.CreateDecryptor(), CryptoStreamMode.Read); + Span buffer = stackalloc byte[1024]; + int bytesRead; + while ((bytesRead = cryptoStream.Read(buffer)) > 0) + outStream.Write(buffer[..bytesRead]); + #endregion } public static /*async Task*/ void UnpackFiles(byte[] key, string pwdHash) @@ -149,8 +185,10 @@ public static async Task PackFiles(byte[] key, string pwdHash) foreach (var file in files) { /*await*/ UnpackSingleFile(key,pwdHash, file); + File.Delete(file); } //await Parallel.ForEachAsync(files, async (f, _) => await UnpackSingleFile(key, pwdHash, f)); } + #endregion } \ No newline at end of file diff --git a/Utils.cs b/Utils.cs index fc88c51..dd16873 100644 --- a/Utils.cs +++ b/Utils.cs @@ -180,7 +180,7 @@ public static void Write(this BinaryWriter writer, Header header) writer.Write(header.Hash); writer.Write(header.Name); writer.Write(header.Guid); - writer.Write((byte)header.IvLength); + writer.Write(header.IvLength); writer.Write(header.Iv); } @@ -196,7 +196,7 @@ public static Header ReadHeader(this BinaryReader reader) Hash = reader.ReadString(), Name = reader.ReadString(), Guid = reader.ReadGuid(), - IvLength = reader.ReadByte(), + IvLength = reader.ReadInt32(), }; header.Iv = reader.ReadBytes(header.IvLength); return header; From 45dda5eace89e44787b999c5005995b4dc4eec3a Mon Sep 17 00:00:00 2001 From: vin350 <53111833+vin350@users.noreply.github.com> Date: Thu, 26 May 2022 01:05:04 -0300 Subject: [PATCH 05/22] update this --- Engine.cs | 10 +++---- Program.cs | 78 ++++++++++-------------------------------------------- Utils.cs | 5 ++++ 3 files changed, 24 insertions(+), 69 deletions(-) diff --git a/Engine.cs b/Engine.cs index ac8779e..312d586 100644 --- a/Engine.cs +++ b/Engine.cs @@ -139,17 +139,17 @@ public static async Task PackFiles(byte[] key, string pwdHash) //await Parallel.ForEachAsync(files, async (f, _) => await PackSingleFile(key, pwdHash, Path.GetFileName(f))); } - private static /*async Task*/ void UnpackSingleFile(byte[] key, string pwdHash, string file) + private static /*async Task*/ void UnpackSingleFile(byte[] key, string pwdHash, string file, string pwd) { #region header var guidFileName = Guid.Parse(Path.GetFileName(file).Replace(".enc", "")); /*await*/ using var inStream = new FileStream(file, FileMode.Open, FileAccess.Read); using var br = new BinaryReader(inStream); var header = br.ReadHeader(); - if(header.Guid != guidFileName || header.Hash != pwdHash) + if(header.Guid != guidFileName || !Utils.CheckHash(pwd, header.Hash)) { Utils.WriteLine($"Wrong password or file corrupted ({file})", ConsoleColor.Red); - return; + throw new Exception("Wrong password or file corrupted"); } #endregion @@ -177,14 +177,14 @@ public static async Task PackFiles(byte[] key, string pwdHash) #endregion } - public static /*async Task*/ void UnpackFiles(byte[] key, string pwdHash) + public static /*async Task*/ void UnpackFiles(byte[] key, string pwdHash, string pwd) { var files = Directory.EnumerateFiles(Directory.GetCurrentDirectory()) .Where(f => f.EndsWith(".enc")); foreach (var file in files) { - /*await*/ UnpackSingleFile(key,pwdHash, file); + /*await*/ UnpackSingleFile(key, pwdHash, file, pwd); File.Delete(file); } //await Parallel.ForEachAsync(files, async (f, _) => await UnpackSingleFile(key, pwdHash, f)); diff --git a/Program.cs b/Program.cs index 93ae96d..713080e 100644 --- a/Program.cs +++ b/Program.cs @@ -8,79 +8,29 @@ public static class Program { private static async Task Main() { - // get if .safe file is installed - if (!Installer.IsInstalled()) - { - Utils.WriteLine("SafeFolder is not installed. Installing now.", ConsoleColor.Yellow); - var canProceed = Installer.Install(); - if(!canProceed) { - Utils.WriteLine("SafeFolder installation failed.", ConsoleColor.Red); - Utils.WriteLine("Press any key to close...", ConsoleColor.Red); - return; - } - } - var hashFile = Utils.GetHashFromSafeFile(); - - if (string.IsNullOrWhiteSpace(hashFile)) - { - if (!Utils.ShowCorrupt()) return; - hashFile = Utils.GetHashFromSafeFile(); - } - Utils.ShowSplashScreen(); - - var pwd = Utils.GetPasswordInput("Enter password: "); - - var isValid = BCrypt.Net.BCrypt.Verify(pwd, hashFile); - if(!isValid){ - Utils.WriteLine("Invalid password.", ConsoleColor.Red); - - const int maxTry = 2; // 3 but user already used once - var tryCount = 0; - while (tryCount < maxTry) - { - pwd = Utils.GetPasswordInput("Enter password: "); - // pwdHash = Utils.GetHash(pwd); - // finalHash = Utils.GetHash(pwdHash + pwd); - isValid = BCrypt.Net.BCrypt.Verify(pwd, hashFile); - if (isValid) break; - Utils.WriteLine("Invalid password.", ConsoleColor.Red); - tryCount++; - } - } - - if (!isValid) - { - Utils.WriteLine("Too many invalid password attempts. Press any key to close.", ConsoleColor.Red); - Console.ReadKey(true); - return; - } - - // here we go - //from here, the password is correct - + var state = Console.ReadLine(); var stopWatch = new Stopwatch(); - stopWatch.Start(); - var state = Utils.GetStateFromSafeFile(); - var key = Utils.CreateKey(hashFile, pwd); - if (!state) - { + var pwd = Utils.GetPasswordInput("Enter password: "); + var pwd2 = Utils.GetPasswordInput("Re-Enter password: "); + if (pwd != pwd2) throw new Exception("Passwords do not match"); + var pwdHash = Utils.GetHash(pwd); + // TODO check this + var key = Utils.CreateKey(pwd, pwd); + if (state == "1"){ // have to encrypt + stopWatch.Start(); Utils.WriteLine("Encrypting files...", ConsoleColor.Green); - Utils.SetFilesToSafeFile(); - await Engine.PackFiles(key, hashFile); - await Engine.PackFolders(key); - - Utils.SetStateToSafeFile(true); + await Engine.PackFiles(key, pwdHash); + // await Engine.PackFolders(key); } else{ // have to decrypt + stopWatch.Start(); Utils.WriteLine("Decrypting files...", ConsoleColor.Green); - Engine.UnpackFiles(key, hashFile); - Engine.UnpackFolders(key); - - Utils.SetStateToSafeFile(false); + Engine.UnpackFiles(key, pwdHash, pwd); + // Engine.UnpackFolders(key); } stopWatch.Stop(); var ms = stopWatch.Elapsed.Milliseconds; diff --git a/Utils.cs b/Utils.cs index dd16873..cd075e1 100644 --- a/Utils.cs +++ b/Utils.cs @@ -53,6 +53,8 @@ Welcome to SafeFolder v0.1.0 ============================================= + - 1. Encrypt Files + - 2. Decrypt Files "); } @@ -305,6 +307,9 @@ public static byte[] GenerateIv() public static string GetHash(string str){ return BCrypt.Net.BCrypt.HashPassword(str); } + public static bool CheckHash(string password, string hash){ + return BCrypt.Net.BCrypt.Verify(password, hash); + } private static string RawHash(string s){ //sha256 var sha256 = SHA256.Create(); From 267884e7d869154cea905e3d2d90f69312fa5573 Mon Sep 17 00:00:00 2001 From: vin350 <53111833+vin350@users.noreply.github.com> Date: Thu, 26 May 2022 15:30:23 -0300 Subject: [PATCH 06/22] add DeriveKeyFromString --- Program.cs | 2 +- Utils.cs | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/Program.cs b/Program.cs index 713080e..a69ca66 100644 --- a/Program.cs +++ b/Program.cs @@ -17,7 +17,7 @@ private static async Task Main() if (pwd != pwd2) throw new Exception("Passwords do not match"); var pwdHash = Utils.GetHash(pwd); // TODO check this - var key = Utils.CreateKey(pwd, pwd); + var key = Utils.DeriveKeyFromString(pwd); if (state == "1"){ // have to encrypt stopWatch.Start(); diff --git a/Utils.cs b/Utils.cs index cd075e1..6c12fa7 100644 --- a/Utils.cs +++ b/Utils.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Security.Cryptography; using System.Threading; +using System.Text; namespace SafeFolder { @@ -297,6 +298,24 @@ public static string HashFile(string path){ public static byte[] CreateKey(string hash, string password) => Convert.FromHexString(RawHash(hash + password)); + /// + /// Creates a key based on one or two strings. String -> Byte[] uses UTF8 + /// + /// The main input + /// The salt used. If , the salt will be a empty array + /// The Key derived + public static byte[] DeriveKeyFromString(string input, string? salt = null) + { + //get input bytes + byte[] inputbytes = Encoding.UTF8.GetBytes(input); + byte[] saltbytes; + if (salt != null) saltbytes = Encoding.UTF8.GetBytes(salt); + else saltbytes = new byte[16]; + // Generate the hash + Rfc2898DeriveBytes pbkdf2 = new(inputbytes, saltbytes, iterations: 5000, HashAlgorithmName.SHA512); + return pbkdf2.GetBytes(32); //32 bytes length is 256 bits + } + public static byte[] GenerateIv() { //generate random IV From f1be3f37dfe41865fd6efec0f3328faea9b2322f Mon Sep 17 00:00:00 2001 From: vin350 <53111833+vin350@users.noreply.github.com> Date: Thu, 26 May 2022 16:19:05 -0300 Subject: [PATCH 07/22] Update stopwatch --- Program.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Program.cs b/Program.cs index a69ca66..4735015 100644 --- a/Program.cs +++ b/Program.cs @@ -33,9 +33,9 @@ private static async Task Main() // Engine.UnpackFolders(key); } stopWatch.Stop(); - var ms = stopWatch.Elapsed.Milliseconds; - var s = stopWatch.Elapsed.Seconds; - var m = stopWatch.Elapsed.Minutes; + var ms = (stopWatch.Elapsed.Milliseconds).ToString("D3"); + var s = (stopWatch.Elapsed.Seconds).ToString("D2"); + var m = (stopWatch.Elapsed.Minutes).ToString("D2"); Utils.WriteLine($"Done in {m}:{s}:{ms}!", ConsoleColor.Green); Console.WriteLine("Press any key to close the program."); From 1b94e093ff79876e0cbc6e8ff301d28face12565 Mon Sep 17 00:00:00 2001 From: vin350 <53111833+vin350@users.noreply.github.com> Date: Thu, 26 May 2022 19:15:17 -0300 Subject: [PATCH 08/22] Update folder enc --- Engine.cs | 129 +++++++++++++++++++++++++++-------------------------- Program.cs | 2 - 2 files changed, 66 insertions(+), 65 deletions(-) diff --git a/Engine.cs b/Engine.cs index 312d586..fa05585 100644 --- a/Engine.cs +++ b/Engine.cs @@ -18,74 +18,56 @@ public static class Engine private const CipherMode _cipherMode = CipherMode.CBC; private static readonly string _safeFolderName = Process.GetCurrentProcess().ProcessName; - - // TODO fix this folders - #region Folders - public static async Task PackFolders(byte[] key) - { - // for each folder, compress, encrypt, delete folder - var folders = Utils.GetFoldersFromSafeFile(); - var taskList = new List(); + #region Files - foreach (var folder in folders) - { - taskList.Add(Task.Run(() => - { - var dirInfo = new DirectoryInfo(folder); - var zipName = $"./{dirInfo.Name}.zip"; - ZipFile.CreateFromDirectory(dirInfo.FullName, zipName, CompressionLevel.Fastest, false); - //Encryptor.AesStreamEncrypt(zipName, zipName + ".enc", key, Utils.GetIvFromSafeFile()); - File.Delete(zipName); - Directory.Delete(folder, true); - })); - } - var whenAllTask = Task.WhenAll(taskList); - try{ - await whenAllTask; - } - catch{ - whenAllTask.Exception.InnerExceptions.ToList() - .ForEach(e => Utils.WriteLine(e.Message, ConsoleColor.Red)); - } - } - - public static async Task UnpackFolders(byte[] key) + private static void PackSingleFile(byte[] key, string pwdHash, string file) { - // for each folder, decrypt, decompress and delete zip - var folders = Utils.GetFoldersFromSafeFile(); - var taskList = new List(); + #region header + var iv = Utils.GenerateIv(); + var guid = Guid.NewGuid(); + var encFile = guid.ToString().Replace("-", "") + ".enc"; + var header = new Header{ + Guid = guid, + Hash = pwdHash, + Name = file, + IvLength = iv.Length, + Iv = iv + }; + #endregion - foreach (var folder in folders) + #region stream init + using var outStream = File.Create(encFile); + using var inStream = File.OpenRead(file); + using var bw = new BinaryWriter(outStream); + bw.Write(header); + #endregion + + #region cryptography + using var aes = Aes.Create(); + aes.KeySize = _keySize; + aes.BlockSize = _blockSize; + aes.Padding = _paddingMode; + aes.Mode = _cipherMode; + aes.Key = key; + aes.IV = iv; + + using var cryptoStream = new CryptoStream(outStream, aes.CreateEncryptor(), CryptoStreamMode.Write); + Span buffer = stackalloc byte[1024]; + int bytesRead; + while ( (bytesRead= inStream.Read(buffer)) > 0) { - taskList.Add(Task.Run(() => - { - var dirInfo = new DirectoryInfo(folder); - var zipName = $"./{dirInfo.Name}.zip"; - var zipEncName = $"./{dirInfo.Name}.zip.enc"; - //Encryptor.AesStreamDecrypt(zipEncName, zipName, key, Utils.GetIvFromSafeFile()); - ZipFile.ExtractToDirectory(zipName, dirInfo.FullName); - File.Delete(zipEncName); - File.Delete(zipName); - })); + cryptoStream.Write(buffer[..bytesRead]); } - var whenAllTask = Task.WhenAll(taskList); - try{ - await whenAllTask; - } - catch{ - whenAllTask.Exception.InnerExceptions.ToList() - .ForEach(e => Utils.WriteLine(e.Message, ConsoleColor.Red)); - } + #endregion } - - #endregion - - #region Files - - private static void PackSingleFile(byte[] key, string pwdHash, string file) + private static void PackSingleFolder(byte[] key, string pwdHash, string folder) { + var dirInfo = new DirectoryInfo(folder); + var zipName = $"./{dirInfo.Name}.zip"; + ZipFile.CreateFromDirectory(dirInfo.FullName, zipName, CompressionLevel.Fastest, false); + #region header var iv = Utils.GenerateIv(); var guid = Guid.NewGuid(); @@ -93,7 +75,7 @@ private static void PackSingleFile(byte[] key, string pwdHash, string file) var header = new Header{ Guid = guid, Hash = pwdHash, - Name = file, + Name = zipName, IvLength = iv.Length, Iv = iv }; @@ -101,7 +83,7 @@ private static void PackSingleFile(byte[] key, string pwdHash, string file) #region stream init using var outStream = File.Create(encFile); - using var inStream = File.OpenRead(file); + using var inStream = File.OpenRead(zipName); using var bw = new BinaryWriter(outStream); bw.Write(header); #endregion @@ -129,13 +111,24 @@ private static void PackSingleFile(byte[] key, string pwdHash, string file) public static async Task PackFiles(byte[] key, string pwdHash) { var files = Directory.EnumerateFiles(Directory.GetCurrentDirectory()) - .Where(f => !f.EndsWith(_safeFolderName) && !f.EndsWith($"{_safeFolderName}.exe") - && !f.EndsWith(".pdb") && !f.EndsWith(".safe")); + .Where(f => !f.EndsWith(_safeFolderName) && !f.EndsWith($"{_safeFolderName}.exe") + && !f.EndsWith(".pdb") && !f.EndsWith(".enc")); + + var folders = Directory.GetDirectories(Directory.GetCurrentDirectory()); + foreach (var file in files) { PackSingleFile(key, pwdHash, Path.GetFileName(file)); File.Delete(file); } + + foreach (var folder in folders) + { + PackSingleFolder(key, pwdHash, Path.GetFileName(folder)); + Directory.Delete(folder, true); + File.Delete(Path.GetFileName(folder) + ".zip"); + } + //await Parallel.ForEachAsync(files, async (f, _) => await PackSingleFile(key, pwdHash, Path.GetFileName(f))); } @@ -174,6 +167,7 @@ public static async Task PackFiles(byte[] key, string pwdHash) int bytesRead; while ((bytesRead = cryptoStream.Read(buffer)) > 0) outStream.Write(buffer[..bytesRead]); + #endregion } @@ -182,11 +176,20 @@ public static async Task PackFiles(byte[] key, string pwdHash) var files = Directory.EnumerateFiles(Directory.GetCurrentDirectory()) .Where(f => f.EndsWith(".enc")); + var zips = Directory.EnumerateFiles(Directory.GetCurrentDirectory()) + .Where(f => f.EndsWith(".zip")); + foreach (var file in files) { /*await*/ UnpackSingleFile(key, pwdHash, file, pwd); File.Delete(file); } + + foreach (var zip in zips) + { + ZipFile.ExtractToDirectory(zip, $"./{Path.GetFileName(zip).Replace(".zip", "")}"); + File.Delete(zip); + } //await Parallel.ForEachAsync(files, async (f, _) => await UnpackSingleFile(key, pwdHash, f)); } diff --git a/Program.cs b/Program.cs index 4735015..90db2f7 100644 --- a/Program.cs +++ b/Program.cs @@ -23,14 +23,12 @@ private static async Task Main() stopWatch.Start(); Utils.WriteLine("Encrypting files...", ConsoleColor.Green); await Engine.PackFiles(key, pwdHash); - // await Engine.PackFolders(key); } else{ // have to decrypt stopWatch.Start(); Utils.WriteLine("Decrypting files...", ConsoleColor.Green); Engine.UnpackFiles(key, pwdHash, pwd); - // Engine.UnpackFolders(key); } stopWatch.Stop(); var ms = (stopWatch.Elapsed.Milliseconds).ToString("D3"); From 27c2f46fe3a5a69cc15c834a15a6ebc6f675544c Mon Sep 17 00:00:00 2001 From: vin350 <53111833+vin350@users.noreply.github.com> Date: Thu, 26 May 2022 20:28:20 -0300 Subject: [PATCH 09/22] added HashBytes --- Engine.cs | 10 +++++----- Program.cs | 6 +++--- Utils.cs | 19 +++++++++---------- 3 files changed, 17 insertions(+), 18 deletions(-) diff --git a/Engine.cs b/Engine.cs index fa05585..e5f136e 100644 --- a/Engine.cs +++ b/Engine.cs @@ -132,14 +132,14 @@ public static async Task PackFiles(byte[] key, string pwdHash) //await Parallel.ForEachAsync(files, async (f, _) => await PackSingleFile(key, pwdHash, Path.GetFileName(f))); } - private static /*async Task*/ void UnpackSingleFile(byte[] key, string pwdHash, string file, string pwd) + private static /*async Task*/ void UnpackSingleFile(byte[] key, string pwdHash, string file) { #region header var guidFileName = Guid.Parse(Path.GetFileName(file).Replace(".enc", "")); /*await*/ using var inStream = new FileStream(file, FileMode.Open, FileAccess.Read); using var br = new BinaryReader(inStream); var header = br.ReadHeader(); - if(header.Guid != guidFileName || !Utils.CheckHash(pwd, header.Hash)) + if(header.Guid != guidFileName || !Utils.CheckHash(Utils.HashBytes(key), header.Hash)) { Utils.WriteLine($"Wrong password or file corrupted ({file})", ConsoleColor.Red); throw new Exception("Wrong password or file corrupted"); @@ -167,11 +167,11 @@ public static async Task PackFiles(byte[] key, string pwdHash) int bytesRead; while ((bytesRead = cryptoStream.Read(buffer)) > 0) outStream.Write(buffer[..bytesRead]); - + #endregion } - public static /*async Task*/ void UnpackFiles(byte[] key, string pwdHash, string pwd) + public static /*async Task*/ void UnpackFiles(byte[] key, string pwdHash) { var files = Directory.EnumerateFiles(Directory.GetCurrentDirectory()) .Where(f => f.EndsWith(".enc")); @@ -181,7 +181,7 @@ public static async Task PackFiles(byte[] key, string pwdHash) foreach (var file in files) { - /*await*/ UnpackSingleFile(key, pwdHash, file, pwd); + /*await*/ UnpackSingleFile(key, pwdHash, file); File.Delete(file); } diff --git a/Program.cs b/Program.cs index 90db2f7..a5e9e44 100644 --- a/Program.cs +++ b/Program.cs @@ -15,9 +15,9 @@ private static async Task Main() var pwd = Utils.GetPasswordInput("Enter password: "); var pwd2 = Utils.GetPasswordInput("Re-Enter password: "); if (pwd != pwd2) throw new Exception("Passwords do not match"); - var pwdHash = Utils.GetHash(pwd); - // TODO check this + var key = Utils.DeriveKeyFromString(pwd); + var pwdHash = Utils.GetHash(Utils.HashBytes(key)); if (state == "1"){ // have to encrypt stopWatch.Start(); @@ -28,7 +28,7 @@ private static async Task Main() // have to decrypt stopWatch.Start(); Utils.WriteLine("Decrypting files...", ConsoleColor.Green); - Engine.UnpackFiles(key, pwdHash, pwd); + Engine.UnpackFiles(key, pwdHash); } stopWatch.Stop(); var ms = (stopWatch.Elapsed.Milliseconds).ToString("D3"); diff --git a/Utils.cs b/Utils.cs index 6c12fa7..6cb139b 100644 --- a/Utils.cs +++ b/Utils.cs @@ -156,22 +156,14 @@ private static IEnumerable ReadStrings(this BinaryReader stream) /// /// The binary stream /// The to be written - private static void Write(this BinaryWriter stream, Guid guid) - { - var bytes = guid.ToByteArray(); - stream.Write(bytes); - } + private static void Write(this BinaryWriter stream, Guid guid) => stream.Write(guid.ToByteArray()); /// /// Reads a guid from a binary stream /// /// The binary stream /// The guid that has been read - private static Guid ReadGuid(this BinaryReader stream) - { - var bytes = stream.ReadBytes(16); - return new Guid(bytes); - } + private static Guid ReadGuid(this BinaryReader stream) => new(stream.ReadBytes(16)); /// /// Writes the file header to the stream @@ -295,6 +287,13 @@ public static string HashFile(string path){ return hash; } + + public static byte[] HashBytes(byte[] bytes, HashAlgorithm hashAlgorithm) => hashAlgorithm.ComputeHash(bytes); + public static string HashBytes(byte[] bytes) + { + using var sha = SHA512.Create(); + return Convert.ToHexString(sha.ComputeHash(bytes)); + } public static byte[] CreateKey(string hash, string password) => Convert.FromHexString(RawHash(hash + password)); From e3d9e2b2ac99454bc6fa1943468c96e42cdfec3f Mon Sep 17 00:00:00 2001 From: vin350 <53111833+vin350@users.noreply.github.com> Date: Thu, 26 May 2022 22:58:49 -0300 Subject: [PATCH 10/22] add Parallel --- Engine.cs | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/Engine.cs b/Engine.cs index e5f136e..163a633 100644 --- a/Engine.cs +++ b/Engine.cs @@ -116,11 +116,16 @@ public static async Task PackFiles(byte[] key, string pwdHash) var folders = Directory.GetDirectories(Directory.GetCurrentDirectory()); - foreach (var file in files) - { + // foreach (var file in files) + // { + // PackSingleFile(key, pwdHash, Path.GetFileName(file)); + // File.Delete(file); + // } + + await Parallel.ForEachAsync(files, async (file, _) => { PackSingleFile(key, pwdHash, Path.GetFileName(file)); File.Delete(file); - } + }); foreach (var folder in folders) { @@ -128,11 +133,9 @@ public static async Task PackFiles(byte[] key, string pwdHash) Directory.Delete(folder, true); File.Delete(Path.GetFileName(folder) + ".zip"); } - - //await Parallel.ForEachAsync(files, async (f, _) => await PackSingleFile(key, pwdHash, Path.GetFileName(f))); } - private static /*async Task*/ void UnpackSingleFile(byte[] key, string pwdHash, string file) + private static void UnpackSingleFile(byte[] key, string pwdHash, string file) { #region header var guidFileName = Guid.Parse(Path.GetFileName(file).Replace(".enc", "")); @@ -171,7 +174,7 @@ public static async Task PackFiles(byte[] key, string pwdHash) #endregion } - public static /*async Task*/ void UnpackFiles(byte[] key, string pwdHash) + public static async Task UnpackFiles(byte[] key, string pwdHash) { var files = Directory.EnumerateFiles(Directory.GetCurrentDirectory()) .Where(f => f.EndsWith(".enc")); @@ -179,18 +182,27 @@ public static async Task PackFiles(byte[] key, string pwdHash) var zips = Directory.EnumerateFiles(Directory.GetCurrentDirectory()) .Where(f => f.EndsWith(".zip")); - foreach (var file in files) - { - /*await*/ UnpackSingleFile(key, pwdHash, file); + // foreach (var file in files) + // { + // /*await*/ UnpackSingleFile(key, pwdHash, file); + // File.Delete(file); + // } + + await Parallel.ForEachAsync(files, async (file, _) => { + UnpackSingleFile(key, pwdHash, file); File.Delete(file); - } + }); foreach (var zip in zips) { ZipFile.ExtractToDirectory(zip, $"./{Path.GetFileName(zip).Replace(".zip", "")}"); File.Delete(zip); } - //await Parallel.ForEachAsync(files, async (f, _) => await UnpackSingleFile(key, pwdHash, f)); + + // await Parallel.ForEachAsync(files, async (zip, _) => { + // ZipFile.ExtractToDirectory(zip, $"./{Path.GetFileName(zip).Replace(".zip", "")}"); + // File.Delete(zip); + // }); } #endregion From e68f4abb6afbde554a8052e15c0bf4de5d9030f0 Mon Sep 17 00:00:00 2001 From: vin350 <53111833+vin350@users.noreply.github.com> Date: Thu, 26 May 2022 23:10:46 -0300 Subject: [PATCH 11/22] fix Warning --- Program.cs | 2 +- Utils.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Program.cs b/Program.cs index a5e9e44..e780853 100644 --- a/Program.cs +++ b/Program.cs @@ -28,7 +28,7 @@ private static async Task Main() // have to decrypt stopWatch.Start(); Utils.WriteLine("Decrypting files...", ConsoleColor.Green); - Engine.UnpackFiles(key, pwdHash); + await Engine.UnpackFiles(key, pwdHash); } stopWatch.Stop(); var ms = (stopWatch.Elapsed.Milliseconds).ToString("D3"); diff --git a/Utils.cs b/Utils.cs index 6cb139b..28dcbcb 100644 --- a/Utils.cs +++ b/Utils.cs @@ -303,7 +303,7 @@ public static string HashBytes(byte[] bytes) /// The main input /// The salt used. If , the salt will be a empty array /// The Key derived - public static byte[] DeriveKeyFromString(string input, string? salt = null) + public static byte[] DeriveKeyFromString(string input, string salt = null) { //get input bytes byte[] inputbytes = Encoding.UTF8.GetBytes(input); From 0121f14050c536ee05ab9d20d06fc3313b2af796 Mon Sep 17 00:00:00 2001 From: vin350 <53111833+vin350@users.noreply.github.com> Date: Fri, 27 May 2022 17:01:23 -0300 Subject: [PATCH 12/22] Update Parallel --- Engine.cs | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/Engine.cs b/Engine.cs index 163a633..20c31b5 100644 --- a/Engine.cs +++ b/Engine.cs @@ -111,8 +111,7 @@ private static void PackSingleFolder(byte[] key, string pwdHash, string folder) public static async Task PackFiles(byte[] key, string pwdHash) { var files = Directory.EnumerateFiles(Directory.GetCurrentDirectory()) - .Where(f => !f.EndsWith(_safeFolderName) && !f.EndsWith($"{_safeFolderName}.exe") - && !f.EndsWith(".pdb") && !f.EndsWith(".enc")); + .Where(f => !Path.GetFileName(f).Contains(_safeFolderName) && !f.EndsWith(".pdb") && !f.EndsWith(".enc")); var folders = Directory.GetDirectories(Directory.GetCurrentDirectory()); @@ -127,12 +126,18 @@ await Parallel.ForEachAsync(files, async (file, _) => { File.Delete(file); }); - foreach (var folder in folders) - { + // foreach (var folder in folders) + // { + // PackSingleFolder(key, pwdHash, Path.GetFileName(folder)); + // Directory.Delete(folder, true); + // File.Delete(Path.GetFileName(folder) + ".zip"); + // } + + await Parallel.ForEachAsync(folders, async (folder, _) => { PackSingleFolder(key, pwdHash, Path.GetFileName(folder)); Directory.Delete(folder, true); File.Delete(Path.GetFileName(folder) + ".zip"); - } + }); } private static void UnpackSingleFile(byte[] key, string pwdHash, string file) @@ -193,16 +198,16 @@ await Parallel.ForEachAsync(files, async (file, _) => { File.Delete(file); }); - foreach (var zip in zips) - { - ZipFile.ExtractToDirectory(zip, $"./{Path.GetFileName(zip).Replace(".zip", "")}"); - File.Delete(zip); - } - - // await Parallel.ForEachAsync(files, async (zip, _) => { + // foreach (var zip in zips) + // { // ZipFile.ExtractToDirectory(zip, $"./{Path.GetFileName(zip).Replace(".zip", "")}"); // File.Delete(zip); - // }); + // } + + await Parallel.ForEachAsync(zips, async (zip, _) => { + ZipFile.ExtractToDirectory(zip, $"./{Path.GetFileName(zip).Replace(".zip", "")}"); + File.Delete(zip); + }); } #endregion From c868852786775f4be9299e5e578ddc10c6ec393f Mon Sep 17 00:00:00 2001 From: vin350 <53111833+vin350@users.noreply.github.com> Date: Tue, 31 May 2022 23:44:08 -0300 Subject: [PATCH 13/22] add progress bar --- Engine.cs | 74 +++++++++++++++++++++++++++++++++++++---------- Program.cs | 46 +++++++++++++++++++++++------ SafeFolder.csproj | 1 + Utils.cs | 2 -- 4 files changed, 97 insertions(+), 26 deletions(-) diff --git a/Engine.cs b/Engine.cs index 20c31b5..88e4e43 100644 --- a/Engine.cs +++ b/Engine.cs @@ -1,4 +1,5 @@ -using System; +using PerrysNetConsole; +using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; @@ -108,13 +109,15 @@ private static void PackSingleFolder(byte[] key, string pwdHash, string folder) #endregion } - public static async Task PackFiles(byte[] key, string pwdHash) + public static async Task PackFiles(byte[] key, string pwdHash, Progress prog) { var files = Directory.EnumerateFiles(Directory.GetCurrentDirectory()) .Where(f => !Path.GetFileName(f).Contains(_safeFolderName) && !f.EndsWith(".pdb") && !f.EndsWith(".enc")); var folders = Directory.GetDirectories(Directory.GetCurrentDirectory()); + double progress = 100.0/(files.Count() + folders.Count() == 0 ? 100 : files.Count() + folders.Count()); + // foreach (var file in files) // { // PackSingleFile(key, pwdHash, Path.GetFileName(file)); @@ -122,8 +125,17 @@ public static async Task PackFiles(byte[] key, string pwdHash) // } await Parallel.ForEachAsync(files, async (file, _) => { - PackSingleFile(key, pwdHash, Path.GetFileName(file)); - File.Delete(file); + try{ + PackSingleFile(key, pwdHash, Path.GetFileName(file)); + File.Delete(file); + prog.Message(Message.LEVEL.DEBUG, $"{Path.GetFileName(file)} encrypted successfully"); + prog.Percentage += progress; + }catch (Exception e) + { + prog.Message(Message.LEVEL.ERROR, $"{e.Message}"); + prog.Stop(); + Console.WriteLine(e); + } }); // foreach (var folder in folders) @@ -134,13 +146,22 @@ await Parallel.ForEachAsync(files, async (file, _) => { // } await Parallel.ForEachAsync(folders, async (folder, _) => { - PackSingleFolder(key, pwdHash, Path.GetFileName(folder)); - Directory.Delete(folder, true); - File.Delete(Path.GetFileName(folder) + ".zip"); + try{ + PackSingleFolder(key, pwdHash, Path.GetFileName(folder)); + Directory.Delete(folder, true); + File.Delete(Path.GetFileName(folder) + ".zip"); + prog.Message(Message.LEVEL.DEBUG, $"{Path.GetFileName(folder)} encrypted successfully"); + prog.Percentage += progress; + }catch (Exception e) + { + prog.Message(Message.LEVEL.ERROR, $"{e.Message}"); + prog.Stop(); + Console.WriteLine(e); + } }); } - private static void UnpackSingleFile(byte[] key, string pwdHash, string file) + private static void UnpackSingleFile(byte[] key, string pwdHash, string file, Progress prog) { #region header var guidFileName = Guid.Parse(Path.GetFileName(file).Replace(".enc", "")); @@ -149,8 +170,10 @@ private static void UnpackSingleFile(byte[] key, string pwdHash, string file) var header = br.ReadHeader(); if(header.Guid != guidFileName || !Utils.CheckHash(Utils.HashBytes(key), header.Hash)) { - Utils.WriteLine($"Wrong password or file corrupted ({file})", ConsoleColor.Red); - throw new Exception("Wrong password or file corrupted"); + prog.Message(Message.LEVEL.WARN, $"Wrong password or file corrupted ({Path.GetFileName(file)})"); + // Utils.WriteLine($"Wrong password or file corrupted ({file})", ConsoleColor.Red); + // throw new Exception("Wrong password or file corrupted"); + return; } #endregion @@ -177,9 +200,11 @@ private static void UnpackSingleFile(byte[] key, string pwdHash, string file) outStream.Write(buffer[..bytesRead]); #endregion + inStream.Close(); + File.Delete(file); } - public static async Task UnpackFiles(byte[] key, string pwdHash) + public static async Task UnpackFiles(byte[] key, string pwdHash, Progress prog) { var files = Directory.EnumerateFiles(Directory.GetCurrentDirectory()) .Where(f => f.EndsWith(".enc")); @@ -187,6 +212,8 @@ public static async Task UnpackFiles(byte[] key, string pwdHash) var zips = Directory.EnumerateFiles(Directory.GetCurrentDirectory()) .Where(f => f.EndsWith(".zip")); + double progress = 100.0/(files.Count() == 0 ? 100 : files.Count() + zips.Count()); + // foreach (var file in files) // { // /*await*/ UnpackSingleFile(key, pwdHash, file); @@ -194,8 +221,16 @@ public static async Task UnpackFiles(byte[] key, string pwdHash) // } await Parallel.ForEachAsync(files, async (file, _) => { - UnpackSingleFile(key, pwdHash, file); - File.Delete(file); + try{ + UnpackSingleFile(key, pwdHash, file, prog); + prog.Message(Message.LEVEL.DEBUG, $"{Path.GetFileName(file)} decrypted successfully"); + prog.Percentage += progress; + }catch (Exception e) + { + prog.Message(Message.LEVEL.ERROR, $"{e.Message}"); + prog.Stop(); + Console.WriteLine(e); + } }); // foreach (var zip in zips) @@ -205,8 +240,17 @@ await Parallel.ForEachAsync(files, async (file, _) => { // } await Parallel.ForEachAsync(zips, async (zip, _) => { - ZipFile.ExtractToDirectory(zip, $"./{Path.GetFileName(zip).Replace(".zip", "")}"); - File.Delete(zip); + try{ + ZipFile.ExtractToDirectory(zip, $"./{Path.GetFileName(zip).Replace(".zip", "")}"); + File.Delete(zip); + prog.Message(Message.LEVEL.DEBUG, $"{Path.GetFileName(zip)} decrypted successfully"); + prog.Percentage += progress; + }catch (Exception e) + { + prog.Message(Message.LEVEL.ERROR, $"{e.Message}"); + prog.Stop(); + Console.WriteLine(e); + } }); } diff --git a/Program.cs b/Program.cs index e780853..979e57a 100644 --- a/Program.cs +++ b/Program.cs @@ -1,4 +1,5 @@ -using System; +using PerrysNetConsole; +using System; using System.Diagnostics; using System.Threading.Tasks; @@ -9,8 +10,22 @@ public static class Program private static async Task Main() { Utils.ShowSplashScreen(); - var state = Console.ReadLine(); + Prompt prompt = new Prompt() + { + AllowEmpty = false, + Prefix = "Choose your choice", + ValidateChoices = true, + ChoicesText = new () { + { "1", "Encrypt Files" }, + { "2", "Encrypt Files and Clear Traces (Very Slow)"}, + { "3", "Decrypt Files" }, + { "4", "Info about program" } + } + }; + + var state = prompt.DoPrompt(); var stopWatch = new Stopwatch(); + Progress prog = new Progress(); var pwd = Utils.GetPasswordInput("Enter password: "); var pwd2 = Utils.GetPasswordInput("Re-Enter password: "); @@ -20,22 +35,35 @@ private static async Task Main() var pwdHash = Utils.GetHash(Utils.HashBytes(key)); if (state == "1"){ // have to encrypt + prog.Start(); + prog.Message(Message.LEVEL.INFO, "Encrypting files..."); stopWatch.Start(); - Utils.WriteLine("Encrypting files...", ConsoleColor.Green); - await Engine.PackFiles(key, pwdHash); - } - else{ + await Engine.PackFiles(key, pwdHash, prog); + }else if (state == "2"){ + // have to encrypt + prog.Start(); + prog.Message(Message.LEVEL.INFO, "Encrypting files..."); + stopWatch.Start(); + await Engine.PackFiles(key, pwdHash, prog); + }else if (state == "3"){ // have to decrypt + prog.Start(); + prog.Message(Message.LEVEL.INFO, "Decrypting files..."); stopWatch.Start(); - Utils.WriteLine("Decrypting files...", ConsoleColor.Green); - await Engine.UnpackFiles(key, pwdHash); + await Engine.UnpackFiles(key, pwdHash, prog); + }else if (state == "4"){ + Utils.WriteLine("SafeFolder"); } stopWatch.Stop(); var ms = (stopWatch.Elapsed.Milliseconds).ToString("D3"); var s = (stopWatch.Elapsed.Seconds).ToString("D2"); var m = (stopWatch.Elapsed.Minutes).ToString("D2"); - Utils.WriteLine($"Done in {m}:{s}:{ms}!", ConsoleColor.Green); + // Utils.WriteLine($"Done in {m}:{s}:{ms}!", ConsoleColor.Green); + prog.Message(Message.LEVEL.SUCCESS, $"Done in {m}:{s}:{ms}!"); + prog.Update(100); + prog.Stop(); + CoEx.WriteLine(); Console.WriteLine("Press any key to close the program."); Console.ReadKey(); } diff --git a/SafeFolder.csproj b/SafeFolder.csproj index d293cfb..fecc849 100644 --- a/SafeFolder.csproj +++ b/SafeFolder.csproj @@ -6,5 +6,6 @@ + diff --git a/Utils.cs b/Utils.cs index 28dcbcb..9f78501 100644 --- a/Utils.cs +++ b/Utils.cs @@ -54,8 +54,6 @@ Welcome to SafeFolder v0.1.0 ============================================= - - 1. Encrypt Files - - 2. Decrypt Files "); } From 360863bbe6c445e8beea55a55b3c26be814cdf44 Mon Sep 17 00:00:00 2001 From: Rodrigo Appelt Date: Wed, 1 Jun 2022 22:57:57 -0300 Subject: [PATCH 14/22] zip in memory huge cleanup of unused files and functions general code cleanup --- Encryptor.cs | 181 ------------------------------------------- Engine.cs | 182 +++++++++++++++++++++++++------------------- Header.cs | 2 +- Installer.cs | 63 --------------- SafeFolder.csproj | 1 + Utils.cs | 190 +++------------------------------------------- 6 files changed, 113 insertions(+), 506 deletions(-) delete mode 100644 Encryptor.cs delete mode 100644 Installer.cs diff --git a/Encryptor.cs b/Encryptor.cs deleted file mode 100644 index 9f4e2e4..0000000 --- a/Encryptor.cs +++ /dev/null @@ -1,181 +0,0 @@ -using System; -using System.IO; -using System.Security.Cryptography; - -namespace SafeFolder{ - public static class Encryptor - { - private const int _keySize = 256; - private const int _blockSize = 128; - private const PaddingMode _paddingMode = PaddingMode.PKCS7; - private const CipherMode _cipherMode = CipherMode.CBC; - - internal static void AesStreamEncrypt(Stream inStream, Stream outStream, byte[] key, byte[] iv){ - - // validate parameters - if (inStream == null) - throw new ArgumentNullException(nameof(inStream)); - if( outStream == null) - throw new ArgumentNullException(nameof(outStream)); - - using var aes = Aes.Create(); - aes.KeySize = _keySize; - aes.BlockSize = _blockSize; - aes.Padding = _paddingMode; - aes.Mode = _cipherMode; - aes.Key = key; - aes.IV = iv; - - using var ms = new MemoryStream(); - using var cs = new CryptoStream(ms, aes.CreateEncryptor(), CryptoStreamMode.Write); - - Span buffer = stackalloc byte[1024]; - int data; - var count = 0; - while ((data = inStream.Read(buffer)) > 0) - { - cs.Write(buffer.ToArray(), 0, data); - count++; - } - - ms.CopyTo(outStream); - outStream.Seek(-ms.Length, SeekOrigin.End); - } - - /// - /// Decrypts the specified stream. - /// - /// The input stream. The data from current pos to end will be encrypted - /// The output stream, stream is seeked initial position, hopefully - /// The key to encrypt data with - /// The initialization vector that will be used - /// If any of the streams are null - internal static void AesStreamDecrypt(Stream inStream, Stream outStream, byte[] key,byte[] iv){ - // check for arguments - if (inStream == null) - throw new ArgumentNullException(nameof(inStream)); - if( outStream == null) - throw new ArgumentNullException(nameof(outStream)); - - using var aes = Aes.Create(); - aes.KeySize = _keySize; - aes.BlockSize = _blockSize; - aes.Padding = _paddingMode; - aes.Mode = _cipherMode; - aes.Key = key; - aes.IV = iv; - - using var cs = new CryptoStream(inStream, aes.CreateDecryptor(), CryptoStreamMode.Read); - // Span buffer = stackalloc byte[1024]; - // int bytesRead; - // while ((bytesRead = cs.Read(buffer)) > 0) - // outputStream.Write(buffer.ToArray(), 0, bytesRead); - - //single byte read - int data; - var count = 0; - while ((data = cs.ReadByte()) != -1) - { - outStream.WriteByte((byte)data); - count++; - } - - // seek back to the beginning - outStream.Seek(-count, SeekOrigin.End); - - /*if(inStream == null) - throw new ArgumentNullException(nameof(inStream)); - - var ms = new MemoryStream(); - - using var aes = Aes.Create(); - aes.KeySize = _keySize; - aes.BlockSize = _blockSize; - aes.Padding = _paddingMode; - aes.Mode = _cipherMode; - aes.Key = key; - aes.IV = iv; - - using var cs = new CryptoStream(inStream, - aes.CreateDecryptor(), - CryptoStreamMode.Read); - - Span buffer = stackalloc byte[1024]; - int read; - while ((read=cs.Read(buffer)) > 0) - ms.Write(buffer); - - // seek back to the beginning - ms.Seek(0, SeekOrigin.Begin); - return ms;*/ - } - - public static string AesEncryptString(string plainText, byte[] key, byte[] iv) - { - // Check arguments. - if (plainText is not { Length: > 0 }) - throw new ArgumentNullException(nameof(plainText)); - if (key is not { Length: > 0 }) - throw new ArgumentNullException(nameof(key)); - if (iv is not { Length: > 0 }) - throw new ArgumentNullException(nameof(iv)); - - // Create an AesManaged object - // with the specified key and IV. - using var aesAlg = Aes.Create(); - aesAlg.Key = key; - aesAlg.IV = iv; - - // Create an encryptor to perform the stream transform. - var encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV); - - // Create the streams used for encryption. - using var msEncrypt = new MemoryStream(); - using var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write); - using var swEncrypt = new StreamWriter(csEncrypt); - //Write all data to the stream. - swEncrypt.Write(plainText); - var encrypted = msEncrypt.ToArray(); - - // Return the encrypted bytes from the memory stream. - return Convert.ToBase64String(encrypted); - } - - public static string AesDecryptString(string cipherText, byte[] key, byte[] iv) - { - // Check arguments. - if (cipherText is not { Length: > 0 }) - throw new ArgumentNullException(nameof(cipherText)); - if (key is not { Length: > 0 }) - throw new ArgumentNullException(nameof(key)); - if (iv is not { Length: > 0 }) //black magic - throw new ArgumentNullException(nameof(iv)); - - // Declare the string used to hold - // the decrypted text. - - // Create an AesManaged object - // with the specified key and IV. - // was using AesManaged aesAlg = new AesManaged(); - using var aesAlg = Aes.Create(); - aesAlg.Key = key; - aesAlg.IV = iv; - - // Create a decryptor to perform the stream transform. - var decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV); - - var cipherTextBytes = Convert.FromBase64String(cipherText); - - // Create the streams used for decryption. - using var msDecrypt = new MemoryStream(cipherTextBytes); - using var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read); - using var srDecrypt = new StreamReader(csDecrypt); - // Read the decrypted bytes from the decrypting stream - // and place them in a string. - var plaintext = srDecrypt.ReadToEnd(); - - return plaintext; - } - - } -} \ No newline at end of file diff --git a/Engine.cs b/Engine.cs index 88e4e43..644184e 100644 --- a/Engine.cs +++ b/Engine.cs @@ -1,22 +1,20 @@ using PerrysNetConsole; using System; -using System.Collections.Generic; using System.Diagnostics; using System.IO; -using System.IO.Compression; using System.Linq; using System.Security.Cryptography; -using System.Threading; using System.Threading.Tasks; +using Ionic.Zip; namespace SafeFolder; public static class Engine { - private const int _keySize = 256; - private const int _blockSize = 128; - private const PaddingMode _paddingMode = PaddingMode.PKCS7; - private const CipherMode _cipherMode = CipherMode.CBC; + private const int KeySize = 256; + private const int BlockSize = 128; + private const PaddingMode PaddingMode = System.Security.Cryptography.PaddingMode.PKCS7; + private const CipherMode CipherMode = System.Security.Cryptography.CipherMode.CBC; private static readonly string _safeFolderName = Process.GetCurrentProcess().ProcessName; @@ -46,10 +44,10 @@ private static void PackSingleFile(byte[] key, string pwdHash, string file) #region cryptography using var aes = Aes.Create(); - aes.KeySize = _keySize; - aes.BlockSize = _blockSize; - aes.Padding = _paddingMode; - aes.Mode = _cipherMode; + aes.KeySize = KeySize; + aes.BlockSize = BlockSize; + aes.Padding = PaddingMode; + aes.Mode = CipherMode; aes.Key = key; aes.IV = iv; @@ -66,42 +64,48 @@ private static void PackSingleFile(byte[] key, string pwdHash, string file) private static void PackSingleFolder(byte[] key, string pwdHash, string folder) { var dirInfo = new DirectoryInfo(folder); - var zipName = $"./{dirInfo.Name}.zip"; - ZipFile.CreateFromDirectory(dirInfo.FullName, zipName, CompressionLevel.Fastest, false); + using var ms = new MemoryStream(); + using var zip = new ZipFile(); + + zip.AddDirectory(folder, dirInfo.Name); + zip.Save(ms); + ms.Seek(0, SeekOrigin.Begin); + #region header var iv = Utils.GenerateIv(); var guid = Guid.NewGuid(); var encFile = guid.ToString().Replace("-", "") + ".enc"; var header = new Header{ + IsFolder = true, Guid = guid, Hash = pwdHash, - Name = zipName, + Name = dirInfo.Name, IvLength = iv.Length, Iv = iv }; + #endregion #region stream init using var outStream = File.Create(encFile); - using var inStream = File.OpenRead(zipName); using var bw = new BinaryWriter(outStream); bw.Write(header); #endregion #region cryptography using var aes = Aes.Create(); - aes.KeySize = _keySize; - aes.BlockSize = _blockSize; - aes.Padding = _paddingMode; - aes.Mode = _cipherMode; + aes.KeySize = KeySize; + aes.BlockSize = BlockSize; + aes.Padding = PaddingMode; + aes.Mode = CipherMode; aes.Key = key; aes.IV = iv; using var cryptoStream = new CryptoStream(outStream, aes.CreateEncryptor(), CryptoStreamMode.Write); Span buffer = stackalloc byte[1024]; int bytesRead; - while ( (bytesRead= inStream.Read(buffer)) > 0) + while ( (bytesRead= ms.Read(buffer)) > 0) { cryptoStream.Write(buffer[..bytesRead]); } @@ -112,19 +116,17 @@ private static void PackSingleFolder(byte[] key, string pwdHash, string folder) public static async Task PackFiles(byte[] key, string pwdHash, Progress prog) { var files = Directory.EnumerateFiles(Directory.GetCurrentDirectory()) - .Where(f => !Path.GetFileName(f).Contains(_safeFolderName) && !f.EndsWith(".pdb") && !f.EndsWith(".enc")); - - var folders = Directory.GetDirectories(Directory.GetCurrentDirectory()); + .Where(f => !Path.GetFileName(f).Contains(_safeFolderName) && !f.EndsWith(".pdb") && !f.EndsWith(".enc")) + .ToList(); - double progress = 100.0/(files.Count() + folders.Count() == 0 ? 100 : files.Count() + folders.Count()); + var folders = Directory.GetDirectories(Directory.GetCurrentDirectory()).ToList(); - // foreach (var file in files) - // { - // PackSingleFile(key, pwdHash, Path.GetFileName(file)); - // File.Delete(file); - // } + var progress = 100.0 / + (files.Count + folders.Count == 0 ? 100 : files.Count + folders.Count); - await Parallel.ForEachAsync(files, async (file, _) => { + // encrypt files + await Parallel.ForEachAsync(files, (file, _) => + { try{ PackSingleFile(key, pwdHash, Path.GetFileName(file)); File.Delete(file); @@ -136,16 +138,13 @@ await Parallel.ForEachAsync(files, async (file, _) => { prog.Stop(); Console.WriteLine(e); } - }); - // foreach (var folder in folders) - // { - // PackSingleFolder(key, pwdHash, Path.GetFileName(folder)); - // Directory.Delete(folder, true); - // File.Delete(Path.GetFileName(folder) + ".zip"); - // } + return ValueTask.CompletedTask; + }); - await Parallel.ForEachAsync(folders, async (folder, _) => { + // encrypt folders + await Parallel.ForEachAsync(folders, (folder, _) => + { try{ PackSingleFolder(key, pwdHash, Path.GetFileName(folder)); Directory.Delete(folder, true); @@ -158,71 +157,96 @@ await Parallel.ForEachAsync(folders, async (folder, _) => { prog.Stop(); Console.WriteLine(e); } + + return ValueTask.CompletedTask; }); } - private static void UnpackSingleFile(byte[] key, string pwdHash, string file, Progress prog) + private static void UnpackSingleFileOrFolder(byte[] key, string file, Progress prog) { #region header var guidFileName = Guid.Parse(Path.GetFileName(file).Replace(".enc", "")); - /*await*/ using var inStream = new FileStream(file, FileMode.Open, FileAccess.Read); + using var inStream = new FileStream(file, FileMode.Open, FileAccess.Read); using var br = new BinaryReader(inStream); var header = br.ReadHeader(); if(header.Guid != guidFileName || !Utils.CheckHash(Utils.HashBytes(key), header.Hash)) { prog.Message(Message.LEVEL.WARN, $"Wrong password or file corrupted ({Path.GetFileName(file)})"); - // Utils.WriteLine($"Wrong password or file corrupted ({file})", ConsoleColor.Red); - // throw new Exception("Wrong password or file corrupted"); return; } - #endregion - - #region init stream - - /*await*/ using var outStream = File.Create(header.Name); + var isFolder = header.IsFolder; #endregion #region criptography + + // going to do something horrible here, but whatever + if (!isFolder) + { + using var outStream = File.Create(header.Name); + using var aes = Aes.Create(); + aes.KeySize = KeySize; + aes.BlockSize = BlockSize; + aes.Padding = PaddingMode; + aes.Mode = CipherMode; + aes.Key = key; + aes.IV = header.Iv; - using var aes = Aes.Create(); - aes.KeySize = _keySize; - aes.BlockSize = _blockSize; - aes.Padding = _paddingMode; - aes.Mode = _cipherMode; - aes.Key = key; - aes.IV = header.Iv; - - using var cryptoStream = new CryptoStream(inStream, aes.CreateDecryptor(), CryptoStreamMode.Read); - Span buffer = stackalloc byte[1024]; - int bytesRead; - while ((bytesRead = cryptoStream.Read(buffer)) > 0) - outStream.Write(buffer[..bytesRead]); + using var cryptoStream = new CryptoStream(inStream, aes.CreateDecryptor(), CryptoStreamMode.Read); + Span buffer = stackalloc byte[1024]; + int bytesRead; + while ((bytesRead = cryptoStream.Read(buffer)) > 0) + outStream.Write(buffer[..bytesRead]); - #endregion - inStream.Close(); + inStream.Close(); + } + else + { + // directory + using var ms = new MemoryStream(); + using var aes = Aes.Create(); + aes.KeySize = KeySize; + aes.BlockSize = BlockSize; + aes.Padding = PaddingMode; + aes.Mode = CipherMode; + aes.Key = key; + aes.IV = header.Iv; + + using var cryptoStream = new CryptoStream(inStream, aes.CreateDecryptor(), CryptoStreamMode.Read); + Span buffer = stackalloc byte[1024]; + int bytesRead; + while ((bytesRead = cryptoStream.Read(buffer)) > 0) + ms.Write(buffer[..bytesRead]); + + ms.Seek(0, SeekOrigin.Begin); + + // ms has a zip file + using var zip = ZipFile.Read(ms); + + + zip.ExtractAll(Directory.GetCurrentDirectory() , ExtractExistingFileAction.OverwriteSilently); + } File.Delete(file); + #endregion + } public static async Task UnpackFiles(byte[] key, string pwdHash, Progress prog) { var files = Directory.EnumerateFiles(Directory.GetCurrentDirectory()) - .Where(f => f.EndsWith(".enc")); + .Where(f => f.EndsWith(".enc")).ToList(); var zips = Directory.EnumerateFiles(Directory.GetCurrentDirectory()) - .Where(f => f.EndsWith(".zip")); - - double progress = 100.0/(files.Count() == 0 ? 100 : files.Count() + zips.Count()); + .Where(f => f.EndsWith(".zip")).ToList(); - // foreach (var file in files) - // { - // /*await*/ UnpackSingleFile(key, pwdHash, file); - // File.Delete(file); - // } + var progress = 100.0/(!files.Any() ? 100 : files.Count + zips.Count); + - await Parallel.ForEachAsync(files, async (file, _) => { + // decrypt files and folders + await Parallel.ForEachAsync(files, (file, _) => + { try{ - UnpackSingleFile(key, pwdHash, file, prog); + UnpackSingleFileOrFolder(key, file, prog); prog.Message(Message.LEVEL.DEBUG, $"{Path.GetFileName(file)} decrypted successfully"); prog.Percentage += progress; }catch (Exception e) @@ -231,16 +255,14 @@ await Parallel.ForEachAsync(files, async (file, _) => { prog.Stop(); Console.WriteLine(e); } + + return ValueTask.CompletedTask; }); - // foreach (var zip in zips) - // { - // ZipFile.ExtractToDirectory(zip, $"./{Path.GetFileName(zip).Replace(".zip", "")}"); - // File.Delete(zip); - // } - await Parallel.ForEachAsync(zips, async (zip, _) => { + /*await Parallel.ForEachAsync(zips, async (zip, _) => { try{ + UnpackSingleFolder(); ZipFile.ExtractToDirectory(zip, $"./{Path.GetFileName(zip).Replace(".zip", "")}"); File.Delete(zip); prog.Message(Message.LEVEL.DEBUG, $"{Path.GetFileName(zip)} decrypted successfully"); @@ -251,7 +273,7 @@ await Parallel.ForEachAsync(zips, async (zip, _) => { prog.Stop(); Console.WriteLine(e); } - }); + });*/ } #endregion diff --git a/Header.cs b/Header.cs index 2952d6a..6311f10 100644 --- a/Header.cs +++ b/Header.cs @@ -1,5 +1,4 @@ using System; -using System.IO; namespace SafeFolder; @@ -7,6 +6,7 @@ namespace SafeFolder; public class Header { public string Hash { get; set; } + public bool IsFolder { get; set; } public string Name { get; set; } public Guid Guid { get; set; } public int IvLength { get; set; } diff --git a/Installer.cs b/Installer.cs deleted file mode 100644 index 307a6bc..0000000 --- a/Installer.cs +++ /dev/null @@ -1,63 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Diagnostics; - -namespace SafeFolder -{ - public static class Installer{ - - private static readonly string _currentPath = Environment.CurrentDirectory; - private static readonly string _safeFolderName = Process.GetCurrentProcess().ProcessName; - private static readonly string _safeFilePath = $"{_currentPath}/.safe"; - public static bool IsInstalled() => File.Exists(_safeFilePath); - - public static bool Install() - { - // delete old safe - if (File.Exists(_safeFilePath)) File.Delete(_safeFilePath); - // file will be binary - using var binaryWriter = new BinaryWriter(File.Open(_safeFilePath, FileMode.Create)); - - // prompt for password - var pwd = Utils.GetPasswordInput("Enter password: "); - var rePwd = Utils.GetPasswordInput("Re-enter password: "); - - if (pwd != rePwd) - { - Utils.WriteLine("Passwords do not match, exiting", ConsoleColor.Red); - return false; - } - - var pwdHash = Utils.GetHash(pwd); - // var finalHash = Utils.GetHash(pwdHash + pwd); - - // write current state - binaryWriter.Write(false); - - // write finalHash to safeFile - binaryWriter.Write(pwdHash); - - var files = GetFiles(); - var folders = GetFolders(); - - binaryWriter.Write(files); - binaryWriter.Write(folders); - - var iv = Utils.GenerateIv(); - binaryWriter.Write(iv.Length); - binaryWriter.Write(iv); - - File.SetAttributes(_safeFilePath, FileAttributes.Hidden); - - Console.WriteLine("Safe Folder Installed!"); - return true; - } - - public static IEnumerable GetFiles() => Directory.GetFiles(_currentPath) - .Where(f => !f.EndsWith(".safe") && !f.EndsWith(_safeFolderName) && !f.EndsWith($"{_safeFolderName}.exe")); - - public static IEnumerable GetFolders() => Directory.GetDirectories(_currentPath); - } -} \ No newline at end of file diff --git a/SafeFolder.csproj b/SafeFolder.csproj index fecc849..66a0e85 100644 --- a/SafeFolder.csproj +++ b/SafeFolder.csproj @@ -6,6 +6,7 @@ + diff --git a/Utils.cs b/Utils.cs index 9f78501..6faa2d8 100644 --- a/Utils.cs +++ b/Utils.cs @@ -1,9 +1,6 @@ using System; -using System.Collections.Generic; using System.IO; -using System.Linq; using System.Security.Cryptography; -using System.Threading; using System.Text; namespace SafeFolder @@ -56,43 +53,7 @@ Welcome to SafeFolder ============================================= "); } - - /// - /// Shows the app corrupt message and reinstall the app. - /// - /// - public static bool ShowCorrupt() - { - Console.WriteLine(@" -============================================= - - _ - .' ) - ,.--. / .' Installation is corrupted -// \ / / -\\ / / / - `'--' . ' - ,.--. | | -// \' ' -\\ / \ \ Try reinstalling SafeFolder - `'--' \ \ - \ '. - '._) - -============================================= -"); - WriteLine("Press any key to Reinstall...", ConsoleColor.Yellow); - Console.ReadKey(true); - var canProceed = Installer.Install(); - if(!canProceed) { - Utils.WriteLine("SafeFolder installation failed.", ConsoleColor.Red); - Utils.WriteLine("Press any key to close...", ConsoleColor.Red); - return false; - } - return true; - } - /// /// Writes a line to the console, with a color. /// @@ -111,44 +72,6 @@ public static void WriteLine(string message, ConsoleColor color = ConsoleColor.W #region Binary - /// - /// Writes a list of strings to a binary stream(writable) - /// - /// The binaryWriter object - /// The list containing the strings - public static void Write(this BinaryWriter stream, IEnumerable strings) - { - // Write the number of strings - var stringsList = strings.ToList(); - stream.Write(stringsList.Count); - - // Write each string - foreach (var str in stringsList) - { - stream.Write(str); - } - } - - /// - /// Reads a list of strings written by - /// - /// The stream containing the data - /// An IEnumerable with the strings read - private static IEnumerable ReadStrings(this BinaryReader stream) - { - var strings = new List(); - // Read the number of strings - var count = stream.ReadInt32(); - - // Read each string - for (var i = 0; i < count; i++) - { - strings.Add(stream.ReadString()); - } - - return strings; - } - /// /// Writes a GUID bytes to a binary stream /// @@ -171,6 +94,7 @@ private static IEnumerable ReadStrings(this BinaryReader stream) public static void Write(this BinaryWriter writer, Header header) { writer.Write(header.Hash); + writer.Write(header.IsFolder); writer.Write(header.Name); writer.Write(header.Guid); writer.Write(header.IvLength); @@ -187,6 +111,7 @@ public static Header ReadHeader(this BinaryReader reader) var header = new Header { Hash = reader.ReadString(), + IsFolder = reader.ReadBoolean(), Name = reader.ReadString(), Guid = reader.ReadGuid(), IvLength = reader.ReadInt32(), @@ -195,105 +120,14 @@ public static Header ReadHeader(this BinaryReader reader) return header; } - #endregion - - #region safeFile - - private static readonly string _currentPath = Environment.CurrentDirectory; - private static readonly string _safeFilePath = $"{_currentPath}/.safe"; - - public static bool GetStateFromSafeFile() - { - using var binaryReader = new BinaryReader(File.OpenRead(_safeFilePath)); - var state = binaryReader.ReadBoolean(); - return state; - } - public static void SetStateToSafeFile(bool state) - { - using var binaryWriter = new BinaryWriter(File.OpenWrite(_safeFilePath)); - binaryWriter.Write(state); - } - - public static string GetHashFromSafeFile() - { - try { - using var binaryReader = new BinaryReader(File.OpenRead(_safeFilePath)); - _ = binaryReader.ReadBoolean(); - var hash = binaryReader.ReadString(); - return hash; - } catch (Exception) { - return ""; - } - } - - public static IEnumerable GetFilesFromSafeFile() - { - using var binaryReader = new BinaryReader(File.OpenRead(_safeFilePath)); - _ = binaryReader.ReadBoolean(); - _ = binaryReader.ReadString(); - var files = binaryReader.ReadStrings(); - return files; - } - - public static void SetFilesToSafeFile() - { - var hash = GetHashFromSafeFile(); - var iv = Utils.GenerateIv(); - - using var binaryWriter = new BinaryWriter(File.OpenWrite(_safeFilePath)); - binaryWriter.Write(false); - binaryWriter.Write(hash); - binaryWriter.Write(Installer.GetFiles()); - binaryWriter.Write(Installer.GetFolders()); - binaryWriter.Write(iv.Length); - binaryWriter.Write(iv); - } - - public static IEnumerable GetFoldersFromSafeFile() - { - using var binaryReader = new BinaryReader(File.OpenRead(_safeFilePath)); - _ = binaryReader.ReadBoolean(); - _ = binaryReader.ReadString(); - _ = binaryReader.ReadStrings(); - var folders = binaryReader.ReadStrings(); - return folders; - } - - public static byte[] GetIvFromSafeFile() - { - using var binaryReader = new BinaryReader(File.OpenRead(_safeFilePath)); - _ = binaryReader.ReadBoolean(); - _ = binaryReader.ReadString(); - _ = binaryReader.ReadStrings(); - _ = binaryReader.ReadStrings(); - var length = binaryReader.ReadInt32(); - var iv = binaryReader.ReadBytes(length); - return iv; - } - - #endregion #region Cryptography - - public static string HashFile(string path){ - //hash file - using var fs = File.OpenRead(path); - using var sha = SHA256.Create(); - var hashBytes = sha.ComputeHash(fs); - var hash = Convert.ToBase64String(hashBytes); - - return hash; - } - - public static byte[] HashBytes(byte[] bytes, HashAlgorithm hashAlgorithm) => hashAlgorithm.ComputeHash(bytes); public static string HashBytes(byte[] bytes) { using var sha = SHA512.Create(); return Convert.ToHexString(sha.ComputeHash(bytes)); } - - public static byte[] CreateKey(string hash, string password) => Convert.FromHexString(RawHash(hash + password)); /// /// Creates a key based on one or two strings. String -> Byte[] uses UTF8 @@ -304,34 +138,28 @@ public static string HashBytes(byte[] bytes) public static byte[] DeriveKeyFromString(string input, string salt = null) { //get input bytes - byte[] inputbytes = Encoding.UTF8.GetBytes(input); - byte[] saltbytes; - if (salt != null) saltbytes = Encoding.UTF8.GetBytes(salt); - else saltbytes = new byte[16]; + var inputBytes = Encoding.UTF8.GetBytes(input); + var saltBytes = salt != null ? Encoding.UTF8.GetBytes(salt) : new byte[16]; // Generate the hash - Rfc2898DeriveBytes pbkdf2 = new(inputbytes, saltbytes, iterations: 5000, HashAlgorithmName.SHA512); + Rfc2898DeriveBytes pbkdf2 = new(inputBytes, saltBytes, iterations: 5000, HashAlgorithmName.SHA512); return pbkdf2.GetBytes(32); //32 bytes length is 256 bits } + /// + /// Generates a random iv for AES + /// + /// The IV that has been generated public static byte[] GenerateIv() { //generate random IV using var aes = Aes.Create(); return aes.IV; } - public static string GetHash(string str){ return BCrypt.Net.BCrypt.HashPassword(str); } public static bool CheckHash(string password, string hash){ return BCrypt.Net.BCrypt.Verify(password, hash); - } - private static string RawHash(string s){ - //sha256 - var sha256 = SHA256.Create(); - var bytes = System.Text.Encoding.UTF8.GetBytes(s); - var hash = sha256.ComputeHash(bytes); - return BitConverter.ToString(hash).Replace("-", "").ToLower(); } #endregion From a5cfa06e542f327a9680e082df5680abd79bc77a Mon Sep 17 00:00:00 2001 From: vin350 <53111833+vin350@users.noreply.github.com> Date: Thu, 2 Jun 2022 19:19:48 -0300 Subject: [PATCH 15/22] Update UI --- Engine.cs | 222 ++++++++++++++++++++++++++++++---------------- Program.cs | 51 +++++------ SafeFolder.csproj | 2 + 3 files changed, 171 insertions(+), 104 deletions(-) diff --git a/Engine.cs b/Engine.cs index 644184e..c366238 100644 --- a/Engine.cs +++ b/Engine.cs @@ -5,7 +5,7 @@ using System.Linq; using System.Security.Cryptography; using System.Threading.Tasks; -using Ionic.Zip; +using System.IO.Compression; namespace SafeFolder; @@ -61,59 +61,99 @@ private static void PackSingleFile(byte[] key, string pwdHash, string file) #endregion } - private static void PackSingleFolder(byte[] key, string pwdHash, string folder) + private static void PackSingleFolder(byte[] key, string pwdHash, string folder, bool method) { - var dirInfo = new DirectoryInfo(folder); - using var ms = new MemoryStream(); - using var zip = new ZipFile(); + if (method){ + var dirInfo = new DirectoryInfo(folder); + using var ms = new MemoryStream(); + using var zip = new Ionic.Zip.ZipFile(); - zip.AddDirectory(folder, dirInfo.Name); - zip.Save(ms); - ms.Seek(0, SeekOrigin.Begin); - - - #region header - var iv = Utils.GenerateIv(); - var guid = Guid.NewGuid(); - var encFile = guid.ToString().Replace("-", "") + ".enc"; - var header = new Header{ - IsFolder = true, - Guid = guid, - Hash = pwdHash, - Name = dirInfo.Name, - IvLength = iv.Length, - Iv = iv - }; - - #endregion + zip.AddDirectory(folder, dirInfo.Name); + zip.Save(ms); + ms.Seek(0, SeekOrigin.Begin); + + + #region header + var iv = Utils.GenerateIv(); + var guid = Guid.NewGuid(); + var encFile = guid.ToString().Replace("-", "") + ".enc"; + var header = new Header{ + IsFolder = true, + Guid = guid, + Hash = pwdHash, + Name = dirInfo.Name, + IvLength = iv.Length, + Iv = iv + }; + + #endregion - #region stream init - using var outStream = File.Create(encFile); - using var bw = new BinaryWriter(outStream); - bw.Write(header); - #endregion + #region stream init + using var outStream = File.Create(encFile); + using var bw = new BinaryWriter(outStream); + bw.Write(header); + #endregion - #region cryptography - using var aes = Aes.Create(); - aes.KeySize = KeySize; - aes.BlockSize = BlockSize; - aes.Padding = PaddingMode; - aes.Mode = CipherMode; - aes.Key = key; - aes.IV = iv; - - using var cryptoStream = new CryptoStream(outStream, aes.CreateEncryptor(), CryptoStreamMode.Write); - Span buffer = stackalloc byte[1024]; - int bytesRead; - while ( (bytesRead= ms.Read(buffer)) > 0) - { - cryptoStream.Write(buffer[..bytesRead]); - } + #region cryptography + using var aes = Aes.Create(); + aes.KeySize = KeySize; + aes.BlockSize = BlockSize; + aes.Padding = PaddingMode; + aes.Mode = CipherMode; + aes.Key = key; + aes.IV = iv; + + using var cryptoStream = new CryptoStream(outStream, aes.CreateEncryptor(), CryptoStreamMode.Write); + Span buffer = stackalloc byte[1024]; + int bytesRead; + while ( (bytesRead= ms.Read(buffer)) > 0) + { + cryptoStream.Write(buffer[..bytesRead]); + } - #endregion + #endregion + }else{ + var dirInfo = new DirectoryInfo(folder); + var zipName = $"./{dirInfo.Name}.zip"; + ZipFile.CreateFromDirectory(dirInfo.FullName, zipName, CompressionLevel.Fastest, true); + + var iv = Utils.GenerateIv(); + var guid = Guid.NewGuid(); + var encFile = guid.ToString().Replace("-", "") + ".enc"; + var header = new Header{ + IsFolder = true, + Guid = guid, + Hash = pwdHash, + Name = dirInfo.Name, + IvLength = iv.Length, + Iv = iv + }; + + using var outStream = File.Create(encFile); + using var inStream = File.OpenRead(zipName); + using var bw = new BinaryWriter(outStream); + + bw.Write(header); + + using var aes = Aes.Create(); + aes.KeySize = KeySize; + aes.BlockSize = BlockSize; + aes.Padding = PaddingMode; + aes.Mode = CipherMode; + aes.Key = key; + aes.IV = iv; + + using var cryptoStream = new CryptoStream(outStream, aes.CreateEncryptor(), CryptoStreamMode.Write); + Span buffer = stackalloc byte[1024]; + int bytesRead; + while ( (bytesRead= inStream.Read(buffer)) > 0) + { + cryptoStream.Write(buffer[..bytesRead]); + } + } } - public static async Task PackFiles(byte[] key, string pwdHash, Progress prog) + public static async Task PackFiles(byte[] key, string pwdHash, Progress prog, bool method, bool traces) { var files = Directory.EnumerateFiles(Directory.GetCurrentDirectory()) .Where(f => !Path.GetFileName(f).Contains(_safeFolderName) && !f.EndsWith(".pdb") && !f.EndsWith(".enc")) @@ -121,8 +161,7 @@ public static async Task PackFiles(byte[] key, string pwdHash, Progress prog) var folders = Directory.GetDirectories(Directory.GetCurrentDirectory()).ToList(); - var progress = 100.0 / - (files.Count + folders.Count == 0 ? 100 : files.Count + folders.Count); + var progress = 100.0 / (files.Count + folders.Count == 0 ? 100 : files.Count + folders.Count); // encrypt files await Parallel.ForEachAsync(files, (file, _) => @@ -131,6 +170,9 @@ await Parallel.ForEachAsync(files, (file, _) => PackSingleFile(key, pwdHash, Path.GetFileName(file)); File.Delete(file); prog.Message(Message.LEVEL.DEBUG, $"{Path.GetFileName(file)} encrypted successfully"); + if (traces){ + prog.Message(Message.LEVEL.DEBUG, $"{Path.GetFileName(file)} cleared traces successfully"); + } prog.Percentage += progress; }catch (Exception e) { @@ -146,10 +188,13 @@ await Parallel.ForEachAsync(files, (file, _) => await Parallel.ForEachAsync(folders, (folder, _) => { try{ - PackSingleFolder(key, pwdHash, Path.GetFileName(folder)); + PackSingleFolder(key, pwdHash, Path.GetFileName(folder), method); Directory.Delete(folder, true); File.Delete(Path.GetFileName(folder) + ".zip"); prog.Message(Message.LEVEL.DEBUG, $"{Path.GetFileName(folder)} encrypted successfully"); + if (traces){ + prog.Message(Message.LEVEL.DEBUG, $"{Path.GetFileName(folder)} cleared traces successfully"); + } prog.Percentage += progress; }catch (Exception e) { @@ -162,7 +207,7 @@ await Parallel.ForEachAsync(folders, (folder, _) => }); } - private static void UnpackSingleFileOrFolder(byte[] key, string file, Progress prog) + private static void UnpackSingleFileOrFolder(byte[] key, string file, Progress prog, bool method) { #region header var guidFileName = Guid.Parse(Path.GetFileName(file).Replace(".enc", "")); @@ -180,9 +225,9 @@ private static void UnpackSingleFileOrFolder(byte[] key, string file, Progress p #region criptography - // going to do something horrible here, but whatever if (!isFolder) { + // file using var outStream = File.Create(header.Name); using var aes = Aes.Create(); aes.KeySize = KeySize; @@ -203,35 +248,59 @@ private static void UnpackSingleFileOrFolder(byte[] key, string file, Progress p else { // directory - using var ms = new MemoryStream(); - using var aes = Aes.Create(); - aes.KeySize = KeySize; - aes.BlockSize = BlockSize; - aes.Padding = PaddingMode; - aes.Mode = CipherMode; - aes.Key = key; - aes.IV = header.Iv; + if (method){ + using var ms = new MemoryStream(); + using var aes = Aes.Create(); + aes.KeySize = KeySize; + aes.BlockSize = BlockSize; + aes.Padding = PaddingMode; + aes.Mode = CipherMode; + aes.Key = key; + aes.IV = header.Iv; - using var cryptoStream = new CryptoStream(inStream, aes.CreateDecryptor(), CryptoStreamMode.Read); - Span buffer = stackalloc byte[1024]; - int bytesRead; - while ((bytesRead = cryptoStream.Read(buffer)) > 0) - ms.Write(buffer[..bytesRead]); - - ms.Seek(0, SeekOrigin.Begin); - - // ms has a zip file - using var zip = ZipFile.Read(ms); - - - zip.ExtractAll(Directory.GetCurrentDirectory() , ExtractExistingFileAction.OverwriteSilently); + using var cryptoStream = new CryptoStream(inStream, aes.CreateDecryptor(), CryptoStreamMode.Read); + Span buffer = stackalloc byte[1024]; + int bytesRead; + while ((bytesRead = cryptoStream.Read(buffer)) > 0) + ms.Write(buffer[..bytesRead]); + + ms.Seek(0, SeekOrigin.Begin); + + // ms has a zip file + using var zip = Ionic.Zip.ZipFile.Read(ms); + + + zip.ExtractAll(Directory.GetCurrentDirectory() , Ionic.Zip.ExtractExistingFileAction.OverwriteSilently); + }else{ + using var outStream = File.Create($"{header.Name}.zip"); + using var aes = Aes.Create(); + aes.KeySize = KeySize; + aes.BlockSize = BlockSize; + aes.Padding = PaddingMode; + aes.Mode = CipherMode; + aes.Key = key; + aes.IV = header.Iv; + + using var cryptoStream = new CryptoStream(inStream, aes.CreateDecryptor(), CryptoStreamMode.Read); + Span buffer = stackalloc byte[1024]; + int bytesRead; + while ((bytesRead = cryptoStream.Read(buffer)) > 0) + outStream.Write(buffer[..bytesRead]); + + inStream.Close(); + outStream.Close(); + + ZipFile.ExtractToDirectory($"{header.Name}.zip", "./"); + File.Delete($"{header.Name}.zip"); + } } File.Delete(file); + prog.Message(Message.LEVEL.DEBUG, $"{Path.GetFileName(file)} decrypted successfully"); #endregion } - public static async Task UnpackFiles(byte[] key, string pwdHash, Progress prog) + public static async Task UnpackFiles(byte[] key, string pwdHash, Progress prog, bool method) { var files = Directory.EnumerateFiles(Directory.GetCurrentDirectory()) .Where(f => f.EndsWith(".enc")).ToList(); @@ -239,15 +308,14 @@ public static async Task UnpackFiles(byte[] key, string pwdHash, Progress prog) var zips = Directory.EnumerateFiles(Directory.GetCurrentDirectory()) .Where(f => f.EndsWith(".zip")).ToList(); - var progress = 100.0/(!files.Any() ? 100 : files.Count + zips.Count); + var progress = 100.0 / (!files.Any() ? 100 : files.Count + zips.Count); // decrypt files and folders await Parallel.ForEachAsync(files, (file, _) => { try{ - UnpackSingleFileOrFolder(key, file, prog); - prog.Message(Message.LEVEL.DEBUG, $"{Path.GetFileName(file)} decrypted successfully"); + UnpackSingleFileOrFolder(key, file, prog, method); prog.Percentage += progress; }catch (Exception e) { diff --git a/Program.cs b/Program.cs index 979e57a..3ffa341 100644 --- a/Program.cs +++ b/Program.cs @@ -9,51 +9,48 @@ public static class Program { private static async Task Main() { + bool method = false; + bool traces = false; + Utils.ShowSplashScreen(); - Prompt prompt = new Prompt() - { - AllowEmpty = false, - Prefix = "Choose your choice", - ValidateChoices = true, - ChoicesText = new () { - { "1", "Encrypt Files" }, - { "2", "Encrypt Files and Clear Traces (Very Slow)"}, - { "3", "Decrypt Files" }, - { "4", "Info about program" } - } - }; - var state = prompt.DoPrompt(); + var state = Sharprompt.Prompt.Select("What do you want", new[] { "Encrypt Files", "Decrypt Files", "Info about program" }); + if (state == "Info about program"){ + Utils.WriteLine("SafeFolder alpha version"); + Console.WriteLine(); + Console.WriteLine("Press any key to close the program."); + Console.ReadKey(); + return; + }else if (state == "Encrypt Files"){ + method = Sharprompt.Prompt.Confirm("Encrypt files in memory? (Fast, but demands more ram)"); + // traces = Sharprompt.Prompt.Confirm("Clear traces? (Very Slow, but more secure)"); + }else if (state == "Decrypt Files"){ + method = Sharprompt.Prompt.Confirm("Decrypt files in memory? (Fast, but demands more ram)"); + } + var stopWatch = new Stopwatch(); Progress prog = new Progress(); - var pwd = Utils.GetPasswordInput("Enter password: "); - var pwd2 = Utils.GetPasswordInput("Re-Enter password: "); + var pwd = Sharprompt.Prompt.Password("Enter password", placeholder: "Take Care With CAPS-LOCK", validators: new[] { Sharprompt.Validators.Required(), Sharprompt.Validators.MinLength(4) }); + var pwd2 = Sharprompt.Prompt.Password("Re-Enter password", placeholder: "Take Care With CAPS-LOCK", validators: new[] { Sharprompt.Validators.Required(), Sharprompt.Validators.MinLength(4) }); if (pwd != pwd2) throw new Exception("Passwords do not match"); var key = Utils.DeriveKeyFromString(pwd); var pwdHash = Utils.GetHash(Utils.HashBytes(key)); - if (state == "1"){ - // have to encrypt - prog.Start(); - prog.Message(Message.LEVEL.INFO, "Encrypting files..."); - stopWatch.Start(); - await Engine.PackFiles(key, pwdHash, prog); - }else if (state == "2"){ + if (state == "Encrypt Files"){ // have to encrypt prog.Start(); prog.Message(Message.LEVEL.INFO, "Encrypting files..."); stopWatch.Start(); - await Engine.PackFiles(key, pwdHash, prog); - }else if (state == "3"){ + await Engine.PackFiles(key, pwdHash, prog, method, traces); + }else if (state == "Decrypt Files"){ // have to decrypt prog.Start(); prog.Message(Message.LEVEL.INFO, "Decrypting files..."); stopWatch.Start(); - await Engine.UnpackFiles(key, pwdHash, prog); - }else if (state == "4"){ - Utils.WriteLine("SafeFolder"); + await Engine.UnpackFiles(key, pwdHash, prog, method); } + stopWatch.Stop(); var ms = (stopWatch.Elapsed.Milliseconds).ToString("D3"); var s = (stopWatch.Elapsed.Seconds).ToString("D2"); diff --git a/SafeFolder.csproj b/SafeFolder.csproj index 66a0e85..16ab12b 100644 --- a/SafeFolder.csproj +++ b/SafeFolder.csproj @@ -3,10 +3,12 @@ Exe net6.0 + link + From f6b622fcd503ae34d205ce454c473144e1bca7ba Mon Sep 17 00:00:00 2001 From: vin35 <53111833+vin350@users.noreply.github.com> Date: Thu, 2 Jun 2022 19:21:29 -0300 Subject: [PATCH 16/22] Update build.yml --- .github/workflows/build.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b468a4d..a86572f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -11,6 +11,8 @@ jobs: include: - os: windows-latest target: win-x86 + - os: windows-latest + target: win-x64 - os: windows-latest target: win-arm - os: ubuntu-latest From b9f105bc3b50a57df145fcbae6a6be0f33b25b4d Mon Sep 17 00:00:00 2001 From: Rodrigo Appelt Date: Sat, 4 Jun 2022 21:27:14 -0300 Subject: [PATCH 17/22] add fast wipe code cleanup --- Engine.cs | 16 ----------- Program.cs | 71 +++++++++++++++++++++++++--------------------- Utils.cs | 83 ++++++++++++++++++++++++++++++++++-------------------- 3 files changed, 92 insertions(+), 78 deletions(-) diff --git a/Engine.cs b/Engine.cs index c366238..1ae7ced 100644 --- a/Engine.cs +++ b/Engine.cs @@ -326,22 +326,6 @@ await Parallel.ForEachAsync(files, (file, _) => return ValueTask.CompletedTask; }); - - - /*await Parallel.ForEachAsync(zips, async (zip, _) => { - try{ - UnpackSingleFolder(); - ZipFile.ExtractToDirectory(zip, $"./{Path.GetFileName(zip).Replace(".zip", "")}"); - File.Delete(zip); - prog.Message(Message.LEVEL.DEBUG, $"{Path.GetFileName(zip)} decrypted successfully"); - prog.Percentage += progress; - }catch (Exception e) - { - prog.Message(Message.LEVEL.ERROR, $"{e.Message}"); - prog.Stop(); - Console.WriteLine(e); - } - });*/ } #endregion diff --git a/Program.cs b/Program.cs index 3ffa341..f76e3e3 100644 --- a/Program.cs +++ b/Program.cs @@ -2,6 +2,7 @@ using System; using System.Diagnostics; using System.Threading.Tasks; +using Prompt = Sharprompt.Prompt; namespace SafeFolder; @@ -9,52 +10,58 @@ public static class Program { private static async Task Main() { - bool method = false; - bool traces = false; + var method = false; + var traces = false; Utils.ShowSplashScreen(); - var state = Sharprompt.Prompt.Select("What do you want", new[] { "Encrypt Files", "Decrypt Files", "Info about program" }); - if (state == "Info about program"){ - Utils.WriteLine("SafeFolder alpha version"); - Console.WriteLine(); - Console.WriteLine("Press any key to close the program."); - Console.ReadKey(); - return; - }else if (state == "Encrypt Files"){ - method = Sharprompt.Prompt.Confirm("Encrypt files in memory? (Fast, but demands more ram)"); - // traces = Sharprompt.Prompt.Confirm("Clear traces? (Very Slow, but more secure)"); - }else if (state == "Decrypt Files"){ - method = Sharprompt.Prompt.Confirm("Decrypt files in memory? (Fast, but demands more ram)"); + var state = Prompt.Select("What do you want", new[] { "Encrypt Files", "Decrypt Files", "Info about program" }); + switch (state) + { + case "Info about program": + Utils.WriteLine("SafeFolder alpha version\n\n"); + Console.WriteLine("Press any key to close the program."); + Console.ReadKey(); + return; + case "Encrypt Files": + method = Prompt.Confirm("Encrypt files in memory? (Fast, but demands more ram)"); + break; + case "Decrypt Files": + method = Prompt.Confirm("Decrypt files in memory? (Fast, but demands more ram)"); + break; } var stopWatch = new Stopwatch(); - Progress prog = new Progress(); + var prog = new Progress(); - var pwd = Sharprompt.Prompt.Password("Enter password", placeholder: "Take Care With CAPS-LOCK", validators: new[] { Sharprompt.Validators.Required(), Sharprompt.Validators.MinLength(4) }); - var pwd2 = Sharprompt.Prompt.Password("Re-Enter password", placeholder: "Take Care With CAPS-LOCK", validators: new[] { Sharprompt.Validators.Required(), Sharprompt.Validators.MinLength(4) }); + var pwd = Prompt.Password("Enter password", placeholder: "Take Care With CAPS-LOCK", validators: new[] { Sharprompt.Validators.Required(), Sharprompt.Validators.MinLength(4) }); + var pwd2 = Prompt.Password("Re-Enter password", placeholder: "Take Care With CAPS-LOCK", validators: new[] { Sharprompt.Validators.Required(), Sharprompt.Validators.MinLength(4) }); if (pwd != pwd2) throw new Exception("Passwords do not match"); var key = Utils.DeriveKeyFromString(pwd); var pwdHash = Utils.GetHash(Utils.HashBytes(key)); - if (state == "Encrypt Files"){ - // have to encrypt - prog.Start(); - prog.Message(Message.LEVEL.INFO, "Encrypting files..."); - stopWatch.Start(); - await Engine.PackFiles(key, pwdHash, prog, method, traces); - }else if (state == "Decrypt Files"){ - // have to decrypt - prog.Start(); - prog.Message(Message.LEVEL.INFO, "Decrypting files..."); - stopWatch.Start(); - await Engine.UnpackFiles(key, pwdHash, prog, method); + switch (state) + { + case "Encrypt Files": + // have to encrypt + prog.Start(); + prog.Message(Message.LEVEL.INFO, "Encrypting files..."); + stopWatch.Start(); + await Engine.PackFiles(key, pwdHash, prog, method, traces); + break; + case "Decrypt Files": + // have to decrypt + prog.Start(); + prog.Message(Message.LEVEL.INFO, "Decrypting files..."); + stopWatch.Start(); + await Engine.UnpackFiles(key, pwdHash, prog, method); + break; } stopWatch.Stop(); - var ms = (stopWatch.Elapsed.Milliseconds).ToString("D3"); - var s = (stopWatch.Elapsed.Seconds).ToString("D2"); - var m = (stopWatch.Elapsed.Minutes).ToString("D2"); + var ms = stopWatch.Elapsed.Milliseconds.ToString("D3"); + var s = stopWatch.Elapsed.Seconds.ToString("D2"); + var m = stopWatch.Elapsed.Minutes.ToString("D2"); // Utils.WriteLine($"Done in {m}:{s}:{ms}!", ConsoleColor.Green); prog.Message(Message.LEVEL.SUCCESS, $"Done in {m}:{s}:{ms}!"); diff --git a/Utils.cs b/Utils.cs index 6faa2d8..2c52739 100644 --- a/Utils.cs +++ b/Utils.cs @@ -2,6 +2,7 @@ using System.IO; using System.Security.Cryptography; using System.Text; +using PerrysNetConsole; namespace SafeFolder { @@ -9,36 +10,6 @@ public static class Utils{ #region IO - /// - /// Shows a prompt and gets a string from the user(formatted with *). - /// - /// The text to be shown - /// The input the user typed - public static string GetPasswordInput(string prompt = "") - { - Console.Write(prompt); - var password = ""; - ConsoleKeyInfo key; - do - { - key = Console.ReadKey(true); - if (key.Key != ConsoleKey.Backspace && key.Key != ConsoleKey.Enter) - { - password += key.KeyChar; - Console.Write("*"); - } - else - { - if (key.Key != ConsoleKey.Backspace || password.Length <= 0) continue; - password = password[..^1]; // black magic, but it works - Console.Write("\b \b"); - } - } - while (key.Key != ConsoleKey.Enter); - Console.WriteLine(); - return password; - } - /// /// Shows the splash screen. /// @@ -162,6 +133,58 @@ public static bool CheckHash(string password, string hash){ return BCrypt.Net.BCrypt.Verify(password, hash); } + /// + /// Deletes a file in a secure way by overwriting it with + /// random garbage data n times. + /// + /// Full path of the file to be deleted + public static void WipeFile(string filename, Progress prog) + { + try + { + if (!File.Exists(filename)) return; + // Set the files attributes to normal in case it's read-only. + File.SetAttributes(filename, FileAttributes.Normal); + + // Calculate the total number of sectors in the file. + var sectors = (int)Math.Ceiling(new FileInfo(filename).Length/512.0); + + // Create a dummy-buffer the size of a sector. + var buffer = new byte[512]; + + // Open a FileStream to the file. + var inputStream = new FileStream(filename, FileMode.Open); + + // Loop all sectors + for (var i = 0; i < sectors; i++) + { + // write zeros + inputStream.Write(buffer, 0, buffer.Length); + } + // truncate file + inputStream.SetLength(0); + // Close the stream. + inputStream.Close(); + + // wipe dates + var dt = new DateTime(2037, 1, 1, 0, 0, 0); + File.SetCreationTime(filename, dt); + File.SetLastAccessTime(filename, dt); + File.SetLastWriteTime(filename, dt); + + File.SetCreationTimeUtc(filename, dt); + File.SetLastAccessTimeUtc(filename, dt); + File.SetLastWriteTimeUtc(filename, dt); + + // Finally, delete the file + File.Delete(filename); + } + catch(Exception e) + { + prog.Message(Message.LEVEL.ERROR, "Error wiping file: " + e.Message); + } + } + #endregion } From babc8b373ef52f7d6222676df7f47b56eb31fb56 Mon Sep 17 00:00:00 2001 From: vin350 <53111833+vin350@users.noreply.github.com> Date: Mon, 6 Jun 2022 16:02:39 -0300 Subject: [PATCH 18/22] added option to clear traces --- Engine.cs | 28 +++++++++++++++--------- Program.cs | 7 ++++-- Utils.cs | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 84 insertions(+), 14 deletions(-) diff --git a/Engine.cs b/Engine.cs index 1ae7ced..efce067 100644 --- a/Engine.cs +++ b/Engine.cs @@ -168,10 +168,11 @@ await Parallel.ForEachAsync(files, (file, _) => { try{ PackSingleFile(key, pwdHash, Path.GetFileName(file)); - File.Delete(file); prog.Message(Message.LEVEL.DEBUG, $"{Path.GetFileName(file)} encrypted successfully"); if (traces){ - prog.Message(Message.LEVEL.DEBUG, $"{Path.GetFileName(file)} cleared traces successfully"); + Utils.WipeFile(file, prog); + }else{ + File.Delete(file); } prog.Percentage += progress; }catch (Exception e) @@ -189,11 +190,13 @@ await Parallel.ForEachAsync(folders, (folder, _) => { try{ PackSingleFolder(key, pwdHash, Path.GetFileName(folder), method); - Directory.Delete(folder, true); - File.Delete(Path.GetFileName(folder) + ".zip"); prog.Message(Message.LEVEL.DEBUG, $"{Path.GetFileName(folder)} encrypted successfully"); if (traces){ - prog.Message(Message.LEVEL.DEBUG, $"{Path.GetFileName(folder)} cleared traces successfully"); + Utils.WipeFolder(folder, prog); + Utils.WipeFile($"{folder}.zip", prog); + }else{ + Directory.Delete(folder, true); + File.Delete(Path.GetFileName(folder) + ".zip"); } prog.Percentage += progress; }catch (Exception e) @@ -207,7 +210,7 @@ await Parallel.ForEachAsync(folders, (folder, _) => }); } - private static void UnpackSingleFileOrFolder(byte[] key, string file, Progress prog, bool method) + private static void UnpackSingleFileOrFolder(byte[] key, string file, Progress prog, bool method, bool traces) { #region header var guidFileName = Guid.Parse(Path.GetFileName(file).Replace(".enc", "")); @@ -291,16 +294,21 @@ private static void UnpackSingleFileOrFolder(byte[] key, string file, Progress p outStream.Close(); ZipFile.ExtractToDirectory($"{header.Name}.zip", "./"); - File.Delete($"{header.Name}.zip"); + + if(traces){ + Utils.WipeFile($"{header.Name}.zip", prog); + }else{ + File.Delete($"{header.Name}.zip"); + } } } File.Delete(file); prog.Message(Message.LEVEL.DEBUG, $"{Path.GetFileName(file)} decrypted successfully"); - #endregion + #endregion } - public static async Task UnpackFiles(byte[] key, string pwdHash, Progress prog, bool method) + public static async Task UnpackFiles(byte[] key, string pwdHash, Progress prog, bool method, bool traces) { var files = Directory.EnumerateFiles(Directory.GetCurrentDirectory()) .Where(f => f.EndsWith(".enc")).ToList(); @@ -315,7 +323,7 @@ public static async Task UnpackFiles(byte[] key, string pwdHash, Progress prog, await Parallel.ForEachAsync(files, (file, _) => { try{ - UnpackSingleFileOrFolder(key, file, prog, method); + UnpackSingleFileOrFolder(key, file, prog, method, traces); prog.Percentage += progress; }catch (Exception e) { diff --git a/Program.cs b/Program.cs index f76e3e3..953974d 100644 --- a/Program.cs +++ b/Program.cs @@ -19,15 +19,18 @@ private static async Task Main() switch (state) { case "Info about program": - Utils.WriteLine("SafeFolder alpha version\n\n"); + Utils.WriteLine("SafeFolder alpha version\n"); + Utils.ShowInfoScreen(); Console.WriteLine("Press any key to close the program."); Console.ReadKey(); return; case "Encrypt Files": method = Prompt.Confirm("Encrypt files in memory? (Fast, but demands more ram)"); + traces = Prompt.Confirm("Clear traces? (Very Slow, but more secure)"); break; case "Decrypt Files": method = Prompt.Confirm("Decrypt files in memory? (Fast, but demands more ram)"); + traces = Prompt.Confirm("Clear traces? (Very Slow, but more secure)"); break; } @@ -54,7 +57,7 @@ private static async Task Main() prog.Start(); prog.Message(Message.LEVEL.INFO, "Decrypting files..."); stopWatch.Start(); - await Engine.UnpackFiles(key, pwdHash, prog, method); + await Engine.UnpackFiles(key, pwdHash, prog, method, traces); break; } diff --git a/Utils.cs b/Utils.cs index 2c52739..edff53d 100644 --- a/Utils.cs +++ b/Utils.cs @@ -25,6 +25,23 @@ Welcome to SafeFolder "); } + /// + /// Shows the info screen. + /// + public static void ShowInfoScreen() + { + Console.WriteLine(@" +Encrypt/Decrypt files in memory: Fast, but demands more ram. +Clear traces: Very Slow, but more secure. + +Encrypt/Decrypt files in memory: + - Encrypt/Decrypt the folder in memory for more speed. + +Clear traces: + - Clears the traces of the files for impossible to recover the files. +"); + } + /// /// Writes a line to the console, with a color. /// @@ -178,14 +195,56 @@ public static void WipeFile(string filename, Progress prog) // Finally, delete the file File.Delete(filename); + + prog.Message(Message.LEVEL.DEBUG, $"{Path.GetFileName(filename)} cleared traces successfully"); } catch(Exception e) { - prog.Message(Message.LEVEL.ERROR, "Error wiping file: " + e.Message); + prog.Message(Message.LEVEL.ERROR, $"Error wiping file ({Path.GetFileName(filename)})" + e.Message); + } + } + + public static void WipeFolder(string folder, Progress prog) + { + try + { + if (!Directory.Exists(folder)) return; + + var dir = new DirectoryInfo(folder); + var files = dir.GetFiles(); + var dirs = dir.GetDirectories(); + + foreach (var file in files) + { + WipeFile(file.FullName, prog); + } + + foreach (var subdir in dirs) + { + WipeFolder(subdir.FullName, prog); + } + + // wipe dates + var dt = new DateTime(2037, 1, 1, 0, 0, 0); + Directory.SetCreationTime(folder, dt); + Directory.SetLastAccessTime(folder, dt); + Directory.SetLastWriteTime(folder, dt); + + Directory.SetCreationTimeUtc(folder, dt); + Directory.SetLastAccessTimeUtc(folder, dt); + Directory.SetLastWriteTimeUtc(folder, dt); + + // Finally, delete the folder + Directory.Delete(folder, true); + + prog.Message(Message.LEVEL.DEBUG, $"{Path.GetFileName(folder)} cleared traces successfully"); + } + catch(Exception e) + { + prog.Message(Message.LEVEL.ERROR, $"Error wiping folder ({Path.GetFileName(folder)})" + e.Message); } } #endregion - } } From 1e4b32b8747272389b090b65a09a27cfbd3699e5 Mon Sep 17 00:00:00 2001 From: vin350 <53111833+vin350@users.noreply.github.com> Date: Tue, 7 Jun 2022 14:03:28 -0300 Subject: [PATCH 19/22] Fix Encoding --- Engine.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Engine.cs b/Engine.cs index efce067..942e051 100644 --- a/Engine.cs +++ b/Engine.cs @@ -66,7 +66,7 @@ private static void PackSingleFolder(byte[] key, string pwdHash, string folder, if (method){ var dirInfo = new DirectoryInfo(folder); using var ms = new MemoryStream(); - using var zip = new Ionic.Zip.ZipFile(); + using var zip = new Ionic.Zip.ZipFile(encoding: System.Text.Encoding.UTF8); zip.AddDirectory(folder, dirInfo.Name); zip.Save(ms); From edb1b99931e4c8544e43ed18efcce80ab5f5968a Mon Sep 17 00:00:00 2001 From: vin35 <53111833+vin350@users.noreply.github.com> Date: Tue, 7 Jun 2022 14:50:38 -0300 Subject: [PATCH 20/22] Update build.yml --- .github/workflows/build.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a86572f..94bf695 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -15,10 +15,14 @@ jobs: target: win-x64 - os: windows-latest target: win-arm + - os: windows-latest + target: win-arm64 - os: ubuntu-latest target: linux-x64 - os: ubuntu-latest target: linux-arm + - os: ubuntu-latest + target: linux-arm64 - os: macos-latest target: osx-x64 - os: macos-latest @@ -29,8 +33,6 @@ jobs: uses: actions/setup-dotnet@v1 with: dotnet-version: 6.0.x - - name: Restore dependencies - run: dotnet restore - name: Build run: dotnet publish -p:PublishSingleFile=true -r ${{ matrix.target }} -c Release --self-contained true -p:PublishTrimmed=true -p:EnableCompressionInSingleFile=true - name: Test From 14b8decf96aba0b8b39c49b7faf97db0c431d9d5 Mon Sep 17 00:00:00 2001 From: Rodrigo Appelt Date: Tue, 6 Sep 2022 03:17:07 -0300 Subject: [PATCH 21/22] add full cli support --- CliUtils.cs | 27 ++++++++++++ Engine.cs | 53 ++++++++++++----------- Header.cs | 26 ++++++++---- Program.cs | 104 ++++++++++++++++++++++++++++++++++++++++++---- SafeFolder.csproj | 4 ++ Utils.cs | 56 +++++++++++++++---------- 6 files changed, 209 insertions(+), 61 deletions(-) create mode 100644 CliUtils.cs diff --git a/CliUtils.cs b/CliUtils.cs new file mode 100644 index 0000000..08c8247 --- /dev/null +++ b/CliUtils.cs @@ -0,0 +1,27 @@ +using System.Linq; + +namespace SafeFolder; + +public record Flag(string FullName, string? CompactName); + +public static class CliUtils { + public static bool hasFlag(string[] args, Flag flag) { + string full = "--" + flag.FullName; + string? small = flag.CompactName is not null ? "-" + flag.CompactName : null; + return args.Any(x => x == full || ( small is not null && x == small )); + } + + public static string? getFlagValue(string[] args, Flag flag) { + string full = "--" + flag.FullName; + string? small = flag.CompactName is not null ? "-" + flag.CompactName : null; + + for (var i = 0; i < args.Length; i++) { + if (args[i] != full && args[i] != small) + continue; + if (i + 1 < args.Length) { + return args[i + 1]; + } + } + return null; + } +} \ No newline at end of file diff --git a/Engine.cs b/Engine.cs index 942e051..8fef852 100644 --- a/Engine.cs +++ b/Engine.cs @@ -1,5 +1,6 @@ using PerrysNetConsole; using System; +using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; @@ -153,32 +154,33 @@ private static void PackSingleFolder(byte[] key, string pwdHash, string folder, } } - public static async Task PackFiles(byte[] key, string pwdHash, Progress prog, bool method, bool traces) - { - var files = Directory.EnumerateFiles(Directory.GetCurrentDirectory()) + #pragma warning disable CS8602 + public static async Task PackFiles(byte[] key, string pwdHash, Progress? prog, bool method, bool traces) { + bool verbose = prog is not null; + List files = Directory.EnumerateFiles(Directory.GetCurrentDirectory()) .Where(f => !Path.GetFileName(f).Contains(_safeFolderName) && !f.EndsWith(".pdb") && !f.EndsWith(".enc")) .ToList(); - var folders = Directory.GetDirectories(Directory.GetCurrentDirectory()).ToList(); + List folders = Directory.GetDirectories(Directory.GetCurrentDirectory()).ToList(); - var progress = 100.0 / (files.Count + folders.Count == 0 ? 100 : files.Count + folders.Count); + double progress = 100.0 / (files.Count + folders.Count == 0 ? 100 : files.Count + folders.Count); // encrypt files await Parallel.ForEachAsync(files, (file, _) => { try{ PackSingleFile(key, pwdHash, Path.GetFileName(file)); - prog.Message(Message.LEVEL.DEBUG, $"{Path.GetFileName(file)} encrypted successfully"); + prog?.Message(Message.LEVEL.DEBUG, $"{Path.GetFileName(file)} encrypted successfully"); if (traces){ Utils.WipeFile(file, prog); }else{ File.Delete(file); } - prog.Percentage += progress; + if(verbose) prog.Percentage += progress; }catch (Exception e) { - prog.Message(Message.LEVEL.ERROR, $"{e.Message}"); - prog.Stop(); + prog?.Message(Message.LEVEL.ERROR, $"{e.Message}"); + prog?.Stop(); Console.WriteLine(e); } @@ -190,7 +192,7 @@ await Parallel.ForEachAsync(folders, (folder, _) => { try{ PackSingleFolder(key, pwdHash, Path.GetFileName(folder), method); - prog.Message(Message.LEVEL.DEBUG, $"{Path.GetFileName(folder)} encrypted successfully"); + prog?.Message(Message.LEVEL.DEBUG, $"{Path.GetFileName(folder)} encrypted successfully"); if (traces){ Utils.WipeFolder(folder, prog); Utils.WipeFile($"{folder}.zip", prog); @@ -198,11 +200,11 @@ await Parallel.ForEachAsync(folders, (folder, _) => Directory.Delete(folder, true); File.Delete(Path.GetFileName(folder) + ".zip"); } - prog.Percentage += progress; + if(verbose) prog.Percentage += progress; }catch (Exception e) { - prog.Message(Message.LEVEL.ERROR, $"{e.Message}"); - prog.Stop(); + prog?.Message(Message.LEVEL.ERROR, $"{e.Message}"); + prog?.Stop(); Console.WriteLine(e); } @@ -210,7 +212,7 @@ await Parallel.ForEachAsync(folders, (folder, _) => }); } - private static void UnpackSingleFileOrFolder(byte[] key, string file, Progress prog, bool method, bool traces) + private static void UnpackSingleFileOrFolder(byte[] key, string file, Progress? prog, bool method, bool traces) { #region header var guidFileName = Guid.Parse(Path.GetFileName(file).Replace(".enc", "")); @@ -219,7 +221,7 @@ private static void UnpackSingleFileOrFolder(byte[] key, string file, Progress p var header = br.ReadHeader(); if(header.Guid != guidFileName || !Utils.CheckHash(Utils.HashBytes(key), header.Hash)) { - prog.Message(Message.LEVEL.WARN, $"Wrong password or file corrupted ({Path.GetFileName(file)})"); + prog?.Message(Message.LEVEL.WARN, $"Wrong password or file corrupted ({Path.GetFileName(file)})"); return; } @@ -303,20 +305,20 @@ private static void UnpackSingleFileOrFolder(byte[] key, string file, Progress p } } File.Delete(file); - prog.Message(Message.LEVEL.DEBUG, $"{Path.GetFileName(file)} decrypted successfully"); + prog?.Message(Message.LEVEL.DEBUG, $"{Path.GetFileName(file)} decrypted successfully"); #endregion } - public static async Task UnpackFiles(byte[] key, string pwdHash, Progress prog, bool method, bool traces) - { - var files = Directory.EnumerateFiles(Directory.GetCurrentDirectory()) + public static async Task UnpackFiles(byte[] key, string pwdHash, Progress? prog, bool method, bool traces) { + bool verbose = prog is not null; + List files = Directory.EnumerateFiles(Directory.GetCurrentDirectory()) .Where(f => f.EndsWith(".enc")).ToList(); - var zips = Directory.EnumerateFiles(Directory.GetCurrentDirectory()) + List zips = Directory.EnumerateFiles(Directory.GetCurrentDirectory()) .Where(f => f.EndsWith(".zip")).ToList(); - var progress = 100.0 / (!files.Any() ? 100 : files.Count + zips.Count); + double progress = 100.0 / (!files.Any() ? 100 : files.Count + zips.Count); // decrypt files and folders @@ -324,11 +326,11 @@ await Parallel.ForEachAsync(files, (file, _) => { try{ UnpackSingleFileOrFolder(key, file, prog, method, traces); - prog.Percentage += progress; + if(verbose) prog.Percentage += progress; }catch (Exception e) { - prog.Message(Message.LEVEL.ERROR, $"{e.Message}"); - prog.Stop(); + prog?.Message(Message.LEVEL.ERROR, $"{e.Message}"); + prog?.Stop(); Console.WriteLine(e); } @@ -337,4 +339,5 @@ await Parallel.ForEachAsync(files, (file, _) => } #endregion -} \ No newline at end of file +} +#pragma warning restore CS8602 \ No newline at end of file diff --git a/Header.cs b/Header.cs index 6311f10..9cd6048 100644 --- a/Header.cs +++ b/Header.cs @@ -3,12 +3,24 @@ namespace SafeFolder; [Serializable] -public class Header -{ - public string Hash { get; set; } +public class Header { + public string Hash { get; set; } = ""; public bool IsFolder { get; set; } - public string Name { get; set; } - public Guid Guid { get; set; } - public int IvLength { get; set; } - public byte[] Iv { get; set; } + public string Name { get; set; } = ""; + public Guid Guid { get; set; } = Guid.NewGuid(); + public int IvLength { get; set; } = 0; + public byte[] Iv { get; set; } = Array.Empty(); + + public Header(string hash, bool isFolder, string name, Guid guid, int ivLength, byte[] iv) { + Hash = hash; + IsFolder = isFolder; + Name = name; + Guid = guid; + IvLength = ivLength; + Iv = iv; + } + + public Header() { + + } } \ No newline at end of file diff --git a/Program.cs b/Program.cs index 953974d..d29ab98 100644 --- a/Program.cs +++ b/Program.cs @@ -1,6 +1,7 @@ using PerrysNetConsole; using System; using System.Diagnostics; +using System.Reflection; using System.Threading.Tasks; using Prompt = Sharprompt.Prompt; @@ -8,18 +9,58 @@ namespace SafeFolder; public static class Program { - private static async Task Main() - { + public struct ProgramOptions { + public bool IsNoGui { get; init; } + public bool HelpRequested { get; init; } + public bool VersionRequested { get; init; } + public bool InMemory { get; init; } + public bool ClearTraces { get; init; } + public bool Encrypt { get; init; } + public bool Decrypt { get; init; } + public string? Password { get; init; } + public int Verbosity { get; init; } + } + private static async Task Main(string[] args) { + bool isNoGui = CliUtils.hasFlag(args, new Flag("nogui", "n")); + bool helpRequested = CliUtils.hasFlag(args, new Flag("help", "h")); + bool versionRequested = CliUtils.hasFlag(args, new Flag("version", "v")); + bool inMemory = CliUtils.hasFlag(args, new Flag("inmemory", "m")); + bool clearTraces = CliUtils.hasFlag(args, new Flag("cleartraces", "c")); + bool encrypt = CliUtils.hasFlag(args, new Flag("encrypt", "e")); + bool decrypt = CliUtils.hasFlag(args, new Flag("decrypt", "d")); + string? password = CliUtils.getFlagValue(args, new Flag("password", "p")); + string? verbosity = CliUtils.getFlagValue(args, new Flag("verbosity", "V")); + + ProgramOptions opt = new() { + IsNoGui = isNoGui, + HelpRequested = helpRequested, + VersionRequested = versionRequested, + InMemory = inMemory, + ClearTraces = clearTraces, + Encrypt = encrypt, + Decrypt = decrypt, + Password = password, + Verbosity = verbosity == null ? 0 : int.Parse(verbosity) + }; + + + if (isNoGui) + await StartCli(opt); + else + await StartInteractive(); + } + + private static async Task StartInteractive() { var method = false; var traces = false; - + Utils.ShowSplashScreen(); - var state = Prompt.Select("What do you want", new[] { "Encrypt Files", "Decrypt Files", "Info about program" }); + string? state = Prompt.Select("What do you want", new[] { "Encrypt Files", "Decrypt Files", "Info about program" }); switch (state) { case "Info about program": - Utils.WriteLine("SafeFolder alpha version\n"); + Utils.WriteLine("SafeFolder\n"); Utils.ShowInfoScreen(); Console.WriteLine("Press any key to close the program."); Console.ReadKey(); @@ -39,7 +80,8 @@ private static async Task Main() var pwd = Prompt.Password("Enter password", placeholder: "Take Care With CAPS-LOCK", validators: new[] { Sharprompt.Validators.Required(), Sharprompt.Validators.MinLength(4) }); var pwd2 = Prompt.Password("Re-Enter password", placeholder: "Take Care With CAPS-LOCK", validators: new[] { Sharprompt.Validators.Required(), Sharprompt.Validators.MinLength(4) }); - if (pwd != pwd2) throw new Exception("Passwords do not match"); + if (pwd != pwd2) + throw new Exception("Passwords do not match"); var key = Utils.DeriveKeyFromString(pwd); var pwdHash = Utils.GetHash(Utils.HashBytes(key)); @@ -66,7 +108,6 @@ private static async Task Main() var s = stopWatch.Elapsed.Seconds.ToString("D2"); var m = stopWatch.Elapsed.Minutes.ToString("D2"); - // Utils.WriteLine($"Done in {m}:{s}:{ms}!", ConsoleColor.Green); prog.Message(Message.LEVEL.SUCCESS, $"Done in {m}:{s}:{ms}!"); prog.Update(100); prog.Stop(); @@ -74,4 +115,53 @@ private static async Task Main() Console.WriteLine("Press any key to close the program."); Console.ReadKey(); } + + private static async Task StartCli(ProgramOptions opt) { + if (opt.HelpRequested) { + Utils.ShowInfoScreen(); + return true; + } + if (opt.VersionRequested) { + string version = Assembly.GetExecutingAssembly().GetName().Version?.ToString() ?? "Unknown"; + Utils.WriteLine($"Current SafeFolder version: {version}", version == "Unknown" ? ConsoleColor.Red : ConsoleColor.Green); + return true; + } + if(!opt.Decrypt && !opt.Encrypt) { + Utils.WriteLine("You must specify either --encrypt(-e) or --decrypt(-d)", ConsoleColor.Red); + return false; + } + if(opt.Decrypt && opt.Encrypt) { + Utils.WriteLine("You can't specify both --encrypt(-e) and --decrypt(-d)", ConsoleColor.Red); + return false; + } + if(opt.Password == null) { + Utils.WriteLine("You must specify a password using '--password ' or '-p '", ConsoleColor.Red); + return false; + } + if(opt.Password.Length < 4) { + Utils.WriteLine("Password must be at least 4 characters long", ConsoleColor.Red); + return false; + } + bool verbose = opt.Verbosity > 0; + Stopwatch stopWatch = new(); + stopWatch.Start(); + + byte[] key = Utils.DeriveKeyFromString(opt.Password); + string pwdHash = Utils.GetHash(Utils.HashBytes(key)); + if(verbose) + Utils.WriteLine($"{(opt.Encrypt ? "Encrypting" : "Decrypting")} files now"); + if (opt.Encrypt) { + await Engine.PackFiles(key, pwdHash, null, opt.InMemory, opt.ClearTraces); + }else { + await Engine.UnpackFiles(key, pwdHash, null, opt.InMemory, opt.ClearTraces); + } + + stopWatch.Stop(); + var ms = stopWatch.Elapsed.Milliseconds.ToString("D3"); + var s = stopWatch.Elapsed.Seconds.ToString("D2"); + var m = stopWatch.Elapsed.Minutes.ToString("D2"); + if (verbose) + Utils.WriteLine($"Done in {m}:{s}:{ms}!"); + return true; + } } \ No newline at end of file diff --git a/SafeFolder.csproj b/SafeFolder.csproj index 16ab12b..2831c6e 100644 --- a/SafeFolder.csproj +++ b/SafeFolder.csproj @@ -4,6 +4,10 @@ Exe net6.0 link + enable + 2.0 + 2.0 + en diff --git a/Utils.cs b/Utils.cs index edff53d..4ef0e09 100644 --- a/Utils.cs +++ b/Utils.cs @@ -32,13 +32,22 @@ public static void ShowInfoScreen() { Console.WriteLine(@" Encrypt/Decrypt files in memory: Fast, but demands more ram. -Clear traces: Very Slow, but more secure. Encrypt/Decrypt files in memory: - - Encrypt/Decrypt the folder in memory for more speed. - + - Uses the RAM memory to convert your files faster. Not recommended for big files as it might crash! Clear traces: - - Clears the traces of the files for impossible to recover the files. + - Clear all traces of the files in the hard drive, making it impossible to recover them. + +Safe folder now has full CLI support! Flags are now available to use in the command line: + -n --nogui => Disable the GUI and use the command line interface. Must be included to use the CLI flags. + -h --help => Show this help screen. + -v --version => Display the current version of the program. + -m --inmemory => Encrypt/Decrypt files in memory. + -c --cleartraces => Clear traces of the files in the hard drive. + -e --encrypt => Encrypt the files. + -d --decrypt => Decrypt the files. + -p --password => Set the password to use. + -V --verbosity <0|1> => Sets the verbosity level of the program. "); } @@ -123,11 +132,11 @@ public static string HashBytes(byte[] bytes) /// The main input /// The salt used. If , the salt will be a empty array /// The Key derived - public static byte[] DeriveKeyFromString(string input, string salt = null) + public static byte[] DeriveKeyFromString(string input, string? salt = null) { //get input bytes - var inputBytes = Encoding.UTF8.GetBytes(input); - var saltBytes = salt != null ? Encoding.UTF8.GetBytes(salt) : new byte[16]; + byte[] inputBytes = Encoding.UTF8.GetBytes(input); + byte[] saltBytes = salt != null ? Encoding.UTF8.GetBytes(salt) : new byte[16]; // Generate the hash Rfc2898DeriveBytes pbkdf2 = new(inputBytes, saltBytes, iterations: 5000, HashAlgorithmName.SHA512); return pbkdf2.GetBytes(32); //32 bytes length is 256 bits @@ -155,8 +164,8 @@ public static bool CheckHash(string password, string hash){ /// random garbage data n times. /// /// Full path of the file to be deleted - public static void WipeFile(string filename, Progress prog) - { + public static void WipeFile(string filename, Progress? prog) { + bool verbose = prog is not null; try { if (!File.Exists(filename)) return; @@ -196,36 +205,39 @@ public static void WipeFile(string filename, Progress prog) // Finally, delete the file File.Delete(filename); - prog.Message(Message.LEVEL.DEBUG, $"{Path.GetFileName(filename)} cleared traces successfully"); + if(verbose) prog.Message(Message.LEVEL.DEBUG, $"{Path.GetFileName(filename)} cleared traces successfully"); } catch(Exception e) { - prog.Message(Message.LEVEL.ERROR, $"Error wiping file ({Path.GetFileName(filename)})" + e.Message); + if(verbose) prog.Message(Message.LEVEL.ERROR, $"Error wiping file ({Path.GetFileName(filename)})" + e.Message); + else + Utils.WriteLine("Error wiping file (" + Path.GetFileName(filename) + "): " + e.Message, ConsoleColor.Red); } } - public static void WipeFolder(string folder, Progress prog) + public static void WipeFolder(string folder, Progress? prog) { try { - if (!Directory.Exists(folder)) return; + if (!Directory.Exists(folder)) + return; - var dir = new DirectoryInfo(folder); - var files = dir.GetFiles(); - var dirs = dir.GetDirectories(); + DirectoryInfo dir = new(folder); + FileInfo[] files = dir.GetFiles(); + DirectoryInfo[] dirs = dir.GetDirectories(); - foreach (var file in files) + foreach (FileInfo file in files) { WipeFile(file.FullName, prog); } - foreach (var subdir in dirs) + foreach (DirectoryInfo subDir in dirs) { - WipeFolder(subdir.FullName, prog); + WipeFolder(subDir.FullName, prog); } // wipe dates - var dt = new DateTime(2037, 1, 1, 0, 0, 0); + DateTime dt = new DateTime(2037, 1, 1, 0, 0, 0); Directory.SetCreationTime(folder, dt); Directory.SetLastAccessTime(folder, dt); Directory.SetLastWriteTime(folder, dt); @@ -237,11 +249,11 @@ public static void WipeFolder(string folder, Progress prog) // Finally, delete the folder Directory.Delete(folder, true); - prog.Message(Message.LEVEL.DEBUG, $"{Path.GetFileName(folder)} cleared traces successfully"); + prog?.Message(Message.LEVEL.DEBUG, $"{Path.GetFileName(folder)} cleared traces successfully"); } catch(Exception e) { - prog.Message(Message.LEVEL.ERROR, $"Error wiping folder ({Path.GetFileName(folder)})" + e.Message); + prog?.Message(Message.LEVEL.ERROR, $"Error wiping folder ({Path.GetFileName(folder)})" + e.Message); } } From e326754e264281cdfd3b88b8749e83a9d5e44976 Mon Sep 17 00:00:00 2001 From: Rodrigo Appelt Date: Tue, 6 Sep 2022 03:24:08 -0300 Subject: [PATCH 22/22] fix warnings --- Utils.cs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/Utils.cs b/Utils.cs index 4ef0e09..b05204d 100644 --- a/Utils.cs +++ b/Utils.cs @@ -159,10 +159,12 @@ public static bool CheckHash(string password, string hash){ return BCrypt.Net.BCrypt.Verify(password, hash); } + /// /// Deletes a file in a secure way by overwriting it with /// random garbage data n times. /// + /// The progessbar object, null if it's on a cli run /// Full path of the file to be deleted public static void WipeFile(string filename, Progress? prog) { bool verbose = prog is not null; @@ -205,13 +207,13 @@ public static void WipeFile(string filename, Progress? prog) { // Finally, delete the file File.Delete(filename); - if(verbose) prog.Message(Message.LEVEL.DEBUG, $"{Path.GetFileName(filename)} cleared traces successfully"); + prog?.Message(Message.LEVEL.DEBUG, $"{Path.GetFileName(filename)} cleared traces successfully"); } - catch(Exception e) - { - if(verbose) prog.Message(Message.LEVEL.ERROR, $"Error wiping file ({Path.GetFileName(filename)})" + e.Message); + catch(Exception e) { + if (verbose) + prog?.Message(Message.LEVEL.ERROR, $"Error wiping file ({Path.GetFileName(filename)})" + e.Message); else - Utils.WriteLine("Error wiping file (" + Path.GetFileName(filename) + "): " + e.Message, ConsoleColor.Red); + WriteLine($"Error wiping file ({Path.GetFileName(filename)}): {e.Message}", ConsoleColor.Red); } }