/// <summary> /// /// </summary> /// <param name="data"></param> /// <param name="key"></param> /// <returns></returns> public static byte[] ComputeMacForIntegrity(this byte[] data, KeyParameter key) { /* * The computation of an s-byte MAC (4 ≤ s ≤ 8; see MAC algorithms) is according to ISO/IEC 9797-1 [2] using a 64-bit block cipher ALG in CBC mode as specified in ISO/IEC 10116. More precisely, the computation of a MAC S over a message MSG consisting of an arbitrary number of bytes with a MAC Session Key K$$_{{\rm S}}$$ takes place in the following steps: * 1. Padding and Blocking * Pad the message M according to ISO/IEC 7816-4 (which is equivalent to method 2 of ISO/IEC 9797-1), hence add a mandatory ‘80’ byte to the right of MSG, and then add the smallest number of ‘00’ bytes to the right such that the length of resulting message MSG := (MSG ‖ ‖ ‘80’ ‖ ‖ ‘00’ ‖ ‖ ‘00’ ‖ ‖ … ‖ ‖ ‘00’) is a multiple of 8 bytes. * MSG is then divided into 8-byte blocks $$X_{1}$$, $$X_{2}$$, $$\ldots$$, $$X_{{\rm k}}$$. * 2. MAC Session Key * The MAC Session Key $$K_{{\rm S}}$$ either consists of only a leftmost key block $$K_{{\rm S}} = K_{{\rm SL}}$$ or the concatenation of a leftmost and a rightmost key block $$K_{{\rm S}} = (K_{{\rm SL} }\vert \vert K_{\rm SR})$$. * 3. Cryptogram Computation * Process the 8-byte blocks $$X_{1}$$, $$X_{2}$$, …, $$X_{{k}}$$ with the block cipher in CBC mode (see modes ofoperation) using the leftmost MAC Session Key block $$K_{{\rm SL}}$$: * $${H}_{{i}} := {\rm ALG}({K}_{{\rm SL}})[{X}_{{i}} \oplus {H}_{{i} - 1}], {\rm for } i = 1, 2, \ldots, {k}$$ * with initial value $$H_{0}$$ := (‘00’ ‖ ‖ ‘00’ ‖ ‖ ‘00’ ‖ ‖ ‘00’ ‖ ‖ ‘00’ ‖ ‖ ‘00’ ‖ ‖ ‘00’ ‖ ‖ ‘00’). * Compute the 8-byte block $$H_{{k} + 1}$$ in one of the following two ways: * • According to ISO/IEC 9797-1 Algorithm 1: * $${H}_{{k}+1} := {H}_{{k}}.$$ * • According to Optional Process 1 of ISO/IEC 9797-1 Algorithm 3: * $${H}_{{k}+1} := {\rm ALG}({K}_{{\rm SL}})[{\rm ALG}^{-1}({K}_{{\rm SR}})[{H}_{{k}}]].$$ * The MAC S is then equal to the s most significant bytes of $$H_{{k} + 1}$$. */ IBlockCipher cipher = new DesEngine(); IMac mac = new ISO9797Alg3Mac(cipher, 64, new ISO7816d4Padding()); mac.Init(key); mac.BlockUpdate(data, 0, data.Length); var m = new byte[mac.GetMacSize()]; mac.DoFinal(m, 0); return(m); }
public override void PerformTest() { KeyParameter key = new KeyParameter(keyBytes); IBlockCipher cipher = new DesEngine(); IMac mac = new ISO9797Alg3Mac(cipher); // // standard DAC - zero IV // mac.Init(key); mac.BlockUpdate(input1, 0, input1.Length); byte[] outBytes = new byte[8]; mac.DoFinal(outBytes, 0); if (!AreEqual(outBytes, output1)) { Fail("Failed - expected " + Hex.ToHexString(output1) + " got " + Hex.ToHexString(outBytes)); } // // reset // mac.Reset(); mac.Init(key); for (int i = 0; i != input1.Length / 2; i++) { mac.Update(input1[i]); } mac.BlockUpdate(input1, input1.Length / 2, input1.Length - (input1.Length / 2)); mac.DoFinal(outBytes, 0); if (!AreEqual(outBytes, output1)) { Fail("Reset failed - expected " + Hex.ToHexString(output1) + " got " + Hex.ToHexString(outBytes)); } }
/// <summary> /// /// </summary> /// <param name="data"></param> /// <param name="key"></param> /// <returns></returns> public static byte[] ComputeMacForPersoCryptogram(this byte[] data, KeyParameter key) { IBlockCipher cipher = new DesEdeEngine(); IMac mac = new ISO9797Alg3Mac(cipher, 64, new ISO7816d4Padding()); mac.Init(key); mac.BlockUpdate(data, 0, data.Length); var m = new byte[mac.GetMacSize()]; mac.DoFinal(m, 0); return(m); }
//public byte[] Bytes() //{ // MACTripleDES mac = new MACTripleDES(); // mac.Initialize(); // mac.Padding = PaddingMode.Zeros; // mac.Key = _kMac.Bytes(); // var eIfd = _eIfd.Bytes(); // var mIfd = mac.TransformFinalBlock(eIfd, 0, eIfd.Length); // return mIfd; //} /// <summary> /// C# Implementation of Retail MAC Calculation (ISOIEC 9797-1 MAC algorithm 3) /// http://stackoverflow.com/questions/20312646/c-sharp-implementation-of-retail-mac-calculation-isoiec-9797-1-mac-algorithm-3 /// </summary> /// <returns></returns> //public byte[] Bytes() //{ // var kMAC = _kMac.Bytes(); // var eIfd = _eIfd.Bytes(); // // Split the 16 byte MAC key into two keys // byte[] key1 = new byte[8]; // Array.Copy(kMAC, 0, key1, 0, 8); // byte[] key2 = new byte[8]; // Array.Copy(kMAC, 8, key2, 0, 8); // // Padd the data with Padding Method 2 (Bit Padding) // System.IO.MemoryStream out_Renamed = new System.IO.MemoryStream(); // out_Renamed.Write(eIfd, 0, eIfd.Length); // out_Renamed.WriteByte((byte)(0x80)); // while (out_Renamed.Length % 8 != 0) // { // out_Renamed.WriteByte((byte)0x00); // } // byte[] eIfd_padded = out_Renamed.ToArray(); // // Split the blocks // byte[] d1 = new byte[8]; // byte[] d2 = new byte[8]; // byte[] d3 = new byte[8]; // byte[] d4 = new byte[8]; // byte[] d5 = new byte[8]; // Array.Copy(eIfd_padded, 0, d1, 0, 8); // Array.Copy(eIfd_padded, 8, d2, 0, 8); // Array.Copy(eIfd_padded, 16, d3, 0, 8); // Array.Copy(eIfd_padded, 24, d4, 0, 8); // Array.Copy(eIfd_padded, 32, d5, 0, 8); // DES des1 = DES.Create(); // des1.BlockSize = 64; // des1.Key = key1; // des1.Mode = CipherMode.CBC; // des1.Padding = PaddingMode.None; // des1.IV = new byte[8]; // DES des2 = DES.Create(); // des2.BlockSize = 64; // des2.Key = key2; // des2.Mode = CipherMode.CBC; // des2.Padding = PaddingMode.None; // des2.IV = new byte[8]; // // MAC Algorithm 3 // // Initial Transformation 1 // byte[] h1 = des1.CreateEncryptor().TransformFinalBlock(d1, 0, 8); // // Iteration on the rest of blocks // // XOR // byte[] int2 = new byte[8]; // for (int i = 0; i < 8; i++) // int2[i] = (byte)(h1[i] ^ d2[i]); // // Encrypt // byte[] h2 = des1.CreateEncryptor().TransformFinalBlock(int2, 0, 8); // // XOR // byte[] int3 = new byte[8]; // for (int i = 0; i < 8; i++) // int3[i] = (byte)(h2[i] ^ d3[i]); // // Encrypt // byte[] h3 = des1.CreateEncryptor().TransformFinalBlock(int3, 0, 8); // // XOR // byte[] int4 = new byte[8]; // for (int i = 0; i < 8; i++) // int4[i] = (byte)(h3[i] ^ d4[i]); // // Encrypt // byte[] h4 = des1.CreateEncryptor().TransformFinalBlock(int4, 0, 8); // // XOR // byte[] int5 = new byte[8]; // for (int i = 0; i < 8; i++) // int5[i] = (byte)(h4[i] ^ d5[i]); // // Encrypt // byte[] h5 = des1.CreateEncryptor().TransformFinalBlock(int5, 0, 8); // // Output Transformation 3 // byte[] h5decrypt = des2.CreateDecryptor().TransformFinalBlock(h5, 0, 8); // byte[] mIfd = des1.CreateEncryptor().TransformFinalBlock(h5decrypt, 0, 8); // return mIfd; //} // http://www.programcreek.com/java-api-examples/index.php?api=org.spongycastle.crypto.macs.ISO9797Alg3Mac public byte[] Bytes() { var cipher = new DesEngine(); var macSizeInBits = 64; // 8 in bytes var mac = new ISO9797Alg3Mac(cipher, 64, new ISO7816d4Padding()); KeyParameter keyP = new KeyParameter(_key.Bytes()); mac.Init(keyP); mac.BlockUpdate(_data.Bytes(), 0, _data.Bytes().Length); byte[] _out = new byte[8]; mac.DoFinal(_out, 0); return(_out); }