日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > Android >内容正文

Android

c语言读写nfc,Android NFC M1卡读写芯片卡读写(CPU卡读写)(RFID读写)

發(fā)布時(shí)間:2024/7/19 Android 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 c语言读写nfc,Android NFC M1卡读写芯片卡读写(CPU卡读写)(RFID读写) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

版權(quán)聲明:本文為博主原創(chuàng)文章,遵循 CC 4.0 by-sa 版權(quán)協(xié)議,轉(zhuǎn)載請(qǐng)附上原文出處鏈接和本聲明。

本文鏈接:https://blog.csdn.net/sgn5200/article/details/82855478

Android NFC M1卡讀寫&芯片卡讀寫(CPU卡讀寫)(RFID讀寫)

NFC 讀寫分幾種,本文主要講M1卡扇區(qū)讀寫和芯片卡讀寫

權(quán)限

初始化

1 onCreate( initNFC() )

2 onResume( )

3 onPause()

4 NFC設(shè)備刷卡時(shí)觸發(fā) onNewIntent(Intent)

1,標(biāo)簽讀寫

2,扇區(qū)讀寫

3 CPU卡讀寫 重頭戲

NFC 讀寫分幾種,本文主要講M1卡扇區(qū)讀寫和芯片卡讀寫

NFC 標(biāo)簽讀寫

NFC 扇區(qū)讀寫

NFC 文件讀寫

權(quán)限

android:name="android.hardware.nfc"

android:required="true"/>

1

2

3

4

5

1

2

3

4

5

6

7

8

初始化

在Activity#onCreate()注冊(cè),在Activity#onResume()開啟前臺(tái)調(diào)度系統(tǒng),在Activity#onPause退出前臺(tái)調(diào)度。

1

1 onCreate( initNFC() )

private void initNFC() {

// 獲取nfc適配器,判斷設(shè)備是否支持NFC功能

nfcAdapter = NfcAdapter.getDefaultAdapter(this);

if (nfcAdapter == null) {

shotToast("當(dāng)前設(shè)備不支持NFC功能");

} else if (!nfcAdapter.isEnabled()) {

shotToast("NFC功能未打開,請(qǐng)先開啟后重試!");

}

pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this,

getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);

IntentFilter ndef = new IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED);

ndef.addCategory("*/*");

// 允許掃描的標(biāo)簽類型

mWriteTagFilters = new IntentFilter[]{ndef};

mTechLists = new String[][]{

new String[]{MifareClassic.class.getName()},

new String[]{NfcA.class.getName()}};// 允許掃描的標(biāo)簽類型

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

2 onResume( )

@Override

protected void onResume() {

super.onResume();

//開啟前臺(tái)調(diào)度系統(tǒng)

nfcAdapter.enableForegroundDispatch(this, pendingIntent, mWriteTagFilters, mTechLists);

}

1

2

3

4

5

6

3 onPause()

@Override

protected void onPause() {

super.onPause();

nfcAdapter.disableForegroundDispatch(this);

}

1

2

3

4

5

4 NFC設(shè)備刷卡時(shí)觸發(fā) onNewIntent(Intent)

給偽代碼,詳細(xì)見下面3點(diǎn)分解

1

@Override

protected void onNewIntent(Intent intent) {

super.onNewIntent(intent);

//當(dāng)該Activity接收到NFC標(biāo)簽時(shí),運(yùn)行該方法

if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction()) ||

NfcAdapter.ACTION_TECH_DISCOVERED.equals(intent.getAction())) {

Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);

1,標(biāo)簽讀寫

Ndef ndef = Ndef.get(tag);//如果ndef為空表示不支持該格式

//可進(jìn)行格式 如果格式化失敗則不能只能換個(gè)方式

2,M1 扇區(qū)讀寫

MifareClassic mfc = MifareClassic.get(tag);//CPU卡時(shí) mfc將為空

3,CPU卡 讀寫

NfcCpuUtilsnfc = new NfcCpuUtils(IsoDep.get(tag));

}

}

1,標(biāo)簽讀寫

/**

* 寫標(biāo)簽

* @param ndef

* @param tag

* @param ndefMessage

* @return

* @throws IOException

* @throws FormatException

*/

