DES ECB C# encryption/decryption

6.1k views Asked by At

I have a problem with decryption of data previously encrypted. I am using the sequential encrypt-decrypt-encrypt with three different keys to get triple des effect. The encryption function works correctly (returns 8-byte array), but the decryption function returns empty array.

    public static byte[] EncryptDES(byte[] clearData, byte[] key) 
    { 
        DES desEncrypt = new DESCryptoServiceProvider(); 
        desEncrypt.Mode = CipherMode.ECB; 
        desEncrypt.Key = key; 
        ICryptoTransform transForm = desEncrypt.CreateEncryptor(); 
        MemoryStream encryptedStream = new MemoryStream(); 
        CryptoStream cryptoStream = new CryptoStream(encryptedStream, transForm, CryptoStreamMode.Write); 
        cryptoStream.Write(clearData, 0, clearData.Length); 
        byte [] encryptedData = encryptedStream.ToArray(); 
        return encryptedData;
    }

    public static byte[] DecryptDES(byte[] clearData, byte[] key)
    {
        DES desDecrypt = new DESCryptoServiceProvider();
        desDecrypt.Mode = CipherMode.ECB;
        desDecrypt.Key = key;
        ICryptoTransform transForm = desDecrypt.CreateDecryptor();
        MemoryStream decryptedStream = new MemoryStream();
        CryptoStream cryptoStream = new CryptoStream(decryptedStream, transForm, CryptoStreamMode.Write);
        cryptoStream.Write(clearData, 0, clearData.Length);
        byte[] encryptedData = decryptedStream.ToArray();
        return encryptedData;
    }

    public static byte[] Encrypt3DES(byte[] clearData, byte[] key0, byte[] key1, byte[] key2) 
    {
        byte[] encryptedData1 = new byte[clearData.Length];
        byte[] encryptedData2 = new byte[clearData.Length];
        byte[] encryptedData3 = new byte[clearData.Length];
        encryptedData1 = DESCrypto.EncryptDES(clearData    , key0);
        encryptedData2 = DESCrypto.DecryptDES(encryptedData1, key1);
        encryptedData3 = DESCrypto.EncryptDES(encryptedData2, key2);
        return encryptedData3;
    } 

What am I doing wrong?

2

There are 2 answers

0
Sani Huttunen On

TripleDES already exist in the Framework but I guess you want to roll your own implementation for educational purposes.

You're making things more complicated than necessary. Since you are using streams why don't you chain them all instead:

public static byte[] TripleDESEncrypt(byte[] plainText, byte[] key1, byte[] key2, byte[] key3)
{
  var des = DES.Create();
  des.Mode = CipherMode.ECB;

  des.Padding = PaddingMode.None;
  des.Key = key3;
  var encryptor1 = des.CreateEncryptor();

  des.Key = key2;
  var decryptor = des.CreateDecryptor();

  des.Padding = PaddingMode.PKCS7;
  des.Key = key1;
  var encryptor2 = des.CreateEncryptor();

  byte[] result;
  using (var ms = new MemoryStream())
  {
    using (var cs1 = new CryptoStream(ms, encryptor1, CryptoStreamMode.Write))
    using (var cs2 = new CryptoStream(cs1, decryptor, CryptoStreamMode.Write))
    using (var cs3 = new CryptoStream(cs2, encryptor2, CryptoStreamMode.Write))
      cs3.Write(plainText, 0, plainText.Length);

    result = ms.ToArray();
  }


  return result;
}

 

public static byte[] TripleDESDecrypt(byte[] cipherText, byte[] key1, byte[] key2, byte[] key3)
{
  var des = DES.Create();
  des.Mode = CipherMode.ECB;

  des.Padding = PaddingMode.PKCS7;
  des.Key = key1;
  var decryptor1 = des.CreateDecryptor();

  des.Padding = PaddingMode.None;
  des.Key = key2;
  var encryptor = des.CreateEncryptor();

  des.Key = key3;
  var decryptor2 = des.CreateDecryptor();

  byte[] result;
  using (var ms = new MemoryStream())
  {
    using (var cs1 = new CryptoStream(ms, decryptor1, CryptoStreamMode.Write))
    using (var cs2 = new CryptoStream(cs1, encryptor, CryptoStreamMode.Write))
    using (var cs3 = new CryptoStream(cs2, decryptor2, CryptoStreamMode.Write))
      cs3.Write(cipherText, 0, cipherText.Length);

    result = ms.ToArray();
  }


  return result;
}

Make note of the usage of using blocks and also how the padding is applied to the different streams.

The framework TripleDES is about 2.5 times faster than the above code.

public static byte[] TripleDESEncryptFramework(byte[] plainText, byte[] key)
{
  var tdes = TripleDES.Create();
  tdes.Mode = CipherMode.ECB;
  tdes.Padding = PaddingMode.PKCS7;
  tdes.Key = key;

  var encryptor = tdes.CreateEncryptor();

  byte[] result;
  using (var ms = new MemoryStream())
  {
    using (var cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
      cs.Write(plainText, 0, plainText.Length);

    result = ms.ToArray();
  }

  return result;
}

If you want to compare the results of the two different encryption methods then you need to remember that the 24-bit key for TripleDES is actually the 3 keys put in one array:

[  key1  ][  key2  ][  key3  ]
==============================
[            key             ]
0
user6836587 On

Just need cryptoStream.FlushFinalBlock(). Its code works great:

   //ENCRYPT
   public static byte[] EncryptDES(byte[] clearData, byte[] key) 
   { 
       DES desEncrypt = new DESCryptoServiceProvider(); 
       desEncrypt.Mode = CipherMode.ECB; 
       desEncrypt.Key = key; 
       ICryptoTransform transForm = desEncrypt.CreateEncryptor(); 
       MemoryStream encryptedStream = new MemoryStream(); 
       CryptoStream cryptoStream = new CryptoStream(encryptedStream, transForm, CryptoStreamMode.Write); 
       cryptoStream.Write(clearData, 0, clearData.Length);
       cryptoStream.FlushFinalBlock();
       return encryptedStream.ToArray();
   }

   //DECRYPT
   public static byte[] DecryptDES(byte[] clearData, byte[] key)
   {
       DES desDecrypt = new DESCryptoServiceProvider();
       desDecrypt.Mode = CipherMode.ECB;
       desDecrypt.Key = key;
       ICryptoTransform transForm = desDecrypt.CreateDecryptor();
       MemoryStream decryptedStream = new MemoryStream();
       CryptoStream cryptoStream = new CryptoStream(decryptedStream, transForm, CryptoStreamMode.Write);
       cryptoStream.Write(clearData, 0, clearData.Length);
       cryptoStream.FlushFinalBlock();
       return decryptedStream.ToArray();
   }