Click here to Skip to main content
15,116,323 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I have not been able to find a clear example of how to store an encryption key in a key container using C#. I can generate my own keys and use them to encrypt and decrypt data. Now I am wondering two things:

1. Is it realistic to consider the Microsoft key containers as a reasonably secure method of protecting encryption keys?

2. Can anyone provide a simple C# code sample showing how to do this? I am currently using the RijndaelManaged encryptor with a symmetric AES encryption method.
Posted
Comments
Sergey Alexandrovich Kryukov 16-Apr-13 15:00pm
   
To start with, review your scenario, described it, as well as the goals. Without it, your question is not anything certain...
—SA
jsolutions_uk 16-Apr-13 15:34pm
   
Just out of interest, how are you planning to distribute these keys? That is going to be your biggest problem with AES keys, or any other symmetric key. Once you have worked that out, then there is little point investing in a storage technology that is weeker than your distribution mechanism.

Also, it is probably worth noting that a possibly better scheme is to use assymetric keys, so clients of whatever app this is share their public keys amongst each other as seen fit. Some kind of fingerprint check could be done over the phone, for example. Each time a message needs to be sent, a one time AES key is generated to encrypt the body of the message and this is encrypted with the destination public key. That way, the only person who can get the clear text is the reciever.

Key management will probably be a lot easier if you follow this model.

Is that more of an answer than a comment? :)
Sergey Alexandrovich Kryukov 16-Apr-13 15:45pm
   
That's the key (pub unintended) :-) That's why I suggest we consider the scenario, and then the security of the solution... Just for giggles, imagine for a second that someone wants to store a private key in a super-puper safe way, and then sends this key somewhere; yes, artificially anecdotic situation, but I'm just trying to explain why the considerations should start with the scenario...
—SA
AnotherKen 17-Apr-13 1:14am
   
ok, in this context what I intend to do is offer the user a way to "securely" store a key for local use only. This key would not be intended for passing along to other systems. The data I am encrypting basically just sits on the HD the application is installed to. I could store a key file of my own devising in the same location but this seems less secure than storing it in some completely different way to try to make it harder for a hacker to figure out what keys are being used.
   
You cannot say "store" a key. You should talk about public or private key.
—SA
jsolutions_uk 17-Apr-13 2:44am
   
If the idea is to only encrypt data locally, to prevent any other users of that PC from reading the data (implementing Confidentiality), how about forgetting the idea of an encrypted key, and deriving a key at runtime from a password entered by the user on running the application (if of course the app is a user interactive one). It sounds to me like your problem is purely a Confidentiality of private, rather than shared data?
AnotherKen 17-Apr-13 3:13am
   
That is certainly one option, another is one I was reading about where you can setup an encryptor that only works for the currently logged in user. But in those cases I am just saving the key into a file. I have heard of storing keys in the registry but that seems no more secure and possibly prone to pruning by registry cleaning programs (assuming you are clever enough not to directly associate the key pair with the application that uses it.) This is why I was asking about the security of the Microsoft provided key containers. That one is still an unknown to me.
Bhanu Pratap Verma 25-Sep-14 2:15am
   
<pre>I have some client requirement to save the key in key container, I have already generated key and I want to store it in the key container. Is it possible to do it?

I am using AES algorithm to encrypt and decrypt data.Please follow the below code.</pre>



<pre>public string Encrypt_AES(string clearText)
{
string text = System.IO.File.ReadAllText("D:\\ITC\\Symmetric Key\\Key.txt");
string EncryptionKey = text;
byte[] clearBytes = Encoding.Unicode.GetBytes(clearText);
using (Aes encryptor = Aes.Create())
{
Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
encryptor.Key = pdb.GetBytes(32);
encryptor.IV = pdb.GetBytes(16);
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateEncryptor(), CryptoStreamMode.Write))
{
cs.Write(clearBytes, 0, clearBytes.Length);
cs.Close();
}
clearText = Convert.ToBase64String(ms.ToArray());
}
}
return clearText;
}
public string Decrypt_AES(string cipherText)
{
string text = System.IO.File.ReadAllText("D:\\ITC\\Symmetric Key\\Key.txt");
string EncryptionKey = text;
byte[] cipherBytes = Convert.FromBase64String(cipherText);
using (Aes encryptor = Aes.Create())
{
Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
encryptor.Key = pdb.GetBytes(32);
encryptor.IV = pdb.GetBytes(16);
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateDecryptor(), CryptoStreamMode.Write))
{
cs.Write(cipherBytes, 0, cipherBytes.Length);
cs.Close();
}
cipherText = Encoding.Unicode.GetString(ms.ToArray());
}
}
return cipherText;
}
#endregion</pre>

