Android NFC M1 & card reader chip card reader (CPU card reader) (the RFID reader)

Disclaimer: This article is a blogger original article, follow the CC 4.0 by-sa copyright agreement, reproduced, please attach the original source link and this statement.
This link: HTTPS: //blog.csdn.net/sgn5200/article/details/82855478
the Android the NFC card reader Ml & chip card reader (CPU card reader) (the RFID reader)
the NFC reader several points, herein main sectors M1 card reader and speaks the chip card read-write
permission
initialization
1 the onCreate (initNFC ())
2 onResume ()
. 3 the onPause ()
triggers onNewIntent (Intent) 4 NFC device when the card
1, the tag reader
2, sector read write
3 CPU card reader highlight
NFC reader several points, paper stresses M1 card reader and chip card reader sectors
NFC tag reader
NFC sector read and write
NFC to read and write files

权限
<uses-feature
android:name="android.hardware.nfc"
android:required="true"/>



























void initNFC Private () {
// Get nfc adapter, determining whether the device supports an NFC function
nfcAdapter = NfcAdapter.getDefaultAdapter (the this);
IF (nfcAdapter == null) {
shotToast ( "NFC device does not support this feature");
} the else IF (! nfcAdapter.isEnabled ()) {
shotToast ( "the NFC function is not open, the first open try again!");
}
pendingIntent = PendingIntent.getActivity (the this, 0, the Intent new new (the this,
. getClass ()) addFlags ( Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
the IntentFilter the IntentFilter NDEF new new = (NfcAdapter.ACTION_TECH_DISCOVERED);
ndef.addCategory ( "* / *");
// tag type allow scan
mWriteTagFilters the IntentFilter new new = [] {} NDEF;
mTechLists new new = String [] [] {
new new String [] {MifareClassic.class.getName ()},
new new String [] {NfcA.class.getName ()}}; // tag type allow scan
}
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();
//开启前台调度系统
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 device triggered when card onNewIntent (Intent)
to the pseudo code, for details see below 3:00 decomposition
. 1
@Override
protected void onNewIntent (the Intent Intent) {
super.onNewIntent (Intent);
// if the NFC tag upon receiving Activity , which run
IF (NfcAdapter.ACTION_NDEF_DISCOVERED.equals (intent.getAction ()) ||
NfcAdapter.ACTION_TECH_DISCOVERED.equals (intent.getAction ())) {
the tag tag = intent.getParcelableExtra (NfcAdapter.EXTRA_TAG);
. 1, tag reader write
Ndef ndef = Ndef.get (tag); // if ndef is empty indicates that the corresponding format
// If the format can not only fails to format another embodiment
2, M1 sector write
MifareClassic mfc = MifareClassic.get (tag); // CPU when the card will be empty mfc
3, CPU card reader
NfcCpuUtilsnfc = new new NfcCpuUtils (IsoDep.get (tag));
}
}

. 1, the tag reader
/ **
* tag writing
* @param NDEF
* @param Tag
* @param ndefMessage
* @return
* @throws IOException
* @throws a FormatException
* /
Private Boolean writeMsg (NDEF Ndef, the Tag Tag, NdefMessage ndefMessage) throws IOException, {a FormatException
the try {
IF (NDEF == null) {
shotToast ( "start data format");
// Ndef format class
NdefFormatable = NdefFormatable.get the format (Tag);
format.connect ();
format.format (ndefMessage);
} the else {
shotToast ( "write data start");
writing process // data must be operatively connected
ndef.connect ();
ndef.writeNdefMessage (ndefMessage);
}
return to true;
} the catch (IOException E) {
e.printStackTrace ();
shotToast ( "the IO exception W Fail");
} the catch (a FormatException E) {
e.printStackTrace ();
shotToast ( "abnormal format, read and write failure");
} the catch (a NullPointerException E) {
shotToast ( "a NullPointerException cells, failed to read and write");
} the catch (IllegalStateException E) {
shotToast ( "OTHER Technology First the Close!");
}
return to false;
}


/**
* 读取NFC标签文本数据
*/
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+" 长度");
NdefRecord record = msgs[0].getRecords()[0];
String textRecord = parseTextRecord(record);
mTagText += textRecord + "\n\ntext\n" + contentSize + " bytes";
print(mTagText);
}
} catch (Exception e) {
}
}
}

