[.NET][C#]Parse ISO8583筆記(二)MAC計算

ISO8583會傳遞許多卡片機密的轉帳授權資訊,為確保並鑑定訊息來源正確性,筆記ISO8583幾種保護機制:

  • MAC(ISO9807、CNS13526)
  • PIN Block(ISO9564-1、CNS13798)
  • ARQC/ARPC

 

先筆記DE[64]MAC,之後再補DE[52]PIN Block及晶片交易驗證。

MAC 全文是Message Authentication Code,訊息驗證碼,有時在銀行會聽到押碼。是一種卡片交易訊息保護的應用,目的:

  1. 確保訊息完整未遭竄改
  2. 鑑定訊息來源的一種驗證碼

Used to validate the source and the text of the message between the sender and receiver (in accordance with ISO 9807).

確保訊息完整未遭竄改也可以用雜湊Hash algorithm計算(MD5、SHA..),但如果竄改後再重算新的Hash,在鑑定訊息來源的保護度還是不夠;在當時的時空用上DES Encryption algorithm,透過一定期間的基碼(Key)交換,使用DEA加密演算法將重要的交易資訊演算出一個驗證碼放到DE64或DE128 Element中提供接收端主機驗證。

先整理需要的參數:

明文範例: (取重要的交易資訊演算,不同地區、代理清算中心或銀行可能選擇的欄位會不同,先舉簡單的案例)

Element DE Length Sample
PAN 02 16H to 8byte 4567890123456789
Process code 03 6H to 3byte 000000
Transaction amount 04 12H to 6byte 000000100000
Trace number 11 6H to 3byte 123456
Tracsaction time 12 6H to 3byte 183020
Padding   0x00 00
  總長 24Byte  

基碼: E6 A1 2F 07 9D 15 C4 37 (假設採CNS13526範例)

MAC演算過程:

1.明文以每8Byte拆解,因為總長24Byte,可以拆解成3段:

#  
S1 4567890123456789
S2 0000000000001000
S3 0012345618302000

2.演算步驟: Des_EN(Des_EN(P1) XOR P2) ~ n times

 IV = 0x00,明文與IV或下一段進行XOR運算後再加密。

# Input XOR XOR Result DEA Result
ALG1 4567890123456789 0000000000000000 4567890123456789 13523C220C2BF2E5
ALG2 13523C220C2BF2E5 0000000000001000 13523C220C2BE2E5 50E3891DE605073E
ALG3 50E3891DE605073E 0012345618302000 50F1BD4BFE35273E 3D584F0A68906875

取最終加密結果前8個或後8個Hex string(3D584F0A)轉4Byte為MAC值,將值放入DE[64] Element (MAC)即可。

程式部分需要XOR、Hex字串轉換及DES演算功能,XOR可以參考這篇Hex string與 Byte轉換參考這篇,DES演算法參考以下:

public static byte[] Encryption(byte[] Deskey, byte[] plainText)
{
    SymmetricAlgorithm desAlg = new DESCryptoServiceProvider();
    //設定基碼
    desAlg.Key = Deskey;
    //加密工作模式:CBC
    desAlg.Mode = CipherMode.CBC;
    //補充字元方式:0
    desAlg.Padding = PaddingMode.Zeros;
    //初始向量IV = 0
    desAlg.IV = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
    ICryptoTransform ict = desAlg.CreateEncryptor(desAlg.Key, desAlg.IV);
    MemoryStream mStream = new MemoryStream();
    CryptoStream cStream = new CryptoStream(mStream, ict, CryptoStreamMode.Write);
    cStream.Write(plainText, 0, plainText.Length);
    cStream.FlushFinalBlock();
    cStream.Close();
    return mStream.ToArray();
}

新增計算MAC的程式碼

public static string MAC(string DesKey, string plainText)
{
    //Block拆解
    List<string> plainTexts = (from Match m in Regex.Matches(plainText, @"\d{16}")
                               select m.Value).ToList();
    //從第1段明文開始
    byte[] CipherText = plainTexts[0].HexToByte();
    for (int i = 0; i < plainTexts.Count; i++)
    {
        //XOR: SKIP第1次IV=0,
        if (i > 0)
        {
            CipherText = XOR(CipherText, plainTexts[i].HexToByte());
        }
        Console.WriteLine("{0} time XOR: {1}", i + 1, CipherText.BToHex());

        //加密
        CipherText = Encryption(DesKey.HexToByte(), CipherText);
        Console.WriteLine("{0} time Encryption: {1}", i + 1, CipherText.BToHex());
    }
    //MAC長度為4
    byte[] MacBytes = new byte[4];
    //取出MAC(這邊假設取前4位)
    Buffer.BlockCopy(CipherText, 0, MacBytes, 0, MacBytes.Length);
    //傳回ASCII字串
    return Encoding.ASCII.GetString(MacBytes);
}

測試方法

string MacValue = MAC("E6A12F079D15C437", "456789012345678900000000000010000012345618302000");
Console.WriteLine("Mac Value: '{0}'", MacValue);

測試結果:

*剛好取出來的ASCII字串有換行符號。

 

小結:

  • 不同區域清算中心或銀行可能有不同細部作法或毋須驗證。
  • 從DES安全性的角度來看,因為基碼太短(56 bit),1999年EFF組織22小時就破解DES基碼,因此定期更新基碼更顯得重要。
  • 大致了解MAC運算機制後,對晶片卡ARQC/ARPC 交易驗證碼演算過程也會更順手。

 

參考:

CNS國家標準

Block cipher mode of operation

DES加密標準

MSDN DESCryptoServiceProvider