How to create Encryption Key for Encryption Algorithms?
Asked Answered
M

8

36

I want to use encryption algorithm available in .Net Security namespace, however I am trying to understand how to generate the key, for example AES algorithm needs 256 bits, that 16 bytes key, and some initialization vector, which is also few bytes.

  1. Can I use any combination of values in my Key and IV? e.g. all zeros in Key and IV are valid or not? I know the detail of algorithm which does lots of xors, so zero wont serve any good, but are there any restrictions by these algorithms?

  2. Or Do I have to generate the key using some program and save it permanently somewhere?

I want to store data in database after encryption, the secure profile data like username, password, phone number etc, and the key will be available to database user mentioned in connection string only, and to the administrator.

Mathewmathews answered 23/3, 2010 at 20:38 Comment(1)
If u r want to use AES256, then your key should be 32 bytes and set KeySize property = 256. else it will use AES 128. You can use all zeros but in the context of security, there is no point doing that as it is not secure. Yes better generate random key(as in Michael Howard-MSFT answer) and store securely.Columelliform
F
13

If you are using encryption to exchange data then you will need a key exchange protocol, but you don't make one yourself instead use one off-the-shelf like TLS or SSL.

If you use encryption to store data then you generate the IV using CryptGenRandom (or its .net equivalent RandomNumberGenerator.GetBytes) and save it along the document (in clear, no need to protect the IV). You never write down the key, the key is provided by the user. Usualy you derive the key from a password phrase using CryptDeriveKey, or its .Net equivalent PasswordDeriveKey.CryptDeriveKey.

Update

To store a secret in the database that is available only to the user and an administrator you need to use 3 keys:

  • one to encrypt the data with (call it the DK key)
  • one user key to encrypt the DK key (call it UK)
  • one administrator key to encrypt the DK key (call it AK)

In theory you encrypt the data with DK and then encrypt the DK with UK and save it, and encrypt the DK with AK and save it. This way the user can use again the UK to decrypt the DK and then decrypt the data, and the administrator can use the AK to decrypt the DK and then decrypt the data. The big problem is the fact that the system is always automated, so the system needs access to the administrator's key which means is not truly a persnal key of the administrator, but instead is a system key (it cannot be used for purposes of non-repudiation for instance).

As a heads up, knowledge of what IV is or how to use AES from C# and how cryptography algorithm work will get you exactly 0 (zero) traction in solving this kind of problems. The issue is never what IV and key to use, the issue is always key provisioning. For actual crypto operations, just use the built-in support from the database, see Cryptography in SQL Server. I can easily argue that the only facility you need is TDE (Transparent Data Encryption) to protect against accidental loss of media.

Foothold answered 23/3, 2010 at 20:45 Comment(5)
I want to store data in database after encryption, the secure profile data like username, password, phone number etc, and the key will be available to database user mentioned in connection string only, and to the administrator.Mathewmathews
In simple words, I only need to protect sensitive user information from other developers accessing the server and backups, although they access server very rarely, backups can be anywhere but without key the sensitive part should not be visible in pure text form.Mathewmathews
passwords should be hashed (one-way encryption) not encrypted. Other sensitive data can be encrypted. but encrypt only the columns containing sensitive data, not the entire database which causes performance consequences and overheads.Columelliform
The acronyms are hard to follow - especially when used closely in the same sentence.Krohn
RandomNumberGenerator.GetBytes() is abstract. Hold on while I go away and implement myself !Jugum
O
47

You really ought to do this the correct way :)

1) Use a securely generated random IV
2) Use a securely generated random key
3) Don't use ECB mode - EVER

AesManaged aes = new AesManaged();
aes.GenerateKey();
aes.GenerateIV();

The code above will correctly and securely generate a random IV and random key for you.

