How can I do an ISO 9797-1 MAC with triple DES in C#?

logeeks picture logeeks · May 19, 2011 · Viewed 9k times · Source

I've got a project which stipulates the following encryption rules for a 24 byte block of data.

1) Cryptography should be done using full triple DES MAC algorithm as defined in 9797-1 as MAC algorithm 3 with output transformation 3 without truncation and with DES in CBC mode as block cipher with ICV set to zeros. Last 8 bytes of encrypted data constitute the value we need.

The program is saying the encryption done is wrong. Are there any other things I need to do to match the above spec?

The data is a 24 byte value and output of the encryption should be 8 bytes, I guess (as per the spec). I am getting the whole 24 bytes as output :(

I wrote the following code to achieve the said specification:

des.KeySize = 128;
des.Key = ParseHex(key);
des.Mode = CipherMode.CBC;
des.Padding = PaddingMode.None;

ICryptoTransform ic = des.CreateEncryptor();

CryptoOutput = ic.TransformFinalBlock(CryptoOutput, 0, 24);

I tried this also:

MACTripleDES des = new MACTripleDES(ParseHex(key));
byte[] CDCryptp = des.ComputeHash(CryptoOutput);

Answer

Rasmus Faber picture Rasmus Faber · Jun 9, 2011

ISO 9797-1 MAC Algorithm 3 consists of using the first DES key to perform a CBC MAC and then only for the final block perform a full 3-DES operation.

Try this:

byte[] keybytes = ParseHex(key);
byte[] key1 = new byte[8];
Array.Copy(keybytes, 0, key1, 0, 8);
byte[] key2 = new byte[8];
Array.Copy(keybytes, 8, key2, 0, 8);

DES des1 = DES.Create();
des1.Key = key1;
des1.Mode = CipherMode.CBC;
des1.Padding = PaddingMode.None;
des1.IV = new byte[8];

DES des2 = DES.Create();
des2.Key = key2;
des2.Mode = CipherMode.CBC;
des2.Padding = PaddingMode.None;
des2.IV = new byte[8];

// MAC Algorithm 3
byte[] intermediate = des1.CreateEncryptor().TransformFinalBlock(data, 0, data.Length);

// Output Transformation 3
byte[] intermediate2 = des2.CreateDecryptor().TransformFinalBlock(intermediate, intermediate.Length - 8, 8);
byte[] result = des1.CreateEncryptor().TransformFinalBlock(intermediate2, 0, 8);