5

を使用してMACを計算しようとしています

暗号チェックサムは、ISOIEC 9797-1 MAC アルゴリズム 3 を使用して、ブロック暗号 DES、ゼロ IV (8 バイト)、および 1S09797-1 パディング方法 2 を使用して計算されます。MAC の長さは 8 バイトでなければなりません。

ICC 読み取り専用アクセスを提供する Machine Readable Travel Documents の Technical Report PM より リリース : 1.1 日付 : 2004 年 10 月 1 日。

レポートの値の例を使用しています。

ケンチ: 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

次に、「ブロック暗号DES、ゼロIV(8バイト)、および1S09797-1パディング方法2を使用したISO / IEC 9797-1 MACアルゴリズム3」を次のように理解したので、すべてのステップを手動で実行しようとしました:(私はこれに基づいています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

キー 2: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

どちらの場合も、予想どおりに異なっていました。私は何が欠けていますか?

お時間をいただきありがとうございます。

4

3 に答える 3

5

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));
于 2013-12-02T16:31:23.947 に答える
4

少なくともパディング モードがありません。ICAO の技術仕様では、ビット パディング (少なくとも 1 バイトの値、次にブロックの最後に到達するまで801 ~ 7 の値のバイト) を使用します。00

于 2013-12-01T18:30:36.323 に答える
3

コードを共有していただきありがとうございます。それは素晴らしい例です。5 バイトのみではなく、任意のサイズのブロックに対応するようにコードを変更しました。次のコードでは、1 バイトのブロックからブロック内の任意のサイズのバイトまでを使用して、MAC を取得できます。

    private static byte[] getCC_MACNbytes(string Key_MAC, byte[] eIFD, string Init_Vec)
    {
        byte[] Kmac = StringToByteArray(Key_MAC);

        // 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);

        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];

        // 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();
        int N_bytes = eIfd_padded.Length/8;  // Number of Bytes 

        byte[] d1 = new byte[8];
        byte[] dN = new byte[8];
        byte[] hN = new byte[8];
        byte[] intN = new byte[8];

        // MAC Algorithm 3
        // Initial Transformation 1
        Array.Copy(eIfd_padded, 0, d1, 0, 8);
        hN = des1.CreateEncryptor().TransformFinalBlock(d1, 0, 8);

        // Split the blocks
        // Iteration on the rest of blocks
        for (int j = 1; j<N_bytes; j++)
        {
            Array.Copy(eIfd_padded, (8*j), dN, 0, 8);
            // XOR
            for (int i = 0; i < 8; i++)
                intN[i] = (byte)(hN[i] ^ dN[i]);

            // Encrypt
            hN = des1.CreateEncryptor().TransformFinalBlock(intN, 0, 8);
        }

        // Output Transformation 3
        byte[] hNdecrypt = des2.CreateDecryptor().TransformFinalBlock(hN, 0, 8);
        byte[] mIfd = des1.CreateEncryptor().TransformFinalBlock(hNdecrypt, 0, 8);

        //  Get check Sum CC
        return mIfd;
    }
于 2014-11-29T12:59:44.780 に答える