But to answer your question, the .NET AES provider does know if you're using the wrong key - but that's only because you asked it to.
You tried to encrypt the bytes:
2,5,1,6,7
Using code something like:
var plainText = new byte[] {2,5,1,6,7};
byte[] cipherText;
var key = new Byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
var iv = new Byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
//encrypt plaintext using one key
using (var aes = Aes.Create())
{
var crypt = aes.CreateEncryptor(key, iv);
cipherText = crypt.TransformFinalBlock(plainText, 0, plainText.Length);
}
In reality, AES only operates on 16-byte blocks. In order to transform your input data into something long enough that it can actually encrypt, the input bytes are first padded. When you construct an Aes
class in .NET:
using (var aes = Aes.Create())
{
}
the default padding mode in Aes
is PKCS#7 padding. This causes the Aes encrypted to pad your plainText to:
2, 5, 1, 6, 7, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11
And those byes are then encrypted into:
210, 49, 160, 164, 2, 53, 121, 254, 79, 249, 91, 111, 104, 173, 50, 207
When you decrypt those cipher bytes:
byte[] recoveredPlainText;
using (var aes = Aes.Create())
{
var key = new Byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
var iv = new Byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
var crypt = aes.CreateDecryptor(key, iv);
recoveredPlainText = crypt.TransformFinalBlock(cipherText, 0, cipherText.Length);
}
Aes knows to ensure that proper PKCS#7 padding exists:
2, 5, 1, 6, 7 , 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11
If you tried to decrypt with an invalid key (e.g. {1,0,0, ..., 0}
), you will end up with plainText that does not contain valid PKCS#7 padding:
154,203,183,159,52,162,186,41,127,162,152,75,114,109,107,74
And so the Aes decryptor will throw an exception.
You can still decrypt the bytes with an invalid key, all you have to do is tell Aes not to look for any padding by setting Padding = PaddingMode.None
:
byte[] recoveredPlainText;
using (var aes = Aes.Create())
{
aes.Padding = PaddingMode.None;
var key = new Byte[] { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
var iv = new Byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
var crypt = aes.CreateDecryptor(key, iv);
recoveredPlainText = crypt.TransformFinalBlock(cipherText, 0, cipherText.Length);
}
tl;dr: It knows because you used Padding.
Note: Any code is released into the public domain. No attribution required.