예제 #1
0
 public static bool AuthenticateFile(string filePath, byte[] macKey, out byte[] storedHash)
 {
     try
     {
         bool tampered = true;
         storedHash = ReadStoredHash(filePath);
         if (storedHash != null)
         {
             byte[] computedHash = new byte[Constants.HashLength];
             using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.Read, Constants.FileBufferSize, FileOptions.SequentialScan))
             {
                 // Remove the stored MAC from the file before computing the MAC
                 fileStream.SetLength(fileStream.Length - computedHash.Length);
                 MemoryEncryption.DecryptByteArray(ref macKey);
                 computedHash = HashingAlgorithms.Blake2(fileStream, macKey);
                 MemoryEncryption.EncryptByteArray(ref macKey);
             }
             // Invert result
             tampered = !Sodium.Utilities.Compare(storedHash, computedHash);
             if (tampered == true)
             {
                 // Restore the stored MAC
                 AppendHash(filePath, storedHash);
             }
         }
         return(tampered);
     }
     catch (Exception ex) when(ExceptionFilters.FileAccessExceptions(ex))
     {
         Logging.LogException(ex.ToString(), Logging.Severity.High);
         DisplayMessage.Error(filePath, ex.GetType().Name, "Unable to authenticate the file.");
         storedHash = null;
         return(true);
     }
 }
예제 #2
0
 private static void EncryptFile(string filePath, string encryptedFilePath, byte[] salt, byte[] encryptionKey, byte[] macKey)
 {
     try
     {
         using (var ciphertext = new FileStream(encryptedFilePath, FileMode.Create, FileAccess.ReadWrite, FileShare.Read, Constants.FileBufferSize, FileOptions.SequentialScan))
             using (var plaintext = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.Read, Constants.FileBufferSize, FileOptions.SequentialScan))
             {
                 WriteFileHeaders.WriteHeaders(ciphertext, salt);
                 byte[] fileBytes = FileHandling.GetBufferSize(plaintext.Length);
                 // Generate a counter starting at 0
                 byte[] counter = Generate.Counter();
                 int    bytesRead;
                 MemoryEncryption.DecryptByteArray(ref encryptionKey);
                 while ((bytesRead = plaintext.Read(fileBytes, 0, fileBytes.Length)) > 0)
                 {
                     byte[] encryptedBytes = StreamEncryption.EncryptXChaCha20(fileBytes, counter, encryptionKey);
                     ciphertext.Write(encryptedBytes, 0, bytesRead);
                     counter = Sodium.Utilities.Increment(counter);
                 }
             }
         Utilities.ZeroArray(encryptionKey);
         CompleteEncryption(filePath, encryptedFilePath, macKey);
     }
     catch (Exception ex) when(ExceptionFilters.FileEncryptionExceptions(ex))
     {
         Logging.LogException(ex.ToString(), Logging.Severity.High);
         DisplayMessage.Error(filePath, ex.GetType().Name, "Unable to encrypt the file.");
         FileHandling.DeleteFile(encryptedFilePath);
         Utilities.ZeroArray(encryptionKey);
         Utilities.ZeroArray(macKey);
     }
 }
예제 #3
0
 private static void DecryptFile(string filePath, int parametersLength, byte[] macBackup, byte[] encryptionKey)
 {
     try
     {
         string decryptedFilePath = Regex.Replace(filePath, Constants.EncryptedExtension, string.Empty);
         int    headersLength     = Constants.SaltLength + parametersLength;
         using (var plaintext = new FileStream(decryptedFilePath, FileMode.Create, FileAccess.ReadWrite, FileShare.Read, Constants.FileBufferSize, FileOptions.SequentialScan))
             using (var ciphertext = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.Read, Constants.FileBufferSize, FileOptions.SequentialScan))
             {
                 // Skip the header bytes
                 ciphertext.Seek(headersLength, SeekOrigin.Begin);
                 byte[] fileBytes = FileHandling.GetBufferSize(ciphertext.Length);
                 // Generate a counter starting at 0
                 byte[] counter = Generate.Counter();
                 int    bytesRead;
                 MemoryEncryption.DecryptByteArray(ref encryptionKey);
                 while ((bytesRead = ciphertext.Read(fileBytes, 0, fileBytes.Length)) > 0)
                 {
                     byte[] decryptedBytes = StreamEncryption.DecryptXChaCha20(fileBytes, counter, encryptionKey);
                     plaintext.Write(decryptedBytes, 0, bytesRead);
                     counter = Sodium.Utilities.Increment(counter);
                 }
                 Utilities.ZeroArray(encryptionKey);
             }
         CompleteDecryption(filePath, decryptedFilePath);
     }
     catch (Exception ex) when(ExceptionFilters.FileEncryptionExceptions(ex))
     {
         Logging.LogException(ex.ToString(), Logging.Severity.High);
         DisplayMessage.Error(filePath, ex.GetType().Name, "Unable to decrypt the file.");
         Utilities.ZeroArray(encryptionKey);
         RestoreMAC(filePath, macBackup);
     }
 }
