Search code examples
c#.netcryptographycryptographicexception

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


I'm using the .NET 3.0 class System.Security.Cryptography.MACTripleDES class to generate a MAC value. Unfortunately, I am working with a hardware device that uses "1111111111111111" (as hex) as a single-length DES key. The System.Security.Cryptography library does some sanity checking on the key and returns a Exception if you try to use a cryptographically weak key.

For example:

byte[] key = new byte[24];
for (int i = 0; i < key.Length; i++)
  key[i] = 0x11;

byte[] data = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
byte[] computedMac = null;
using (MACTripleDES mac = new MACTripleDES(key))
{
  computedMac = mac.ComputeHash(data);
}

throws an exception

System.Security.Cryptography.CryptographicException : Specified key is a known weak key for 'TripleDES' and cannot be used.

I know this is not a secure key. In production, the device will be flashed with a new, secure key. In the mean time, is there any way to inhibit this Exception from being thrown? Perhaps an app.config or registry setting?

Edit: The key would actually be 101010... due to the algorithm forcing odd parity. I'm not sure if this is universal to the DES algorithm or just a requirement in the payment processing work I do.

Edit 2: Daniel's answer below has some very good information about hacking .NET. Unfortunately, I wasn't able to solve my problem using this technique, but there is still some interesting reading there.


Solution

  • Instead of using MACTripleDES with the DES key repeated to fake a single DES CBC-MAC, you could just implement CBC-MAC yourself on top of DESCryptoServiceProvider.

    <1111111111111111> is not a weak DES key.

    This will calculate a DES CBC-MAC:

    public static byte[] CalcDesMac(byte[] key, byte[] data){
            DESCryptoServiceProvider des = new DESCryptoServiceProvider();
            des.Key = key;
            des.IV = new byte[8];
            des.Padding = PaddingMode.Zeros;
            MemoryStream ms = new MemoryStream();
            using(CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write)){
              cs.Write(data, 0, data.Length);
            }
            byte[] encryption = ms.ToArray();
            byte[] mac = new byte[8];
            Array.Copy(encryption, encryption.Length-8, mac, 0, 8);
            PrintByteArray(encryption);
            return mac;
        }