private boolean writeMsg(Ndef ndef, Tag tag, NdefMessage ndefMessage) throws IOException, FormatException {

try {

if (ndef == null) {

shotToast("格式化數(shù)據(jù)開始");

//Ndef格式類

NdefFormatable format = NdefFormatable.get(tag);

format.connect();

format.format(ndefMessage);

} else {

shotToast("寫入數(shù)據(jù)開始");

//數(shù)據(jù)的寫入過程一定要有連接操作

ndef.connect();

ndef.writeNdefMessage(ndefMessage);

}

return true;

} catch (IOException e) {

e.printStackTrace();

shotToast("IO異常,讀寫失敗");

} catch (FormatException e) {

e.printStackTrace();

shotToast("格式化異常,讀寫失敗");

} catch (NullPointerException e) {

shotToast("格NullPointerException異常,讀寫失敗");

}catch (IllegalStateException e){

shotToast("Close other technology first!");

}

return false;

}

/**

* 讀取NFC標(biāo)簽文本數(shù)據(jù)

*/

private void readNfcTag(Intent intent) {

if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())||

NfcAdapter.ACTION_TECH_DISCOVERED.equals(intent.getAction())) {

Parcelable[] rawMsgs = intent.getParcelableArrayExtra(

NfcAdapter.EXTRA_NDEF_MESSAGES);

NdefMessage msgs[] = null;

int contentSize = 0;

if (rawMsgs != null) {

msgs = new NdefMessage[rawMsgs.length];

for (int i = 0; i < rawMsgs.length; i++) {

msgs[i] = (NdefMessage) rawMsgs[i];

contentSize += msgs[i].toByteArray().length;

}

}

try {

if (msgs != null) {

print(msgs.length+" 長(zhǎng)度");

NdefRecord record = msgs[0].getRecords()[0];

String textRecord = parseTextRecord(record);

mTagText += textRecord + "\n\ntext\n" + contentSize + " bytes";

print(mTagText);

}

} catch (Exception e) {

}

}

}

1

2,扇區(qū)讀寫

M1扇區(qū)默認(rèn)是沒有密碼的,但有部分人閑不住要把密碼改了,因此認(rèn)證過程要加密碼,一般認(rèn)證KeyA就行。普通卡16個(gè)扇區(qū)64塊,第一個(gè)扇區(qū)等閑不能操作。每個(gè)扇區(qū)4塊,從0數(shù)起,第二扇區(qū)第一塊索引就是8,每個(gè)扇區(qū)前3塊存數(shù)據(jù)最后一塊一般存密碼。實(shí)例代碼讀的是2扇區(qū)8塊。

/**

* 扇區(qū)寫

* @param tag

* @param sectorIndex 扇區(qū)索引 一般16個(gè)扇區(qū) 64塊

* @return

*/

public boolean writeTAG(Tag tag,int sectorIndex) {

MifareClassic mfc = MifareClassic.get(tag);

try {

mfc.connect();

if (mfc.authenticateSectorWithKeyA(sectorIndex, new byte[]{0x42,0x53,0x4B, (byte) sectorIndex,0x4C,0x53})) { //已知密碼認(rèn)證 r

// the last block of the sector is used for KeyA and KeyB cannot be overwritted

int block = mfc.sectorToBlock(sectorIndex);

mfc.writeBlock(block, "sgn-old000000000".getBytes());

mfc.close();

shotToast("舊卡 寫入成功");

return true;

}else if(mfc.authenticateSectorWithKeyA(sectorIndex, MifareClassic.KEY_NFC_FORUM)){ //新卡 未設(shè)密碼認(rèn)證 r

int block = mfc.sectorToBlock(sectorIndex);

mfc.writeBlock(block, "SGN-new000000000".getBytes());

mfc.close();

shotToast("新卡 寫入成功");

} else{

shotToast("未認(rèn)證");

}

} catch (IOException e) {

e.printStackTrace();

shotToast("扇區(qū)連接異常");

try {

mfc.close();

} catch (IOException e1) {

e1.printStackTrace();

}

}

return false;

}

/**

* 讀扇區(qū)

* @return

*/