Obsession answered 25/3, 2010 at 0:19 Comment(2)
A late reply because I was just reading into this: instantiating the AESManaged Class already generates the keys for you, just read the .Key and .IV properties.Unamuno
You say you should never use ECB mode, and although I agree with you, I would say that there are times when you may want to use it. It's very rare, but as a for example, if you wanted to implement AES in CTR (counter mode) then you'd need to use the algorithm in ECB mode. For the ordinary user, you statement is absolutely correct and I would never advocate you use ECB mode without fully understanding the potential pitfalls. en.wikipedia.org/wiki/Block_cipher_mode_of_operation gives a good round-up of block cipher modes.Tulatulip
M
18

Sounds like you need to read into the Rfc2898DeriveBytes class.

Rfc2898DeriveBytes.GetBytes();

It has a method(above) that allows you to tailor the size of byte arrays that are fed into the .Key and .IV properties on a symmetric encryption algorithm, simply by feeding an int value. The MS official 70-536 book suggests doing this pro-grammatically by dividing the KeySize property / 8.

I.e TripleDes or AESManaged. Whatever you use, the algorithm itself will have some pre-reqs that will need meeting first. I.e satisfying the key size conditions. The RunTime will automatically fill the properties and fields and etc the best and most strongest values for you. But the IV and Key needs to come from you. This how you can do the following:

RijndaelManaged myAlg = new RiRijndaelManaged();
byte[] salt = Encoding.ASCII.GetBytes("Some salt value");
Rfc2898DeriveBytes key = new Rfc2898DeriveBytes("some password", salt);
myAlg.Key = key.GetBytes( myAlg.KeySize / 8);
myAlg.IV  = key.GetBytes( myAlg.BlockSize / 8);
// myAld should now fully set-up.

Above you can see what I mean by doing it pro-grammatically, as it should pretty much do it all for you, without you even really having to bat an eye-lid as to meeting it's pre-reqs.

The Microsoft 70-536 book states that the .Key properties expect the byte arrays you supply to them in bytes and not bits. The RFC class works in bytes where as an algorithms KeySize property works in bits. 1 byte = 8 bits. Can you see where this is going ... ? This should give you an idea as to why the above sample peice of code is done the way it is! I studied it and it makes pretty darn good sense to me!

The above answer should allow you to create your algorithm object with supplied password and a static salt value that can be hard code at both ends. Only thing you need to do is worry about how you going to make sure that the byte arrays stored at .Key and .IV are safely transported to a recipient so that can successfully decrypt the message you encrypted. By safely reconstructing the same algorithm object.

OBTW:

AESManaged has a keysize req': 128Bits = 16 Bytes !!! (8*8 = 64, 64Bit / 8bits per Byte = 8 Bytes) Therefore

64*2 = 128Bit, 8*2, ==> 16bytes key size !

256Bit = 32Bytes !!!!


According to the 70-536 official training kit book, Aes is limited to having keysize of 128bits in size. 256bits,192 and 128 key size for example can be used with the Rijndael class.


You could on the other hand completely forget all that crap and simply use .GenerateKey and GenerateIV methods instead to save you all the hassle of sorting out a pre-shared and agreed password and static salt values. Your only concern is figuring out a way of storing and retrieving the key and IV byte arrays. Binary Formatter? .

Myungmyxedema answered 20/4, 2010 at 1:41 Comment(0)
H
13

Generate a random letters / hex code in a specific length.

This function (taken from here) return a random key in a specific length:

private static string CreateSalt(int size)
{
    //Generate a cryptographic random number.
    RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
    byte[] buff = new byte[size];
    rng.GetBytes(buff);

    // Return a Base64 string representation of the random number.
    return Convert.ToBase64String(buff);
}
Handiwork answered 23/3, 2010 at 20:42 Comment(0)
F
13

If you are using encryption to exchange data then you will need a key exchange protocol, but you don't make one yourself instead use one off-the-shelf like TLS or SSL.

If you use encryption to store data then you generate the IV using CryptGenRandom (or its .net equivalent RandomNumberGenerator.GetBytes) and save it along the document (in clear, no need to protect the IV). You never write down the key, the key is provided by the user. Usualy you derive the key from a password phrase using CryptDeriveKey, or its .Net equivalent PasswordDeriveKey.CryptDeriveKey.

Update

