'Encrypted key no longer readable after reboot

I am running into issues with some of my encrypted keys whenever I reboot my machines. I have several test VMs set up with encrypted passwords that are used for API Tests, UI Tests, etc.

Whenever the machines are rebooted I have to regenerate these encrypted keys. At first it wasn't too much of a hassle, but now we utilize around 14 VMs and its starting to turn into a time dump..

What I want is for this key to still work after rebooting. I see that the file is still there with some contents, but when I go to read it after a reboot it throws a System.ArgumentException: Source array was not long enough error on the line where it copies the byte array.

Below is the code for my console app that generates a file with the encrypted key. It allows you to enter the key and specify the target file name

Main.cs

        static void Main(string[] args)
        {
            Run();
        }

        public static void Run()
        {
            // Create the original data to be encrypted (The data length should be a multiple of 16).
            Console.WriteLine("Enter the string to encrypt: ");
            string enData = Console.ReadLine();

            string fileName = "";

            Console.WriteLine("Enter the target file name: ");
            fileName = Console.ReadLine();
            
            byte[] encodedBytes = UnicodeEncoding.ASCII.GetBytes(enData);

            Console.WriteLine("Original data: " + UnicodeEncoding.ASCII.GetString(encodedBytes));
            Console.WriteLine("Encrypting...");

            // Encrypt the data in memory.
            int size = encodedBytes.Length + 4;
            int unit = size / 16;
            if (size % 16 != 0)
            {
                unit += 1;
            }

            byte[] toEncrypt = new byte[unit * 16];

            Array.Copy(BitConverter.GetBytes(encodedBytes.Length), 0, toEncrypt, 0, 4);
            Array.Copy(encodedBytes, 0, toEncrypt, 4, encodedBytes.Length);
            EncryptInMemoryData(toEncrypt, MemoryProtectionScope.SameLogon);

            Console.WriteLine("Encrypted data: " + UnicodeEncoding.ASCII.GetString(toEncrypt));
            System.IO.File.WriteAllBytes(@"C:\temp\" + fileName + ".dat", toEncrypt);
            Console.WriteLine("Decrypting...");

            // Decrypt the data in memory.
            DecryptInMemoryData(toEncrypt, MemoryProtectionScope.SameLogon);

            int outputSize = BitConverter.ToInt32(toEncrypt, 0);
            var outputEncodedBytes = new byte[outputSize];
            Array.Copy(toEncrypt, 4, outputEncodedBytes, 0, outputSize);

            Console.WriteLine("Decrypted data: " + UnicodeEncoding.ASCII.GetString(outputEncodedBytes));
        }

        public static void EncryptInMemoryData(byte[] Buffer, MemoryProtectionScope Scope)
        {
            if (Buffer == null)
                throw new ArgumentNullException("Buffer");
            if (Buffer.Length <= 0)
                throw new ArgumentException("Buffer");

            // Encrypt the data in memory. The result is stored in the same array as the original data.
            ProtectedMemory.Protect(Buffer, Scope);
        }

        public static void DecryptInMemoryData(byte[] Buffer, MemoryProtectionScope Scope)
        {
            if (Buffer == null)
                throw new ArgumentNullException("Buffer");
            if (Buffer.Length <= 0)
                throw new ArgumentException("Buffer");

            // Decrypt the data in memory. The result is stored in the same array as the original data.
            ProtectedMemory.Unprotect(Buffer, Scope);
        }

And then below is the code that reads this file

        public string GetKey()
        {
            byte[] byteArray = System.IO.File.ReadAllBytes(@"...");

            // Decrypt the data in memory. The result is stored in the same array as the original data.
            ProtectedMemory.Unprotect(byteArray, MemoryProtectionScope.SameLogon);

            int outputSize = BitConverter.ToInt32(byteArray, 0);
            var outputEncodedBytes = new byte[outputSize];
            Array.Copy(byteArray, 4, outputEncodedBytes, 0, outputSize);

            return UnicodeEncoding.ASCII.GetString(outputEncodedBytes);
        }

Again this works great up until I have to restart the machine, then the ecrypted file no longer seems to work.



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source