Я собрал следующий пример кода для обнаружения смарт-карт Mifare с помощью библиотеки javax.smartcardio. Этот код отлично подходит для перечисленных типов Mifare.Как вы можете использовать javax.smartcardio для обнаружения дескриптивной карты?
public class DetectCardTester {
private static final String PROTOCOL = "T=1";
static Map<String,String> KNOWN_CARD_TYPES = ImmutableMap.<String, String>builder()
.put("00-01", "Mifare 1K")
.put("00-02", "Mifare 4K")
.put("00-03", "Mifare Ultralight")
.put("00-26", "Mifare Mini")
.build();
public static void main(String... args) {
try {
final TerminalFactory terminalFactory = SmartcardTerminalFactory.create();
System.out.println("Place card on the reader");
final Card card = awaitCard(terminalFactory, 3, SECONDS);
final ATR atr = card.getATR();
final byte[] bytes = atr.getBytes();
System.out.println("ATR=" + String.valueOf(Hex.encodeHex(bytes, false)));
if (bytes != null && bytes.length > 13) {
String typeCode = String.format("%02X-%02X", bytes[13], bytes[14]);
if (KNOWN_CARD_TYPES.containsKey(typeCode)) {
System.out.println("Known Type:" + KNOWN_CARD_TYPES.get(typeCode));
} else {
System.out.println("Unknown Type:" + typeCode);
}
}
// TODO: Detect Desfire Card
} catch (Throwable t) {
t.printStackTrace();
}
}
public static Card awaitCard(final TerminalFactory terminalFactory, final int qty, final TemporalUnit unit) throws CardException {
LocalDateTime timeout = now().plus(qty, unit);
while (now().isBefore(timeout)) {
Optional<CardTerminal> cardTerminal = getCardPresentTerminal(terminalFactory);
if (cardTerminal.isPresent()) {
return cardTerminal.get().connect(PROTOCOL);
}
}
throw new CardNotPresentException("Timed out waiting for card");
}
private static Optional<CardTerminal> getCardPresentTerminal(final TerminalFactory terminalFactory) throws CardException {
List<CardTerminal> terminals = terminalFactory.terminals().list();
for (CardTerminal cardTerminal : terminals) {
if (cardTerminal.isCardPresent()) {
return Optional.of(cardTerminal);
}
}
for (CardTerminal cardTerminal : terminals) {
// waitForCardPresent/Absent doesn't work with some Jacax.smartcard.io implementations
// i.e. OSX http://bugs.java.com/view_bug.do?bug_id=7195480
// This is why we have the imediate check above
if (cardTerminal.waitForCardPresent(250)) {
return Optional.of(cardTerminal);
}
}
return Optional.empty();
}
}
Я использовал следующие ресурсы, чтобы поместить этот код вместе:
- http://downloads.acs.com.hk/drivers/en/API-ACR122U-2.02.pdf
- How to get SAK to Identify smart card type using JAVA?
Я хотел бы реализовать TODO комментарий для обнаружения DESFire карт. Если я помещаю карту DESFire на чтение этого кода просто выводит:
Place card on the reader
ATR=3B8180018080
Я нашел этот вопрос Determine card type from ATR который помогает немного, но я что-то отсутствует. Для этой карточки HistoryByte является 0x80, для которой я не могу найти никакой информации.
Если возможно, я был бы очень признателен за приведенный выше пример кода, который может обнаружить тип карты Desfire.
Как насчет пользовательских ATS для ваших карт? Или отправить GetVersion?Или отправить некоторую команду в native DESFire, а не завернуть. У меня нет другого варианта, так как это ISO14443-4A. Даже используя SAK (недоступно на Java), вы можете столкнуться с конфликтами. – jlanza
Спасибо за предложение. Я не уверен, как отправить ATS с использованием Java, а также не уверен, как использовать его для обеспечения карты карты Desfire. Я думал об использовании GetVersion, но это похоже на взломать! – bludginozzie
ATS будет специально для вашей карты не DESFire или, по крайней мере, я так думаю. Затем это то, что вы настраиваете на своей карте. Что касается GetVersion как взлома, я думаю, что это карта типа 4A, иначе было бы трудно. На самом деле, кто-то может реализовать на JavaCard аналогичную команду и подделку - это карта DESFire :( – jlanza