今天記錄一下Android 非接觸式M1卡是怎麼樣改預設密碼的,因為這幾天剛好幫公司撸了一下,希望能對做NFC開發這一塊的兄弟們有所幫助。首先我們先要了解一下為什麼要M1卡的基本構造和相關說明,這裡我推薦看業餘代碼工作者的blog,感謝他的分享。
了解完M1卡的基本構造和相關說明後,知道了M1卡有16個扇區,每個扇區的最後一塊是記錄KeyA和KeyB還有控制位的。KeyA和KeyB的預設密碼都是ffffffffffff,其中KeyA在所有情況下都是不可讀的(大多數寫機程式裡顯示的是000000000000)。是以使用預設的密碼的M1卡很容易被人模拟,就有了修改預設密碼的需求。
要修改密碼我們首先要知道存放密碼的是哪一塊結構?是怎麼樣的結構?
首先我解答一下上面的問題: M1卡存放密碼大多數都是在 每一扇區的最後一塊,結構是000000000000FF078069ffffffffffff。前12位是是KeyA,中間8位位控制位,後12位為KeyB。
我現在的需求是根據KeyB來檢驗密碼,是以我要修改的就是KeyB的密碼。這裡要注意一下了,在修改之前一定要先修改控制位為(08 77 8F 69),要怎麼修改呢?我們先去查找廠家給的SDK裡面的write和read這兩個函數。然後我們先通過調用SDK的mifare.authenticate()這個方法去校驗扇區的預設密碼,通過後便可調用read()方法讀取扇區的資料,接下來就是調用write()方法把我們要修改的資料寫進去。這裡記得是先修改控制位再去修改密碼,順序不要錯了,不然可能會有其他問題。
msgBuffer.delete(0, msgBuffer.length());
msgBuffer.append("尋到Mifare卡->UID:").append(mifare.uidToString()).append("\r\n");
msgBuffer.append("開始驗證第1塊密碼\r\n");
handler.sendEmptyMessage(0);
byte[] key = {(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff};
try {
boolean anth = mifare.authenticate((byte) 0x11, Mifare.MIFARE_KEY_TYPE_A, key);
if (anth) {
byte[] readDataBytes ;
readDataBytes = mifare.read((byte) 0x11);
msgBuffer.append("塊11資料:").append(StringTool.byteHexToSting(readDataBytes)).append("\r\n");
handler.sendEmptyMessage(0);
msgBuffer.append("驗證密碼成功\r\n");
msgBuffer.append("寫213496578320到塊1\r\n");
// handler.sendEmptyMessage(0);
// boolean isSuc = mifare.write((byte)0x11, new byte[]{0x22, 0x11, 0x22, 0x44, 0x66, 0x11, 0x22, 0x77, (byte) 0x88, (byte) 0x99, 0x22, 0x55, 0x66, 0x33, 0x44, 0x55});
// boolean isSuc = mifare.write((byte)(3&0xFF),new byte[]{(byte) 0xff,(byte) 0xff,(byte) 0xff,(byte) 0xff,(byte) 0xff,(byte) 0xff,0x08,0x77, (byte) 0x8f,0x69, (byte) 0x11,(byte) 0xff,(byte) 0xff,(byte) 0xff,(byte) 0xff,(byte) 0xff});
// if (isSuc) {
// msgBuffer.append("寫成功!\r\n");
// msgBuffer.append("讀塊1資料\r\n");
// handler.sendEmptyMessage(0);
byte[] readDataBytes1 = mifare.read((byte) 0x13);
msgBuffer.append("塊1資料:").append(StringTool.byteHexToSting(readDataBytes1)).append("\r\n");
handler.sendEmptyMessage(0);
// } else {
// msgBuffer.append("寫失敗!\r\n");
// handler.sendEmptyMessage(0);
// return false;
// }
}
else {
msgBuffer.append("驗證密碼失敗\r\n");
handler.sendEmptyMessage(0);
return false;
}
handler.sendEmptyMessage(0);
} catch (CardNoResponseException e) {
e.printStackTrace();
return false;
}
菜鳥代碼勿噴,要是有高手能簡化歡迎留言哈,這樣我們就能修改了一個扇區裡的密碼了。但是一般來說我們都要把每個扇區的每一個密碼都進行修改的,這樣才能在最大限度的保證安全性。這時候我們其實就可以寫一個for循環就好,至于怎麼寫大家可以試試思想是一樣的。
原創連結:https://blog.csdn.net/weixin_40600325/article/details/82856415