/** * The MIT License (MIT) * * Copyright (c) 2015 Marc de Verdelhan * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ package eu.verdelhan.acr122urw; import java.io.IOException; import java.util.ArrayList; import java.util.List; import javax.smartcardio.CardException; import org.nfctools.mf.MfCardListener; import org.nfctools.mf.MfReaderWriter; import org.nfctools.mf.card.MfCard; /** * Entry point of the program. * <p> * Manager for an ACR122 reader/writer. */ public class Acr122Manager { /** * Entry point. * @param args the command line arguments * @see Acr122Manager#printHelpAndExit() */ public static void main(String[] args) throws IOException { if (args == null || args.length == 0) { printHelpAndExit(); } switch (args[0]) { case "-d": case "--dump": dumpCards(args); break; case "-w": case "--write": writeToCards(args); break; case "-h": case "--help": default: printHelpAndExit(); break; } } /** * Prints information about a card. * @param card a card */ private static void printCardInfo(MfCard card) { System.out.println("Card detected: " + card.getTagType().toString() + " " + card.toString()); } /** * Listens for cards using the provided listener. * @param listener a listener */ private static void listen(MfCardListener listener) throws IOException { Acr122Device acr122; try { acr122 = new Acr122Device(); } catch (RuntimeException re) { System.out.println("No ACR122 reader found."); return; } acr122.open(); acr122.listen(listener); System.out.println("Press ENTER to exit"); System.in.read(); acr122.close(); } /** * Dumps cards. * @param args the arguments of the dump command */ private static void dumpCards(String... args) throws IOException { // Building the list of keys final List<String> keys = new ArrayList<>(); for (int i = 1; i < args.length; i++) { String k = args[i].toUpperCase(); if (MifareUtils.isValidMifareClassic1KKey(k)) { keys.add(k); } } // Adding the common keys keys.addAll(MifareUtils.COMMON_MIFARE_CLASSIC_1K_KEYS); // Card listener for dump MfCardListener listener = new MfCardListener() { @Override public void cardDetected(MfCard mfCard, MfReaderWriter mfReaderWriter) throws IOException { printCardInfo(mfCard); try { MifareUtils.dumpMifareClassic1KCard(mfReaderWriter, mfCard, keys); } catch (CardException ce) { System.out.println("Card removed or not present."); } } }; // Start listening listen(listener); } /** * Writes to cards. * @param args the arguments of the write command */ private static void writeToCards(String... args) throws IOException { // Checking arguments if (args.length != 5) { printHelpAndExit(); } final String sector = args[1]; final String block = args[2]; final String key = args[3].toUpperCase(); final String data = args[4].toUpperCase(); if (!MifareUtils.isValidMifareClassic1KSectorIndex(sector) || !MifareUtils.isValidMifareClassic1KBlockIndex(block) || !MifareUtils.isValidMifareClassic1KKey(key) || !HexUtils.isHexString(data)) { printHelpAndExit(); } final int sectorId = Integer.parseInt(sector); final int blockId = Integer.parseInt(block); // Card listener for writing MfCardListener listener = new MfCardListener() { @Override public void cardDetected(MfCard mfCard, MfReaderWriter mfReaderWriter) throws IOException { printCardInfo(mfCard); try { MifareUtils.writeToMifareClassic1KCard(mfReaderWriter, mfCard, sectorId, blockId, key, data); } catch (CardException ce) { System.out.println("Card removed or not present."); } } }; // Start listening listen(listener); } /** * Prints help and exits. */ private static void printHelpAndExit() { String jarPath = Acr122Manager.class.getProtectionDomain().getCodeSource().getLocation().getFile(); String jarName = jarPath.substring(jarPath.lastIndexOf('/') + 1); StringBuilder sb = new StringBuilder("Usage: java -jar "); sb.append(jarName).append(" [option]\n"); sb.append("Options:\n"); sb.append("\t-h, --help\t\t\tshow this help message and exit\n"); sb.append("\t-d, --dump [KEYS...]\t\tdump Mifare Classic 1K cards using KEYS\n"); sb.append("\t-w, --write S B KEY DATA\twrite DATA to sector S, block B of Mifare Classic 1K cards using KEY\n"); sb.append("Examples:\n"); sb.append("\tjava -jar ").append(jarName).append(" --dump FF00A1A0B000 FF00A1A0B001 FF00A1A0B099\n"); sb.append("\tjava -jar ").append(jarName).append(" --write 13 2 FF00A1A0B001 FFFFFFFFFFFF00000000060504030201"); System.out.println(sb.toString()); System.exit(0); } }