예제 #4
0
 private static byte[] GetKeyfileBytes(byte[] passwordBytes, string keyfilePath)
 {
     if (!string.IsNullOrEmpty(keyfilePath))
     {
         byte[] keyfileBytes = Keyfiles.ReadKeyfile(keyfilePath);
         if (keyfileBytes != null)
         {
             MemoryEncryption.DecryptByteArray(ref passwordBytes);
             // Combine password and keyfile bytes
             passwordBytes = HashingAlgorithms.Blake2(passwordBytes, keyfileBytes);
             MemoryEncryption.EncryptByteArray(ref passwordBytes);
             Utilities.ZeroArray(keyfileBytes);
         }
     }
     return(passwordBytes);
 }
예제 #5
0
        public static (byte[] encryptionKey, byte[] macKey) DeriveKeys(byte[] passwordBytes, byte[] salt, int iterations, int memorySize)
        {
            var argon2id = PasswordHash.ArgonAlgorithm.Argon_2ID13;

            MemoryEncryption.DecryptByteArray(ref passwordBytes);
            // Derive a 96 byte key
            byte[] derivedKey = PasswordHash.ArgonHashBinary(passwordBytes, salt, iterations, memorySize, Constants.Argon2KeySize, argon2id);
            // 256-bit encryption key
            byte[] encryptionKey = new byte[Constants.EncryptionKeySize];
            Array.Copy(derivedKey, encryptionKey, encryptionKey.Length);
            // 512-bit MAC key
            byte[] macKey = new byte[Constants.MACKeySize];
            Array.Copy(derivedKey, encryptionKey.Length, macKey, 0, macKey.Length);
            Utilities.ZeroArray(derivedKey);
            MemoryEncryption.EncryptByteArray(ref passwordBytes);
            MemoryEncryption.EncryptByteArray(ref encryptionKey);
            MemoryEncryption.EncryptByteArray(ref macKey);
            return(encryptionKey, macKey);
        }
예제 #6
0
 private static byte[] ComputeFileHash(string encryptedFilePath, byte[] macKey)
 {
     try
     {
         byte[] computedHash = new byte[Constants.HashLength];
         using (var fileStream = new FileStream(encryptedFilePath, FileMode.Open, FileAccess.Read, FileShare.Read, Constants.FileBufferSize, FileOptions.SequentialScan))
         {
             MemoryEncryption.DecryptByteArray(ref macKey);
             computedHash = HashingAlgorithms.Blake2(fileStream, macKey);
             MemoryEncryption.EncryptByteArray(ref macKey);
         }
         return(computedHash);
     }
     catch (Exception ex) when(ExceptionFilters.FileAccessExceptions(ex))
     {
         Logging.LogException(ex.ToString(), Logging.Severity.High);
         DisplayMessage.Error(encryptedFilePath, ex.GetType().Name, "Unable to compute MAC.");
         return(null);
     }
 }
예제 #7
0
 private static byte[] HashPasswordBytes(byte[] passwordBytes)
 {
     passwordBytes = HashingAlgorithms.Blake2(passwordBytes);
     MemoryEncryption.EncryptByteArray(ref passwordBytes);
     return(passwordBytes);
 }