在Parse ISO8583(五)及(六)中,筆記了Natural PIN及PIN Offset運作,前兩種驗證在處理過程中,免不了用正確金鑰計算出正確的密碼值PIN,這因此有了一種過程風險。
為了避免風險,在PIN的驗證上也有PVV(PIN Verification Value),概念很像取雜湊驗證(Hash),但精確度不同。
Wiki上三種PIN的驗證方式,今天筆記第三種: Visa PVV
- IBM 3624: 通常只使用在產生Natural PIN,非常不適合使用在PIN驗證。
- IBM 3624 + PIN-Offset
- Visa PVV: 不是專屬Visa卡使用喔,其他Mastercard、JCB也適用。
PVV Generation Algorithm
1.卡號PAN:11位 + PVKI:1位 + PIN前4位 用PVK金鑰下去做2TDEA運算,
2.依序取出前4位小於10的運算結果,若位數不足,再將超過10的16進位字元除10的餘數補在後方。
- 卡號PAN 11位: 不含最後1位檢查碼,從右邊開始取11位
- PVKI 1位: 0-6 ,用來表示使用哪一組PVK
- PIN 4位: 密碼值的前4位。
算出PVV後,實際PT(PIN Tranaction)時怎麼驗證PIN?
PIN驗證流程主要分成卡片製卡及持卡人進行需要PIN的交易時兩個階段
A.卡片製卡時:
- 會先用卡號PAN:11位 + PVKI:1位 + Natural PIN或動態PIN前4位算PVV。
- 依據ISO7813規格,在磁軌二(Track2)的Discretionary data欄位中分別寫入PVKI(1位)、PVV(4位)。
B.當持卡人進行需要PIN的交易時:
- 前端POS設備或刷卡機會讀取磁軌二(Track2)放在ISO8583 DE35欄位。
- 持卡人輸入的PIN在前端經過初步加密運算成PIN Block,交易傳遞時放在ISO8583 DE52(PIN Block)欄位。
- 後台收到ISO8583後先從DE52 PIN Block還原出持卡人輸入的PIN。
- 後台再拿ISO8583中的卡號PAN:11位 + PVKI:1位 + PIN前4位 用PVK金鑰下去做2TDEA運算,算出PVV
- 驗算步驟(4)算出的PVV是否與ISO8583 DE35 磁軌二中的PVV相符。
小結:
- 即使卡片被側錄(skimming),密碼還是必須正確才能提款(withdraw)或進行其他需要PIN的交易。
- 另外除了卡片製卡,在驗證過程中,流程中只算PVV,不會用有"正確的金鑰"計算出"正確的密碼值"的過程風險。
理論筆記完了,來實務計算:
1.準備2TDEA呼叫方法:
輸入兩把PVK(基碼)及卡號(PAN)明文
這一段和先前那篇[.NET][C#]Parse ISO8583筆記(五)Natural PIN內容完全相同!!
參數1是PVKA+PVKB;參數2則是16 Byte的明文資料。
/// <summary>
/// 輸入16位KEY byte[]及明文byte[]進行加密
/// </summary>
/// <param name="key"></param>
/// <param name="plaintext"></param>
/// <returns></returns>
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();
}
2.寫一段組成明文並執行測試的方法
明文項目 | 明文組成 |
PAN | 1234567899876543 |
PVKI | 1 |
PIN | 1234 |
[TestMethod]
public void TesPVVGen()
{
//Visa Methid PVV(PVKI:1 PIN:1234)
//PVKA + PVKB
string Deskey = "0123456789ABCDEFFEDCBA9876543210";
//含PIN的明文資料 (卡號:11位 + PVKI:1位 + PIN前4位)
string plainText = "5678998765411234";
//取得加密演算結果
byte[] b = Encryption(Deskey.HexToByte(), plainText.HexToByte());
List<int> hexInt = new List<int>();
//依序取出小於10的數字並保留大於10的數字(ABCDEF)在小於10的數字區塊右方
for (int i = 0; i < b.BToHex().Length; i++)
{
int p = Convert.ToInt32(b.BToHex().Substring(i, 1), 16);
if (p < 10)
{
Console.WriteLine("PVV(number) Value: {0} ", p);
}
else
{
hexInt.Add(p % 10);
}
}
foreach (int p in hexInt)
{
Console.WriteLine("PVV(hex) Value: {0} ", p);
}
}
3.測試結果: 依序取出前4位數值,PVV值就是9365
4.用BP-Tools驗算(eftlab網站)
PVV值也是9365!!!
小結:
- 根據ISO7813,通常PVV都會錄製在磁軌二中,變更密碼時也會重新錄製在磁條。
- 國外也有儲存在資料庫中的作法,好在PCI DSS也沒有特別的規定,卡片真偽還是可以使用CVV驗證。
參考:
Personal identification number
Discretionary data from magnetic strip credit card, how to parse?
ISO7811、ISO7813、ISO8583