Tuesday, 27 June 2017

Key Management

When you use encryption be it symmetric or asymmetric you have either have a shared secret or a public and private key combo, either way these need to be stored somewhere. If they're strongly type they're near impossible to remember; think along the lines of a GUID as your password.

Luckily there's a ProtectData class, which does pretty much exactly what it sounds like it does. It only has two methods, Protect and Unprotect which also do exactly what they sound they'd do.

now one thing you have to remember is to manually add a reference to the "System.Security" assembly in your solution explorer.

using System;
using System.Text;
using System.Security.Cryptography;
using System.IO;

namespace pc.ImplementingKeyManagement
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Enter in secret Data");
            var data = Console.ReadLine();

            var EncryptedData = Protect(data);
            var s = Encoding.Default.GetString(EncryptedData);

            Console.WriteLine(s);

            SaveToFile(s);
        }

        static byte[] Protect(string data)
        {
            byte[] userData = Encoding.Default.GetBytes(data);
            return ProtectedData.Protect(userData, null, DataProtectionScope.CurrentUser);
        }

        static void SaveToFile(string data)
        {
            using (var fs = new FileStream(@"c:\secure.txt", FileMode.Create, FileAccess.Write))
            {
                try
                {
                    using (var bw = new BinaryWriter(fs))
                    {
                        try
                        {
                            bw.Write(data);
                        }
                        finally
                        {
                            bw.Close();
                        }
                    }
                }
                finally
                {
                    fs.Close();
                }
            }
        }
    }
}

in the above code, we take in a string encrypt it to the logged in user, then save to a file.



The string is written to our text file



now here's the code to decrypt our string

using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

namespace pc.keyManagementReadExample
{
    class Program
    {
        static void Main(string[] args)
        {
            //get contents of secret data
            var s = ReadFile();
            //print encrypted data
            Console.WriteLine("Encrypted data");
            Console.WriteLine(s);

            //print decrypted data
            Console.WriteLine("Decrypted:");
            Console.WriteLine(UnProtect(s));
        }

        static string ReadFile()
        {
            string data = string.Empty;

            using (var fs = new FileStream("c:/secure.txt", FileMode.Open))
                try
                {
                    using (var br = new BinaryReader(fs))
                        try
                        {
                            data = br.ReadString();
                        }
                        finally
                        {
                            br.Close();
                        }

                }
                finally
                {
                    fs.Close();
                }


            return data;
        }

        static string UnProtect(string data)
        {
            byte[] encryptedData = Encoding.Default.GetBytes(data);
            byte[] decryptedData = ProtectedData.Unprotect(encryptedData,
                                    null, DataProtectionScope.CurrentUser);

            return Encoding.Default.GetString(decryptedData);
        }
    }

}

Above we read the encrypted string in from our file and decrypt it. if we try to decrypt if with the same user context we get.



but if we try to decrypt the data under a different user context we get an CryptographicException "Key not valid for use in specified state"