To store a secret in the database that is available only to the user and an administrator you need to use 3 keys:

  • one to encrypt the data with (call it the DK key)
  • one user key to encrypt the DK key (call it UK)
  • one administrator key to encrypt the DK key (call it AK)

In theory you encrypt the data with DK and then encrypt the DK with UK and save it, and encrypt the DK with AK and save it. This way the user can use again the UK to decrypt the DK and then decrypt the data, and the administrator can use the AK to decrypt the DK and then decrypt the data. The big problem is the fact that the system is always automated, so the system needs access to the administrator's key which means is not truly a persnal key of the administrator, but instead is a system key (it cannot be used for purposes of non-repudiation for instance).

As a heads up, knowledge of what IV is or how to use AES from C# and how cryptography algorithm work will get you exactly 0 (zero) traction in solving this kind of problems. The issue is never what IV and key to use, the issue is always key provisioning. For actual crypto operations, just use the built-in support from the database, see Cryptography in SQL Server. I can easily argue that the only facility you need is TDE (Transparent Data Encryption) to protect against accidental loss of media.

Foothold answered 23/3, 2010 at 20:45 Comment(5)
I want to store data in database after encryption, the secure profile data like username, password, phone number etc, and the key will be available to database user mentioned in connection string only, and to the administrator.Mathewmathews
In simple words, I only need to protect sensitive user information from other developers accessing the server and backups, although they access server very rarely, backups can be anywhere but without key the sensitive part should not be visible in pure text form.Mathewmathews
passwords should be hashed (one-way encryption) not encrypted. Other sensitive data can be encrypted. but encrypt only the columns containing sensitive data, not the entire database which causes performance consequences and overheads.Columelliform
The acronyms are hard to follow - especially when used closely in the same sentence.Krohn
RandomNumberGenerator.GetBytes() is abstract. Hold on while I go away and implement myself !Jugum
S
6

Use System.Security.Cryptography.RandomNumberGenerator to generate random bytes:

var rnd = new System.Security.Cryptography.RandomNumberGenerator.Create();
var key = new byte[50];
rnd.GetBytes(key);
Susette answered 23/3, 2010 at 20:45 Comment(0)
I
0

It really depends on what you ned to do with the key.

If the key is to be generated by the computer (and can be any random value) I generally take a SHA256 of a couple GUIDs. This is about as random as you're going to get without a hardware random number generator.

You can use keys with all 0s but obviously it won't be very secure.

Isaiasisak answered 23/3, 2010 at 20:43 Comment(2)
So in short, I can just generate any random crap and store it forever right, ok, and once key is lost its all over? Sure i will try to save copies on secondary medium.Mathewmathews
That's correct. The more random the key, the more secure it is (depending, of course, on how secure your storage of the key is.)Isaiasisak
X
0

For anyone who is looking to generate symmetric key of different byte sizes, this will be the easiest and secure way.

// keyInBytes can be used directly if you setting the key as byte array
var keyInBytes = new System.Security.Cryptography.RandomNumberGenerator.GetBytes(<<DesiredBytes>>);

// securityKey can be used where SecurityKey type is required
var = new SymmetricSecurityKey(keyInBytes);
Xenia answered 26/8, 2023 at 16:25 Comment(0)
D
0

For AES 256 for secret key size of length 44 you can use this code. If you need length of 32 then KeySize would be 192. use according to your requirement.

   string keyBase64Key = string.Empty;
   Console.WriteLine("Creating Aes Encryption 256 bit key");
   using (Aes aesAlgorithm = Aes.Create())
   {
       aesAlgorithm.KeySize = 256;
       aesAlgorithm.GenerateKey();
       keyBase64Key = Convert.ToBase64String(aesAlgorithm.Key);
       Console.WriteLine($"Aes Key Size : {aesAlgorithm.KeySize}");
       Console.WriteLine($"keyBase64Key Size : {keyBase64Key.Length}");
       Console.WriteLine("Here is the Aes key in Base64:");
       Console.WriteLine(keyBase64Key);
   }
Doley answered 8/1 at 6:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.