ISO8583會傳遞許多卡片機密的轉帳授權資訊,為確保並鑑定訊息來源正確性,筆記ISO8583幾種保護機制:
- MAC(ISO9807、CNS13526)
- PIN Block(ISO9564-1、CNS13798)
- ARQC/ARPC
先筆記DE[64]MAC,之後再補DE[52]PIN Block及晶片交易驗證。
MAC 全文是Message Authentication Code,訊息驗證碼,有時在銀行會聽到押碼。是一種卡片交易訊息保護的應用,目的:
- 確保訊息完整未遭竄改
- 鑑定訊息來源的一種驗證碼
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範例)
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 交易驗證碼演算過程也會更順手。
參考: