[.NET][C#]Parse ISO8583筆記(三)PIN Block

上一篇筆記了MAC的演算法,接下來筆記PIN Block。

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

 

PIN是Personal Identification Number的縮寫而來,中文為個人識別碼,金融業卡片交易應用在ATM或POS外接PIN Pad輸入的個人密碼。

  • 個人密碼是相當隱私的資訊,交易設備在傳輸前就會將PIN以適當的演算法遮蓋及加密起來,也和MAC的運算類似,PIN也用上DES或3DES Encryption algorithm,透過一定期間的工作基碼(Working Key)交換(AWK/IWK),來確保機密資訊的安全性。
  • 發行卡片的金融機構收到ATM/POS端授權請求後再將加密後的密碼解開進行驗證值確認。

在ISO8583中,加密後的密碼區塊放在DE(52) Element中,也稱之為PIN Block,運算方式依照國際ISO9564標準或國家CNS13798標準。

 

 

這邊先筆記加密流程,假設使用ISO9564-1 Format 0標準(ANSI X9.8, VISA-1, and ECI-0)

Step1、Step2明文準備範例:

 

運算元1:PIN字串組

Element Length Sample
ISO9564版本 format 0 1 0
PIN Length(16進位) 1 6
PIN 4-12 123456
Padding(位數不足補F) 2-10 FFFFFFFF
總長 16 06123456FFFFFFFF

運算元2:卡號字串組

Element Length Sample
fIxed character 4 0000
card number(不含檢查碼,從右取12位) 12

4567890123456789

789012345678

總長 16 0000789012345678

3.將PIN字串與卡號字串進行Exclusive OR運算: Clear PIN Block。

Item value
運算元1 06123456FFFFFFFF
運算元2 0000789012345678
XOR結果 06124CC6EDCBA987

肉眼上的安全,但還是不安全,繼續進行加密步驟

4.執行DES加密演算法,這邊假設以2TDEA運算。

 

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

public static byte[] Encryption(byte[] Deskey, byte[] plainText)
{
    SymmetricAlgorithm TdesAlg = new TripleDESCryptoServiceProvider();
    //設定基碼
    TdesAlg.Key = Deskey;
    //加密工作模式:CBC
    TdesAlg.Mode = CipherMode.CBC;
    //補充字元方式:0
    TdesAlg.Padding = PaddingMode.Zeros;
    //初始向量IV = 0
    TdesAlg.IV = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
    ICryptoTransform ict = TdesAlg.CreateEncryptor(TdesAlg.Key, TdesAlg.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();
}

產生PIN Block程式碼

public static string GenPinBlock(string CardNbr, string PIN, string keyA, string KeyB)
{
    //1.運算元1:將PIN依照規範組成16進位數值字串
    //(0)ISO9564 Format version(Format 0固定為0)
    //(1)PIN Length(最長12,超過時截掉後面的)
    //(2)PIN
    //(3)Padding value "F" (Format 0 固定結尾補F)
    string PinPrepare = string.Format("{0}{1}{2}{3}",
                        "0",
                        PIN.Length.ToString("X"),
                        PIN,
                        "".PadRight(16 - 2 - PIN.Length, 'F'));

    //2.運算元2:將PAN依照規範組成16進位數值字串
    //(0)固定0000 
    //(1)卡片卡號PAN(去除檢查碼)
    string CardNumberPrepare = string.Format("{0}{1}",
                        "0000",
                        CardNbr.Right(12, 1));

    //3.進行XOR運算
    byte[] ClearPinBlockByte = XOR(PinPrepare.HexToByte(), CardNumberPrepare.HexToByte());
    //4.進行3DES加密運算
    byte[] EncryptPinBlockByte = Encryption((keyA + KeyB).HexToByte(), ClearPinBlockByte);
    //回傳16進位字串結果
    return EncryptPinBlockByte.BToHex();
}

測試程式碼:

string CardNumber = "4567890123456789";
string ClearPin = "123456";
string KeyA = "1234567890123456";
string KeyB = "0123456789012345";

string PinBlock = GenPinBlock(CardNumber, ClearPin, KeyA, KeyB);

Console.WriteLine("ISO 9564-2 Format 0 (ISO-0) Encrypt"); //與ANSI X9.8相同
Console.WriteLine("===============================");
Console.WriteLine("PAN:              {0}", CardNumber);
Console.WriteLine("Clear PIN:        {0}", ClearPin);
Console.WriteLine("Encrypt PIN block:  {0}", PinBlock);
Console.WriteLine("");

測試結果:

小結:

  • 加密PIN所使用的DEA 基碼需要定期更換,二次世界大戰德國潛艦Enigma密碼機上的每日密碼本
  • 解密流程: 先執行TripleDES解密,解密結果 XOR 運算元2:卡號字串 即可演算回 PIN字串

獵殺U571

 

參考:

TripleDESCryptoServiceProvider 類別

CNS國家標準

Complete list of PIN-blocks

ISO 9564-1, Banking — Personal Identification Number (PIN) management and security — Part 1: Basic
principles and requirements for online PIN handling in ATM and POS systems