零售MAC计算的C#实现(ISOIEC 9797-1 MAC算法3)

 沙尘jr暴的天下 发布于 2023-02-13 16:02

我正在尝试使用计算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

在这两种情况下,它都与预期的不同.我错过了什么?

感谢您的时间.

1 个回答
  • 感谢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));
    

    2023-02-13 16:05 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有