我正在尝试使用计算MAC
使用ISOIEC 9797-1 MAC算法3和分组密码DES,零IV(8字节)和1S09797-1填充方法2计算密码校验和.MAC长度必须是8字节
来自技术报告PM的机读旅行证件提供ICC只读访问版本:1.1日期:2004年10月1日.
我正在使用报告中的示例值:
Kenc:AB 94 FD EC F2 67 4F DF B9 B3 91 F8 5D 7F 76 F2
Kmac:79 62 D9 EC E0 3D 1A CD 4C 76 08 9D CE 13 15 43
eIFD:72 C2 9C 23 71 CC 9B DB 65 B7 79 B8 E8 D3 7B 29 EC C1 54 AA 56 A8 79 9F AE 2F 49 8F 76 ED 92 F2
但是,我没有得到相同的MAC,也不确定我需要怎么做.我的第一次尝试是:
MACTripleDES mac = new System.Security.Cryptography.MACTripleDES(Kmac); mac.Initialize(); mac.Padding = PaddingMode.None; mac.Key = Kmac; mIfd = mac.TransformFinalBlock(eIfd, 0, eIfd.Length);
结果:
mIFD:1C DE 09 70 4C 0D 9B 12
预期:
mIFD:5F 14 48 EE A8 AD 90 A7
然后我尝试手动完成每一步,因为我理解"ISO/IEC 9797-1 MAC算法3使用分组密码DES,零IV(8字节)和1S09797-1填充方法2",具有以下内容:(我基于此Rasmus Faber的答案,但是将数据拆分为64位块以进行迭代步骤)
byte[] key1 = new byte[8]; Array.Copy(kMAC, 0, key1, 0, 8); byte[] key2 = new byte[8]; Array.Copy(kMAC, 8, key2, 0, 8); Console.WriteLine("key1:{0}", Hex.BytesToSpacedHexString(key1)); Console.WriteLine("key2:{0}", Hex.BytesToSpacedHexString(key2)); // Plit the blocks byte[] d1 = new byte[8]; byte[] d2 = new byte[8]; byte[] d3 = new byte[8]; byte[] d4 = new byte[8]; Array.Copy(eIfd, 0, d1, 0, 8); Array.Copy(eIfd, 8, d2, 0, 8); Array.Copy(eIfd, 16, d3, 0, 8); Array.Copy(eIfd, 24, d4, 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); // Output Transformation 3 byte[] h4decrypt = des2.CreateDecryptor().TransformFinalBlock(h4, 0, 8); mIfd = des1.CreateEncryptor().TransformFinalBlock(h4decrypt, 0, 8); Console.WriteLine("mIFD:{0}", Hex.BytesToSpacedHexString(mIfd));
输出是:
eIFD:72 C2 9C 23 71 CC 9B DB 65 B7 79 B8 E8 D3 7B 29 EC C1 54 AA 56 A8 79 9F AE 2F 49 8F 76 ED 92 F2
key1:79 62 D9 EC E0 3D 1A CD
key2:4C 76 08 9D CE 13 15 43
结果:
mIFD:AA E3 F3 51 32 ED 34 65
预期:
mIFD:5F 14 48 EE A8 AD 90 A7
在这两种情况下,它都与预期的不同.我错过了什么?
感谢您的时间.
感谢owlstead,诀窍是即使数据字符串正好是32个字节,也必须填充.对于需要完整代码的人.MAC哈希的代码
eIFD:72 C2 9C 23 71 CC 9B DB 65 B7 79 B8 E8 D3 7B 29 EC C1 54 AA 56 A8 79 9F AE 2F 49 8F 76 ED 92 F2
数据字符串如下所示:
// 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); Console.WriteLine("key1:{0}", Hex.BytesToSpacedHexString(key1)); Console.WriteLine("key2:{0}", Hex.BytesToSpacedHexString(key2)); // 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(); Console.WriteLine("eIfd_padded:{0}", Hex.BytesToSpacedHexString(eIfd_padded)); // 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); Console.WriteLine("mIFD:{0}", Hex.BytesToSpacedHexString(mIfd));