I still think you are thinking too much about the implementation rather than thinking about exactly what security you need, but maybe I'm wrong, so I'll try and provide some suggestions for the solution you are looking for :) :

My understanding is that you cannot store symmetric keys in key containers, although I am not 100% sure of this.

Looking at AesCryptoServiceProvider[^], the constructor doesn't take the parameters that RSACryptoServiceProvider[^] provides, to allow it to use key containers. I would love to hear otherwise.

So if you really want to use key containers, probably the best way to do it, is to generate a pub/priv key pair and store it in a user keystore using various CspParameters[^]. Your app can then generate, or accept a user input AES key. Your data that needs encrypting can then be encrypted with the AES key and the AES key encrypted with the pub key from your stored key pair. When you need to decrypt, you decrypt your AES key, then decrypt your data. Alternatively, if you have a small amount of data, you could skip the AES encryption entirely and use RSA encryption.

Try this[^] for starters
   
Comments
AnotherKen 17-Apr-13 15:45pm
   
Thank you jsolutions_uk, that is helpful. I will investigate the use of RSA encryption, since that sounds more promising for this application.
AnotherKen 17-May-13 15:41pm
   
I have gotten to the point where I agree that I can use RSA Asymmetric encryption for the application I am working on. My initial tests are now working. I had originally gone with AES because it was easier to pickup and use than RSA, but with time I was able to find the information I needed to get RSA encryption working. Thank you for taking the time to respond to my question.
jsolutions_uk 18-May-13 3:46am
   
glad to be of help :)
I have some client requirement to save the key in key container, I have already generated key and I want to store it in the key container. Is it possible to do it?

I am using AES algorithm to encrypt and decrypt data.Please follow the below code.

public string Encrypt_AES(string clearText)
        {
            string text = System.IO.File.ReadAllText("D:\\ITC\\Symmetric Key\\Key.txt");
            string EncryptionKey = text;
            byte[] clearBytes = Encoding.Unicode.GetBytes(clearText);
            using (Aes encryptor = Aes.Create())
            {
                Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
                encryptor.Key = pdb.GetBytes(32);
                encryptor.IV = pdb.GetBytes(16);
                using (MemoryStream ms = new MemoryStream())
                {
                    using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateEncryptor(), CryptoStreamMode.Write))
                    {
                        cs.Write(clearBytes, 0, clearBytes.Length);
                        cs.Close();
                    }
                    clearText = Convert.ToBase64String(ms.ToArray());
                }
            }
            return clearText;
        }
        public string Decrypt_AES(string cipherText)
        {
            string text = System.IO.File.ReadAllText("D:\\ITC\\Symmetric Key\\Key.txt");
            string EncryptionKey = text;
            byte[] cipherBytes = Convert.FromBase64String(cipherText);
            using (Aes encryptor = Aes.Create())
            {
                Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
                encryptor.Key = pdb.GetBytes(32);
                encryptor.IV = pdb.GetBytes(16);
                using (MemoryStream ms = new MemoryStream())
                {
                    using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateDecryptor(), CryptoStreamMode.Write))
                    {
                        cs.Write(cipherBytes, 0, cipherBytes.Length);
                        cs.Close();
                    }
                    cipherText = Encoding.Unicode.GetString(ms.ToArray());
                }
            }
            return cipherText;
        }
        #endregion
   
Thanks Bhanu Raja. That is almost identical to what I have implemented now, but I appreciate your attempt to answer the question.
   

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)




CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900