Often when using pre built framework web applications they have hard coded the <machineKey> validationKey and decryptionKey values. The main reason for this is to add support for web farms as the forms authentication, view state and out of process session state all use these settings for security. Whilst most of these frameworks work out of the box, using the defaults out of the box mitigates most of the benefit of the encryption as the keys are public knowledge becuase the source code is published. Take for example dot Net Nuke whcih is a popular framework, their default encryption keys are hard coded as.
<machineKey validationKey="143E348B9D47BC9BB545663349152FA4E721A0E1" decryptionKey="D71F4C5AB3D2EBAE9C2C70EFC498D726F8B0ABDECCB8296B" decryption="3DES" validation="SHA1" />
Knowing the keys and the algorithm used leaves very little in the line of defense from someone wanting to decrypt the forms authentication, and hidden values are not that hidden for someone with a little encryption knowledge
When using public frameworks it best to create you own set of keys. This can be done using the method below passing in the required key size in bytes, the key sizes for common Crypto Algorithms and Hashs are listed below;
- AES requires a 256 bit key (64 hexadecimal characters, 32 bytes).
- MD5 requires a 128 bit key (32 hexadecimal characters, 16 bytes).
- SHA1 requires a 160 bit key (40 hexadecimal characters, 20 bytes).
- DES requires a 64 bit key (16 hexadecimal characters, 8 bytes).
- 3DES requires a 192 bit key (48 hexadecimal characters, 24 bytes).
- RC2 requires a 128 bit key (32 hexadecimal characters 16 bytes).
- HMACSHA256 requires a 256 bit key (64 hexadecimal characters, 32 bytes).
- HMACSHA384 requires a 384 bit key (96 hexadecimal characters, 48 bytes).
- HMACSHA512 requires a 512 bit key (128 hexadecimal characters, 64 bytes).
public byte[] GenerateRandomKey(int keySizeInBytes)
{
byte[] buff = new byte[keySizeInBytes];
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
rng.GetBytes(buff);
return buff;
}
public string GenerateRandomKeyAsString(int keySizeInBytes)
{
byte[] keyAsBytes = GenerateRandomKey(keySizeInBytes);
StringBuilder sb = new StringBuilder(keySizeInBytes * 2);
for (int i = 0; i < keyAsBytes.Length; i++)
sb.Append(string.Format("{0:X2}", keyAsBytes[i]));
return sb.ToString();
}
public string GenerateRandomKeyAsString()
{
// new key for AES
Trace.WriteLine(GenerateRandomKeyAsString(32))
}