private String readTag(Tag tag,MifareClassic mfc,int sectorIndex){

for (String tech : tag.getTechList()) {

System.out.println("------------"+tech);

}

//讀取TAG

try {

String metaInfo = "";

//Enable I/O operations to the tag from this TagTechnology object.

mfc.connect();

int type = mfc.getType();//獲取TAG的類型

int sectorCount = mfc.getSectorCount();//獲取TAG中包含的扇區(qū)數(shù)

String typeS = "";

switch (type) {

case MifareClassic.TYPE_CLASSIC:

typeS = "TYPE_CLASSIC";

break;

case MifareClassic.TYPE_PLUS:

typeS = "TYPE_PLUS";

break;

case MifareClassic.TYPE_PRO:

typeS = "TYPE_PRO";

break;

case MifareClassic.TYPE_UNKNOWN:

typeS = "TYPE_UNKNOWN";

break;

}

metaInfo += "卡片類型:" + typeS + "\n共" + sectorCount + "個(gè)扇區(qū)\n共" + mfc.getBlockCount() + "個(gè)塊\n存儲(chǔ)空間: " + mfc.getSize() + "B\n";

int blockIndex;

if (mfc.authenticateSectorWithKeyA(sectorIndex, new byte[]{0x42,0x53,0x4B, (byte) sectorIndex,0x4C,0x53}) ) {

blockIndex = mfc.sectorToBlock(sectorIndex);

byte[] data = mfc.readBlock(blockIndex);

metaInfo += "舊卡 Block " + blockIndex + " : " + new String(data) + "\n";

}else if( mfc.authenticateSectorWithKeyA(sectorIndex, MifareClassic.KEY_NFC_FORUM)){

blockIndex = mfc.sectorToBlock(sectorIndex);

byte[] data = mfc.readBlock(blockIndex);

metaInfo += "新卡 Block " + blockIndex + " : " + new String(data) + "\n";

}else {

metaInfo += "Sector " + sectorIndex + ":驗(yàn)證失敗\n";

}

return metaInfo;

} catch (Exception e) {

Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG).show();

e.printStackTrace();

} finally {

if (mfc != null) {

try {

mfc.close();

} catch (IOException e) {

Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG)

.show();

}

}

}

return null;

}

99

3 CPU卡讀寫 重頭戲

先直接上代碼,看完代碼在說吧,搞這個(gè)有點(diǎn)心力疲憊。

下面是一個(gè)寫的完全流程,if的嵌套我承認(rèn)有點(diǎn)low,但有助于流程理解。

這里要說下外部認(rèn)證過程:

devices -----獲取4字節(jié)隨機(jī)數(shù)---------------------> cpu 卡

devices

四個(gè)字節(jié)隨機(jī)數(shù)+四個(gè)字節(jié)0 使用密鑰進(jìn)行DES加密,如果是8個(gè)隨機(jī)數(shù)DES3加密。

將命令00 82 00 00 08 以及加密后的隨機(jī)數(shù)取前8位 7f cf 90 a0 5b 9c f1 73發(fā)送

devices ----00 82 00 00 08 7f cf 90 a0 5b 9c f1 73–>cpu 卡

devices

/**

* Description : cpu卡寫的工具類 命令返回90 00 表示成功

* CreateAuthor: Cannan

* CreateTime : 2018/9/22 18:53

* Project : TestNFC

*/