. 1
2 sector read
M1 sector default is no password, but some people want to change the password restless, so to add a password authentication process, a general authentication KeyA line. Common card 16 sectors 64, the first sector can not operate lightly. Each sector 4, numbered from 0, the index is the second sector of the first block 8, each sector before the data stored in the last 3 is generally a password storage. Examples of codes are read sector 2 8.

/ **
* Write sector
* @param Tag
* @param sectorIndex sector index typically 16 sectors 64
* @return
* /
public Boolean writeTAG (the Tag Tag, int sectorIndex) {
MifareClassic MFC = MifareClassic.get (Tag) ;
the try {
mfc.connect ();
IF (mfc.authenticateSectorWithKeyA (sectorIndex, new new byte [] {0x42,0x53,0x4B, (byte) sectorIndex, 0x4C, 0x53})) {// password known to the authentication R & lt
// The The Block of a SECTOR IS Last Used for KeyA and Not KeyB which CAN BE overwritted
int = mfc.sectorToBlock Block (sectorIndex);
mfc.writeBlock (Block, "SGN-old000000000" .getBytes ());
mfc.close ();
shotToast ( " old card writing success ");
return to true;
} else if (mfc.authenticateSectorWithKeyA (sectorIndex, MifareClassic.KEY_NFC_FORUM)) {// new password authentication card is not R & lt
int = mfc.sectorToBlock Block (sectorIndex);
mfc.writeBlock (Block, "the SGN-new000000000" .getBytes () );
mfc.close ();
shotToast ( "new card successfully written");
} the else {
shotToast ( "unauthenticated");
}
} the catch (IOException E) {
e.printStackTrace ();
shotToast ( "sector attachment abnormal");

try {
mfc.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
return false;
}


/**
* 读扇区
* @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中包含的扇区数
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 + "个扇区\n共" + mfc.getBlockCount() + "个块\n存储空间: " + 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";

the else {}
MetaInfo + = "Sector" + sectorIndex + ": failed \ n validation";
}
return MetaInfo;
} the catch (Exception E) {
Toast.makeText (the this, e.getMessage (), Toast.LENGTH_LONG) the .Show ( );
e.printStackTrace ();
} the finally {
IF (MFC = null) {!
the try {
mfc.close ();
} the catch (IOException E) {
Toast.makeText (the this, e.getMessage (), Toast.LENGTH_LONG)
the .Show ();
}
}
}
return null;
}

99
. 3 highlights the CPU card reader
to directly on the code, the code reading speak, to engage in this bit enervated.
Here is a complete write process, nested if I admit a little low, but it helps to understand the process.
External authentication process here to say:
Devices Get ----- 4-byte random number ---------------------> cpu card
devices <-------- random number +90 00 --------------------- cpu card
four bytes of four byte random number + 0 using DES encryption key, if the random number is 8 DES3 encryption.
The command 0082000008 encrypted and a random number from the former 8 7f cf 90 a0 5b 9c f1 73 transmitting
devices ---- 00 82 00 00 08 7f cf 90 a0 5b 9c f1 73-> cpu card
devices < ------------- 90 00 ---------------------------- cpu card

/ **
* the Description: the CPU card writing tools command returns 9000 indicating success
* CreateAuthor: Cannan
* CreateTime: 2018/9/22 18:53
* Project: TestNFC
* /

public class NfcCpuUtils {

/ **
* 1. "COS command box" Enter "00A40000023F00", then click the "transmission command" into the main directory
* /
Private Final byte [] = CMD_START new 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,
/ **
* The composite external authentication (secret key: FFFFFFFFFFFFFFFF, secret key identification number: 00)
* /
Private byte [] = {CMD_KEY (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF};
/ **
* 4 2.1 obtain random code {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 deletes all files in the home directory:. 800E000000 (Note: this command deletes all files in the main directory)

// 4. Establish external authentication keys 4.1 Select the root directory (00A4000000)
@ 4.2 build key file (3F 80 E0 00 00 07 00 01 F0 FF FF B0
// 4.3 create an external authentication key (80 D4 01 00 0D AA 55 FFFFFFFFFFFFFFFF the FOFO 39)
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};
// build. 5 from the access key file definition file
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};
// fill key 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. create a custom file, identified as 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 // write the data into the document identification file 0005
//7.1 selected the file (00A40000020005)
// 7.2写数据“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 // Declare Tag protocol operation example of
private final IsoDep tag;

NfcCpuUtils public (IsoDep Tag) throws IOException {
// Initialization protocol ISO-DEP Tag action class instance
this.tag = Tag;
tag.setTimeout (5000);
tag.connect ();
}

byte public [] wirte () throws IOException {
byte [] = tag.transceive RESP (CMD_START); // enter the main directory. 1
IF (checkRs (RESP)) {
Print ( "successful access main menu. 1");
RESP = Tag .transceive (CMD_GET_RANDOM); // 2 to obtain random code
IF (checkRs (RESP)) {
Print ( "Get random code 2");
byte [] = {random RESP [0], RESP [. 1], RESP [2] , resp [3], 0x00, 0x00, 0x00, 0x00}; // 3 random code 4 bytes + 4 bytes 0
byte [] DESKey;
the try {
DESKey = the encrypt (random, CMD_KEY); // production. 4 random code encrypted
print ( "random code encryption production after 3");
printByte (DESKey);
} the catch (Exception E) {
e.printStackTrace ();
DESKey = null;
}
// 00 82 00 00 08 7F CF2 73 is A0 5B 9C F1 90
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 after producing the encrypted random code command");
printByte (respondKey);
RESP = tag.transceive (respondKey); //. 5 to transmit the encrypted random code, attention here the fourth byte represent the password identifier 00,
}
IF (checkRs (RESP)) {
Print ( "external authentication success. 5");
RESP = tag.transceive (CMD_DEL);
IF (checkRs (RESP)) {
Print ( "6 directory is removed successfully");
RESP = tag.transceive (CMD_CREATE_DIR);
IF (checkRs (RESP)) {
Print ( "choose the directory. 7");
RESP = tag.transceive (CMD_CREATE_KEY);
IF (checkRs (RESP)) {
Print ( "create the directory. 8");
RESP = tag.transceive (CMD_CREATE_OUT_KEY);
IF (checkRs (RESP)) {
print ( "9 to create an external authentication key success");
RESP = tag.transceive (CMD_ACCESS);
IF (checkRs (RESP)) {
Print ( "10 to establish access from the key file definition file successfully");
RESP = Tag .transceive (CMD_ACCESS_INTO); // 11 filled key 123 456
IF (checkRs (RESP)) {
Print ( "filling key 123456 success. 11");
RESP = tag.transceive (CMD_ACCESS_FILE); // create a custom file 12 is, identified as 005
IF (checkRs (RESP)) {
Print ( "12 to create a custom file, identified as 005 successful");
RESP = tag.transceive (CMD_ACCESS_FILE_CHOOICE); // select the file 13 0005
IF (checkRs (RESP)) {
print ( "0005 to select the file 13 is successfully");
RESP = tag.transceive (CMD_ACCESS_FILE_WRITE); 14 // write data "112233445566" to the file
if (checkRs (resp)) { // 15 should close the connection
print ( "14 write data" 112233445566 "to the file successfully");
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);
}

/ **
* based on a key to encrypt the Description
* random code 4 bytes + 4 bytes 0
*
* @param Data
* @param Key encryption key byte array
* @return
* @throws Exception
* /
public byte [] the encrypt (byte [] Data, byte [] Key) throws Exception {
}
}

https://blog.csdn.net/sgn5200/article/details/82855478


Note receiving and processing the information returned, CPU cards commonly used command APDU
References: Many blog, remember, the RFID card reader described
https://blog.csdn.net/qq_34075348/article/details/77877306
FMCOS2. 0 user's Manual 50-70
If you need the source code: Download https://download.csdn.net/download/sgn5200/10688898
----------------
Disclaimer: This article is CSDN blog master "bean soup with corn meal 'original article, follow the CC 4.0 by-sa copyright agreement, reproduced, please attach the original source link and this statement.
Original link: https: //blog.csdn.net/sgn5200/article/details/82855478

Guess you like

Origin www.cnblogs.com/Alex80/p/11367060.html