How to create Encryption Key for Encryption Algori

2019-01-30 12:26发布

问题:

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.

回答1:

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.



回答2:

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.



回答3:

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? .



回答4:

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);
}


回答5:

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);


回答6:

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.