public class NfcCpuUtils {

/**

* 1. 在“COS命令框”輸入“00A40000023F00”,然后點(diǎn)擊“發(fā)送命令”,進(jìn)入主目錄

*/

private final byte[] CMD_START = new byte[]{0x00, (byte) 0xA4, 0x00, 0x00, 0x02, 0x3F, 0x00}; //6f,15,84,e,31,50,41,59,2e,53,59,53,2e,44,44,46,30,31,a5,3,88,1,1,90,0,

/**

* 2. 復(fù)合外部認(rèn)證(秘鑰:FFFFFFFFFFFFFFFF,秘鑰標(biāo)識(shí)號(hào):00)

*/

private byte[] CMD_KEY = {(byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF};

/**

* 2.1 獲取4位 隨機(jī)碼 {0x00, (byte) 0x84, 0x00, 0x00, 0x04}

*/

private final byte[] CMD_GET_RANDOM = {0x00, (byte) 0x84, 0x00, 0x00, 0x04};

private final byte[] CMD_DEL = {(byte) 0x80, 0x0E, 0x00, 0x00, 0x00}; //3.刪除主目錄下的所有文件:800E000000(注意:這個(gè)命令會(huì)刪除主目錄下的所有文件)

// 4. 建立外部認(rèn)證秘鑰 4.1選擇根目錄(00A4000000)

// 4.2建密鑰文件 (80 E0 00 00 07 3F 00 B0 01 F0 FF FF

// 4.3創(chuàng)建外部認(rèn)證密鑰 (80 D4 01 00 0D 39 F0F0 AA 55 FFFFFFFFFFFFFFFF)

private final byte[] CMD_CREATE_DIR = {0x00, (byte) 0xA4, 0x00, 0x00, 0x02,0x3f,0x00};

private final byte[] CMD_CREATE_KEY = {(byte) 0x80, (byte) 0xE0, 0x00, 0x00, 0x07, 0x3F, 0x00, (byte) 0xB0, 0x01, (byte) 0xF0, (byte) 0xFF, (byte) 0xFF};

private final byte[] CMD_CREATE_OUT_KEY = {(byte) 0x80, (byte) 0xD4, (byte) 0x01, (byte) 0x00, (byte) 0x0D, (byte)0x39, (byte) 0xF0, (byte) 0xF0, (byte) 0xAA

, (byte) 0x55, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF};

//5 建立訪問自定義文件的密鑰文件

private final byte[] CMD_ACCESS = {(byte) 0x80, (byte) 0xE0, (byte) 0x00, (byte) 0x01, (byte) 0x07, (byte) 0x3F, (byte) 0x01, (byte) 0x8F, (byte) 0x95, (byte) 0xF0, (byte) 0xFF, (byte) 0xFF};

// 填充密鑰123456

private final byte[] CMD_ACCESS_INTO = {(byte) 0x80, (byte) 0xD4, (byte) 0x01, (byte) 0x01, (byte) 0x08, (byte) 0x3A, (byte) 0xF0, (byte) 0xEF, (byte) 0x44, (byte) 0x55, (byte) 0x12, (byte) 0x34, (byte) 0x56};

//6. 創(chuàng)建自定義文件,標(biāo)識(shí)為005(80E000050728000FF4F4FF02)

private final byte[] CMD_ACCESS_FILE = {(byte) 0x80, (byte) 0xE0, (byte) 0x00, (byte) 0x05, (byte) 0x07, (byte) 0x28, (byte) 0x00, (byte) 0x0F, (byte) 0xF4, (byte) 0xF4, (byte) 0xFF, (byte) 0x02};

//7.寫數(shù)據(jù)到文件標(biāo)識(shí)為0005的文件

//7.1選中該文件(00A40000020005)

// 7.2寫數(shù)據(jù)“112233445566”到該文件(00D6000006112233445566)

private final byte[] CMD_ACCESS_FILE_CHOOICE = {(byte) 0x00, (byte) 0xA4, (byte) 0x00, (byte) 0x00, (byte) 0x02, (byte) 0x00, (byte) 0x05};

private final byte[] CMD_ACCESS_FILE_WRITE = {(byte) 0x00, (byte) 0xD6, (byte) 0x00, (byte) 0x00, (byte) 0x06, (byte) 0x88, (byte) 0x88, (byte) 0x88, (byte) 0x44, (byte) 0x55, (byte) 0x66};

// 聲明ISO-DEP協(xié)議的Tag操作實(shí)例

private final IsoDep tag;

public NfcCpuUtils(IsoDep tag) throws IOException {

// 初始化ISO-DEP協(xié)議的Tag操作類實(shí)例

this.tag = tag;

tag.setTimeout(5000);

tag.connect();

}

public byte[] wirte() throws IOException {

byte[] resp = tag.transceive(CMD_START); //1 進(jìn)入主目錄

if (checkRs(resp)) {

print("1 進(jìn)入主目錄成功");

resp = tag.transceive(CMD_GET_RANDOM); //2 獲取隨機(jī)碼

if (checkRs(resp)) {

print("2 獲取隨機(jī)碼");

byte[] random = {resp[0], resp[1], resp[2], resp[3], 0x00, 0x00, 0x00, 0x00};//3 隨機(jī)碼4個(gè)字節(jié)+4個(gè)字節(jié)0

byte[] desKey;

try {

desKey = encrypt(random, CMD_KEY); //4 生產(chǎn)加密后的隨機(jī)碼

print("3 生產(chǎn)加密后的隨機(jī)碼");

printByte(desKey);

} catch (Exception e) {

e.printStackTrace();

desKey = null;

}

//00 82 00 00 08 7f cf 90 a0 5b 9c f1 73

if (desKey != null && desKey.length > 8) {

byte[] respondKey = {0x00, (byte) 0x82, 0x00, 0x00, 0x08, desKey[0], desKey[1], desKey[2], desKey[3], desKey[4], desKey[5], desKey[6], desKey[7]};

print("4 生產(chǎn)加密后的隨機(jī)碼命令");

printByte(respondKey);

resp = tag.transceive(respondKey); //5 將加密后的隨機(jī)碼發(fā)送,注意此處第四字節(jié)表示密碼標(biāo)識(shí)符00,

}

if (checkRs(resp)) {

print("5 外部認(rèn)證成功");

resp = tag.transceive(CMD_DEL);

if (checkRs(resp)) {

print("6 刪除目錄成功");

resp = tag.transceive(CMD_CREATE_DIR);

if (checkRs(resp)) {

print("7 選擇目錄");

resp = tag.transceive(CMD_CREATE_KEY);

if (checkRs(resp)) {

print("8 建立目錄");

resp = tag.transceive(CMD_CREATE_OUT_KEY);

if (checkRs(resp)) {

print("9 創(chuàng)建外部認(rèn)證密鑰成功");

resp = tag.transceive(CMD_ACCESS);

if (checkRs(resp)) {

print("10 建立訪問自定義文件的密鑰文件成功");

resp = tag.transceive(CMD_ACCESS_INTO); //11 填充密鑰123456

if (checkRs(resp)) {

print("11 填充密鑰123456成功");

resp = tag.transceive(CMD_ACCESS_FILE); //12 創(chuàng)建自定義文件,標(biāo)識(shí)為005

if (checkRs(resp)) {

print("12 創(chuàng)建自定義文件,標(biāo)識(shí)為005成功");

resp = tag.transceive(CMD_ACCESS_FILE_CHOOICE); // 13 選中該文件0005

if (checkRs(resp)) {

print(" 13 選中該文件0005成功");

resp = tag.transceive(CMD_ACCESS_FILE_WRITE); //14 寫數(shù)據(jù)“112233445566”到該文件

if (checkRs(resp)) { //15 應(yīng)該有關(guān)閉連接

print("14 寫數(shù)據(jù)“112233445566”到該文件成功");

return "01".getBytes();

}

}

}

}

}

}

}

}

}

}

}

}

return null;

}

private boolean checkRs(byte[] resp) {

String r = printByte(resp);

Log.i("---------", "response " + r);

int status = ((0xff & resp[resp.length - 2]) << 8) | (0xff & resp[resp.length - 1]);

return status == 0x9000;

}

private String printByte(byte[] data) {

StringBuffer bf = new StringBuffer();

for (byte b : data) {

bf.append(Integer.toHexString(b & 0xFF));

bf.append(",");

}

Log.i("TAG", bf.toString());

return bf.toString();

}

private void print(String msg) {

Log.i("TAG", msg);

}

/**

* Description 根據(jù)鍵值進(jìn)行加密

* 隨機(jī)碼4個(gè)字節(jié)+4個(gè)字節(jié)0

*

* @param data

* @param key 加密鍵byte數(shù)組

* @return

* @throws Exception

*/

public byte[] encrypt(byte[] data, byte[] key) throws Exception {

}

}

注意接收和處理返回的信息,CPU卡常用的APDU指令

參考文獻(xiàn):很多博客,記不得了,RFID多功能讀卡器說明

https://blog.csdn.net/qq_34075348/article/details/77877306

FMCOS2.0用戶手冊(cè) 50-70

如果需要源碼:下載地址https://download.csdn.net/download/sgn5200/10688898

————————————————

版權(quán)聲明:本文為CSDN博主「豆湯包谷飯」的原創(chuàng)文章,遵循CC 4.0 by-sa版權(quán)協(xié)議,轉(zhuǎn)載請(qǐng)附上原文出處鏈接及本聲明。

原文鏈接:https://blog.csdn.net/sgn5200/article/details/82855478

總結(jié)

以上是生活随笔為你收集整理的c语言读写nfc,Android NFC M1卡读写芯片卡读写(CPU卡读写)(RFID读写)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。