Reputation: 3943
Why does this code return the weak key error?
static public byte[] TDESDecrypt(byte[] toDecrypt, byte[] key, CipherMode mode = CipherMode.ECB, PaddingMode padding = PaddingMode.None)
{
TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
tdes.Key = key;
tdes.Mode = mode;
tdes.Padding = padding;
ICryptoTransform cTransform = tdes.CreateDecryptor();
byte[] resultArray = cTransform.TransformFinalBlock(toDecrypt, 0, toDecrypt.Length);
tdes.Clear();
return resultArray;
}
When I try to execute the line "tdes.Key = key", I get the error
deriveSessionKeyIS System.Security.Cryptography.CryptographicException: Specified key is a known weak key for TripleDES and cannot be used
Why? The key I'm trying is random, but one of the tested keys, for example, is FB13347FE570DC4FFB13347FE570DC4F. Where is the problem?
Upvotes: 4
Views: 5593
Reputation: 1
I found this solution on MSDN Forum. This solution works perfectly with weak keys.
With the code from the forum I made this:
using System.Security.Cryptography;
using System.IO;
using System.Reflection;
static class MyDES
{
public static byte[] Encrypt(byte[] data, byte[] key, byte[] IV)
{
MemoryStream mStream = new MemoryStream();
DESCryptoServiceProvider des = new DESCryptoServiceProvider();
des.Mode = CipherMode.ECB;
des.Padding = PaddingMode.None;
CryptoStream cStream = new CryptoStream(mStream,
des.CreateWeakEncryptor(key, IV),
CryptoStreamMode.Write);
cStream.Write(data, 0, data.Length);
cStream.FlushFinalBlock();
byte[] ret = mStream.ToArray();
cStream.Close();
mStream.Close();
return ret;
}
public static byte[] Decrypt(byte[] data, byte[] key, byte[] IV)
{
MemoryStream msDecrypt = new MemoryStream(data);
DESCryptoServiceProvider des = new DESCryptoServiceProvider();
des.Mode = CipherMode.ECB;
des.Padding = PaddingMode.None;
CryptoStream csDecrypt = new CryptoStream(msDecrypt,
des.CreateWeakDecryptor(key, IV),
CryptoStreamMode.Read);
byte[] fromEncrypt = new byte[data.Length];
csDecrypt.Read(fromEncrypt, 0, fromEncrypt.Length);
return fromEncrypt;
}
#region DESCryptoExtensions
public static ICryptoTransform CreateWeakEncryptor(this DESCryptoServiceProvider cryptoProvider, byte[] key, byte[] iv)
{
MethodInfo mi = cryptoProvider.GetType().GetMethod("_NewEncryptor", BindingFlags.NonPublic | BindingFlags.Instance);
object[] Par = { key, cryptoProvider.Mode, iv, cryptoProvider.FeedbackSize, 0 };
ICryptoTransform trans = mi.Invoke(cryptoProvider, Par) as ICryptoTransform;
return trans;
}
public static ICryptoTransform CreateWeakEncryptor(this DESCryptoServiceProvider cryptoProvider)
{
return CreateWeakEncryptor(cryptoProvider, cryptoProvider.Key, cryptoProvider.IV);
}
public static ICryptoTransform CreateWeakDecryptor(this DESCryptoServiceProvider cryptoProvider, byte[] key, byte[] iv)
{
return CreateWeakEncryptor(cryptoProvider, key, iv);
}
public static ICryptoTransform CreateWeakDecryptor(this DESCryptoServiceProvider cryptoProvider)
{
return CreateWeakDecryptor(cryptoProvider, cryptoProvider.Key, cryptoProvider.IV);
}
#endregion
}
Upvotes: 0
Reputation: 112875
It is a weak 3DES key because the additional 8-byte will again be repeated as the last 8-bits. Thus the 3DES encryption has reverted to DES and that is weak.
3DES does three operations, in the most common form of ede
the data is first encrypted with the first 8-bytes of the key, then decrypted with the second 8-bytes and finally encrypted with the final 8-bytes (which in this case are the first 8-bytes). Note that after the first two operations the data is back to the original data thus the only encryption that is actually performed is the last encryption and that is 8-bytes which is a 56-bit key. That is a weak 3DES key.
Upvotes: 1
Reputation: 101613
You can read in wikipedia for example about what is the weak key in cryptography. For triple DES there is a method (TripleDES.IsWeakKey) which checks triple DES key for weakness. In you case, key FB13347FE570DC4FFB13347FE570DC4F
is symmetric in a sense that first 8 bytes of it are exactly equal last 8 bytes. That means if you encrypt something with that key, and then encrypt that encrypted info one more time - you will restore original text (because of how this concrete encryption algorithm works), which is obviously dangerous.
So in short .NET protects you from doing dangerous things resulting in cryptographic weakness. If you will use standard GenerateKey()
function to generate key (or just don't set Key
explicitly) - weak keys won't be generated.
A bit more information about why that key is weak for triple DES. 3DES is named like this because it essentially uses 3 keys and applies pure DES encryption\decryption with those keys 3 times. Each key is 8 bytes long, so 3DES key size is 8*3 = 24 bytes. However, algorithm also allows for first and third keys to be the same, and as such allows to use 16-byte keys (like in your example). In that case first half of those 16-bytes are used as a third key. This option provides less security but is still viable.
Now, when in your case first half and second half of your 16-bytes key are the same, so all three keys which will be used by 3DES are the same. Given that 3DES works like this:
DES encrypt with 3rd(DES Decrypt with 2nd(DES Encrypt with 1st(plaintext)))
You see that in your case you fall back to using simple DES, which defeats whole purpose of using 3DES in the first place.
Upvotes: 5