/** * Write all the blocks in a Tag to the Mifare tag. * * @param t * @throws IOException */ public void write(Tag t) throws IOException { if (t.getSectorCount() > mKeys.getSectorCount()) throw new IOException("Too few keys"); mTag.connect(); int sectors = mTag.getSectorCount(); try { for (int s = 0; s < sectors; ++s) { // Authenticate for each sector (try B key, then A key) if (!mTag.authenticateSectorWithKeyB(s, mKeys.getKeyB(s)) && !mTag.authenticateSectorWithKeyA(s, mKeys.getKeyA(s))) throw new IOException("Auth error"); // Write to tag. Skip block 0 and the trailer of each sector int blockOffset = mTag.sectorToBlock(s); int lastBlock = blockOffset + mTag.getBlockCountInSector(s); // Skip block 0 blockOffset = blockOffset == 0 ? 1 : blockOffset; for (int b = blockOffset; b < lastBlock; ++b) { mTag.writeBlock(b, t.getBlock(b)); if (mProgressListener != null) mProgressListener.publishProgress((100 * b) / t.getBlockCount()); } } } finally { mTag.close(); } }
private void resolveIntent(Intent intent) { String action = intent.getAction(); toast("resolving intent"); if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) { toast("RESOLVE THIS INTENT"); Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); receiveTab.append("\nResolve Intent for NDEF discovery"); } else if (NfcAdapter.ACTION_TECH_DISCOVERED.equals(action)) { Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); MifareClassic mfc = MifareClassic.get(tagFromIntent); byte[] data; receiveTab.append("\nNew tech tag received"); try { mfc.connect(); boolean auth = false; String cardData = null; int secCount = mfc.getSectorCount(); int bCount = 0; int bIndex = 0; for (int j = 0; j < secCount; j++) { auth = mfc.authenticateSectorWithKeyA(j, MifareClassic.KEY_DEFAULT); if (auth) { bCount = mfc.getBlockCountInSector(j); bIndex = 0; for (int i = 0; i < bCount; i++) { bIndex = mfc.sectorToBlock(j); data = mfc.readBlock(bIndex); cardData = new String(data); receiveTab.append("\n" + cardData); bIndex++; } } else { Toast.makeText(this, "Auth failed", Toast.LENGTH_LONG).show(); } } } catch (IOException ex) { Toast.makeText(this, "IO Error while attempting to read mifare", Toast.LENGTH_LONG).show(); } } else if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(action)) { receiveTab.append("\nSome Tag found from card"); Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); receiveTab.append("\n" + tagFromIntent.toString()); for (int k = 0; k < tagFromIntent.getTechList().length; k++) { receiveTab.append("\nTech List: " + tagFromIntent.getTechList()[k]); if (tagFromIntent.getTechList()[k].equals("android.nfc.tech.NfcA")) { // Run connection method parseNfcATag(tagFromIntent); // connectToNDEF(tagFromIntent); // parseMifareTag(tagFromIntent); } else if (tagFromIntent.getTechList()[k].equals("android.nfc.tech.Ndef")) { connectToNDEF(tagFromIntent); // receiveTab.append("\nRun connect to NDEF"); } } } }
/** * Set the mapping range for {@link #buildNextKeyMapPart()}. * * @param firstSector Index of the first sector of the key map. * @param lastSector Index of the last sector of the key map. * @return True if range parameters were correct. False otherwise. */ public boolean setMappingRange(int firstSector, int lastSector) { if (firstSector >= 0 && lastSector < mMFC.getSectorCount() && firstSector <= lastSector) { mFirstSector = firstSector; mLastSector = lastSector; // Init. status of buildNextKeyMapPart to create a new key map. mKeyMapStatus = lastSector + 1; return true; } return false; }
/** * Test if all the keys in the KeyChain are valid, i.e. can be used for authenticating. * * @return true if all A and B keys can be used to authenticate, false otherwise. * @throws IOException */ public boolean testKeys() throws IOException { // Tag and key sector count mismatch. // Need at least as many keys as there are sectors. if (mTag.getSectorCount() > mKeys.getSectorCount()) return false; mTag.connect(); try { for (int i = 0; i < mTag.getSectorCount(); ++i) { if (!mTag.authenticateSectorWithKeyA(i, mKeys.getKeyA(i)) || !mTag.authenticateSectorWithKeyB(i, mKeys.getKeyB(i))) { return false; } } } finally { mTag.close(); } return true; }
/** * Read all blocks from the Mifare tag and return the data in a Tag object. * * @return A Tag object containing the data of the Mifare tag. * @throws IOException */ public Tag read() throws IOException { int sectors = mTag.getSectorCount(); Tag t = new Tag(TagType.getType(sectors)); if (t.getSectorCount() > mKeys.getSectorCount()) throw new IOException("Too few keys"); mTag.connect(); try { for (int s = 0; s < sectors; ++s) { byte[] aKey = mKeys.getKeyA(s); byte[] bKey = mKeys.getKeyB(s); // Authenticate for each sector (try A key, then B key) if (!mTag.authenticateSectorWithKeyA(s, aKey) && !mTag.authenticateSectorWithKeyB(s, bKey)) throw new IOException("Auth error"); // Read every block of the sector int blockOffset = mTag.sectorToBlock(s); int lastBlock = blockOffset + mTag.getBlockCountInSector(s); for (int b = blockOffset; b < lastBlock; ++b) { byte[] readBuffer = mTag.readBlock(b); // Manually transfer key data to tag since it is usually not // readable if (b == lastBlock - 1) { for (int i = 0; i < Tag.KEY_SIZE; ++i) { readBuffer[i] = aKey[i]; readBuffer[Tag.BLOCK_SIZE - Tag.KEY_SIZE + i] = bKey[i]; } } t.setBlock(b, readBuffer); if (mProgressListener != null) mProgressListener.publishProgress((100 * b) / t.getBlockCount()); } } return t; } finally { mTag.close(); } }
/** * Write a block of 16 byte data to tag. * * @param sectorIndex The sector to where the data should be written * @param blockIndex The block to where the data should be written * @param data 16 byte of data. * @param key The Mifare Classic key for the given sector. * @param useAsKeyB If true, key will be treated as key B for authentication. * @return The return codes are:<br> * <ul> * <li>0 - Everything went fine. * <li>1 - Sector index is out of range. * <li>2 - Block index is out of range. * <li>3 - Data are not 16 byte. * <li>4 - Authentication went wrong. * <li>-1 - Error while writing to tag. * </ul> * * @see #authenticate(int, byte[], boolean) */ public int writeBlock( int sectorIndex, int blockIndex, byte[] data, byte[] key, boolean useAsKeyB) { if (mMFC.getSectorCount() - 1 < sectorIndex) { return 1; } if (mMFC.getBlockCountInSector(sectorIndex) - 1 < blockIndex) { return 2; } if (data.length != 16) { return 3; } if (!authenticate(sectorIndex, key, useAsKeyB)) { return 4; } // Write block. int block = mMFC.sectorToBlock(sectorIndex) + blockIndex; try { mMFC.writeBlock(block, data); } catch (IOException e) { Log.e(LOG_TAG, "Error while writing block to tag.", e); return -1; } return 0; }
/** * Return the sector count of the Mifare Classic tag. * * @return The sector count of the current tag. */ public int getSectorCount() { return mMFC.getSectorCount(); }
private void resolveIntent(Intent intent) { // 1) Parse the intent and get the action that triggered this intent String action = intent.getAction(); // 2) Check if it was triggered by a tag discovered interruption. if (NfcAdapter.ACTION_TECH_DISCOVERED.equals(action)) { mydialog = ProgressDialog.show(ReadCardActivity.this, "loading", "loading"); // 3) Get an instance of the TAG from the NfcAdapter Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); // 4) Get an instance of the Mifare classic card from this TAG // intent MifareClassic mfc = MifareClassic.get(tagFromIntent); MifareClassCard mifareClassCard = null; try { // 5.1) Connect to card mfc.connect(); // 5.2) and get the number of sectors this card has..and loop // thru these sectors int secCount = mfc.getSectorCount(); mifareClassCard = new MifareClassCard(secCount); // init information String techtemp = ""; for (String tech : mfc.getTag().getTechList()) { techtemp = techtemp + tech + "\n"; } mifareClassCard.addValue("UID", Converter.getHexString(mfc.getTag().getId())); mifareClassCard.addValue("TechList", techtemp); // mifareClassCard.addValue("MemorySize", mfc.get); int bCount = 0; int bIndex = 0; for (int j = 0; j < secCount; j++) { boolean authKeyA = false; boolean authKeyB = false; MifareSector mifareSector = new MifareSector(); mifareSector.sectorIndex = j; // 6.1) authenticate the sector for (String key : defaultKeys) { if (!authKeyA) { authKeyA = mfc.authenticateSectorWithKeyA(j, Converter.hexStringToByteArray(key)); mifareSector.keyA = new MifareKey(Converter.hexStringToByteArray(key)); } if (!authKeyB) { authKeyB = mfc.authenticateSectorWithKeyB(j, Converter.hexStringToByteArray(key)); mifareSector.keyB = new MifareKey(Converter.hexStringToByteArray(key)); } // 都满足则break if (authKeyA && authKeyB) { break; } } if ((authKeyA && authKeyB) || authKeyA || authKeyB) { mifareSector.authorized = true; // 6.2) In each sector - get the block count bCount = mfc.getBlockCountInSector(j); bCount = Math.min(bCount, MifareSector.BLOCKCOUNT); bIndex = mfc.sectorToBlock(j); // set access condition byte[] acdata = mfc.readBlock(bIndex + 3); String hexString = Converter.getHexString(acdata, 16); mifareSector.accessCondition = hexString.substring(12, 20); for (int i = 0; i < bCount; i++) { // 6.3) Read the block byte[] data = mfc.readBlock(bIndex); // System.out.println(Converter.getHexString(data, 16)); MifareBlock mifareBlock = new MifareBlock(mifareSector); mifareBlock.setData(data); mifareBlock.setIndex(bIndex); // 7) Convert the data into a string from Hex // format. bIndex++; mifareSector.blocks[i] = mifareBlock; } mifareClassCard.setSector(mifareSector.sectorIndex, mifareSector); } else { // Authentication failed - Handle it mifareSector.authorized = false; } } this.mydialog.dismiss(); mfc.close(); Intent dataIntent = new Intent(this, ViewCardActivity.class); Bundle bundle = new Bundle(); bundle.putSerializable("mifare", mifareClassCard); dataIntent.putExtras(bundle); this.startActivityForResult(dataIntent, 0); this.finish(); } catch (IOException e) { Log.e(TAG, e.getLocalizedMessage()); showAlert(3); this.mydialog.dismiss(); } finally { if (mifareClassCard != null) { // mifareClassCard.debugPrint(); } } } // End of IF } // End of method