Piero Alberto
Piero Alberto

Reputation: 3943

Decrypting TripleDES: Specified key is a known weak key and cannot be used

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

Answers (3)

Vlad Koshelik
Vlad Koshelik

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

zaph
zaph

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

Evk
Evk

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

Related Questions