Чтение Mifare Classic возвращает странных персонажей - PullRequest
0 голосов
/ 20 февраля 2019

При чтении карты MIFARE с Android и преобразовании данных в UTF-8 у меня появляются странные символы, такие как �.Я пытаюсь создать приложение, которое может читать какую-то идентификационную карту, которую мы используем.Проблема в том, что я получаю странные символы между словами, а некоторые слова разбиваются на блоки, так как я могу безопасно получить слово, которое ищу?Например, мои показания выглядят примерно так:

43224���19032019�� в блоке 2, сектор 2 bindex: 8

и с разбиением, где остаток числа, начинающийся с 19, равенновый блок:

Имя ���M���19

в блоке 1 сектор 1 bindex: 4

930402���NO934951

в блоке 2 сектор 1 bindex: 4

c5 42 4e 49 44 00 07 4f 4f 4f 4f 4f 4f 00 4b 42   "Åbnid" "OOOOOO" "KB"
44 44 44 20 44 44 44 44 44 00 82 4d 00 c9 31 39   "DDD DDDDD" "M" "19"
39 34 34 33 34 32 00 d0 4e 4f 39 36 36 36 35 31   "944342" "NO966651"
00 00 00 00 00 00 70 f7 88 00 00 00 00 00 00 00
30 32 32 20 20 41 53 00 d3 54 4f 54 41 4c 20 4b   "022" "AS" "Total k"
4f 4e 54 52 4f 4c 4c 20 41 53 20 00 c9 30 32 38   "ONTROLL AS" "028"
37 30 34 33 33 00 c9 32 30 32 31 30 32 31 31 00   "70433" "20210211"
00 00 00 00 00 00 70 f7 88 00 00 00 00 00 00 00

Вот как я читаю с карты:

Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
MifareClassic mfc = MifareClassic.get(tagFromIntent);

Вот мой код, который я использую для чтения внутри цикла for:

 data = mfc.readBlock(bIndex + block); 

, а затем для преобразования данных в UTF8 для печати, которую я использую:

   public String convertByteArrayToUTF8(byte[] bytes){
    String encoded = null;
    try {
        encoded = new String(bytes, StandardCharsets.UTF_8);
    }
    catch (Exception e){
        encoded = new String(bytes, Charset.defaultCharset());
    }
    return encoded;
}

Я пробовал с ASCII, UTF-16 и т. Д. Безуспешно.

Ответы [ 2 ]

0 голосов
/ 25 февраля 2019

Таким образом, данные в вашем теге (исключая секторные трейлеры выглядят примерно так:

C5 42 4E 49 44 00 07 4F 4F 4F 4F 4F 4F 00 4B 42        ÅBNID..OOOOOO.KB
44 44 44 20 44 44 44 44 44 00 82 4D 00 C9 31 39        DDD DDDDD.‚M.É19
39 34 34 33 34 32 00 D0 4E 4F 39 36 36 36 35 31        944342.ÐNO966651
30 32 32 20 20 41 53 00 D3 54 4F 54 41 4C 20 4B        022  AS.ÓTOTAL K
4F 4E 54 52 4F 4C 4C 20 41 53 20 00 C9 30 32 38        ONTROLL AS .É028
37 30 34 33 33 00 C9 32 30 32 31 30 32 31 31 00        70433.É20210211.

Это похоже на некоторую форму структурированных данных. Просто преобразование всего двоичного двоичного объекта в UTF-8 (или ASCII) кодированная строка не имеет большого смысла. Вместо этого вам нужно будет перепроектировать способ структурирования данных (или, что еще лучше, вы попытаетесь получить спецификацию от производителя системы).

Из того, что я вижу, похоже, что эти данные состоят из нескольких строк с нулевым символом в конце, встроенных в какой-либо компактный (Tag) -Length-Value формат. Первый байт, кажется, тег (?) + Length, поэтому мы имеем

C5    Length = 5
    42 4E 49 44 00                                               "BNID"
07    Length = 7
    4F 4F 4F 4F 4F 4F 00                                         "OOOOOO"
4B    Length = 11
    42 44 44 44 20 44 44 44 44 44 00                             "KBDDD DDDDD"
82    Length = 2
    4D 00                                                        "M"
C9    Length = 9
    31 39 39 34 34 33 34 32 00                                   "19944342"
D0    Length = 16
    4E 4F 39 36 36 36 35 31 30 32 32 20 20 41 53 00              "NO966651022  AS"
D3    Length = 19
    54 4F 54 41 4C 20 4B 4F 4E 54 52 4F 4C 4C 20 41 53 20 00     "TOTAL KONTROLL AS "
C9    Length = 9
    30 32 38 37 30 34 33 33 00                                   "02870433"
C9    Length = 9
    32 30 32 31 30 32 31 31 00                                   "20210211"

Первый байт, например, можно разделить на тег и длину, например, так: TTTL LLLL (старшие 3 бита кодируют тег, младшие 5 бит кодируют длину следующего значения).укажите следующие теги

  • 0x6 для "BNID", "19944342", "NO966651022 AS", "TOTAL KONTROLL AS", "02870433" и "20210211"
  • 0x0для "OOOOOO"
  • 0x2 для "KBDDD DDDDD"
  • 0x4 для "M"

Следовательно, разделение между тегом и длиной может такжебыть TTLL LLLL (старшие 2 бита кодируют тег, младшие 6 бит кодируют длину следующего значения).

К сожалению, этот формат не похож ни на один из известных мне известных форматов.Таким образом, вы можете просто продолжить обратный инжиниринг, сравнивая несколько разных карт и получая значения из значений.

До сих пор, чтобы расшифровать вышеприведенное, вы должны начать с чтения первого байта, извлечения длины изэтот байт, обрежьте это количество последующих байтов и преобразуйте их в строку (в зависимости от предоставленного вами примера, подойдет кодировка ASCII).Затем вы можете продолжить со следующего байта, извлечь из него информацию о длине, ...

0 голосов
/ 20 февраля 2019

Прежде всего LOL для заголовка вопроса.Я был в той же ситуации, когда был новичком.В Интернете нет учебника, в котором вы найдете точный код для чтения данных с классической карты Mifare.

Сначала разберитесь со структурой памяти карт Mifare.

Память Mifare Classic разделена на сектора., которые также делятся на блоки по 16 байт.

Карта MIFARE Classic 1K имеет 16 секторов, каждый из которых разделен на четыре блока.Если мы посчитаем, мы сможем понять, как будет выглядеть структура памяти: 16 байтов (1 блок) * 4 блока * 16 секторов = 1024 байта.

enter image description here

Карта MIFARE Classic 4K имеет 40 секторов, 32 из которых разделены на четыре блока, а остальные 8 разделены на 16 блоков.16 байтов (1 блок) * 4 блока * 32 сектора + 16 байтов (1 блок) * 16 блоков * 8 секторов = 4096 байтов.Структура памяти следующая:

enter image description here

Число в блоках указывает его индекс.Каждый сектор защищен ключом сайта, записанным в последнем блоке сектора.Например, блок 3 содержит ключ сайта для сектора 1 и блок 7 для сектора 2. Последний блок в каждом секторе также содержит информацию об условиях доступа, такую ​​как «запись», «чтение» и «чтение и запись».На следующем рисунке показано, из чего состоит последний блок:

enter image description here

Кроме того, данные, записанные на карте, являются двоичными, т.е.0 & 1.

Теперь для чтения данных необходимо выполнить следующие шаги:

step1: проверить, поддерживает ли устройство NFC или нет.

step2: проверитьесли устройство оснащено микросхемой NXP (особенно для чтения классических карт Mifare).

step3: создать экземпляр NFC-менеджера и NFC-adpater и определить технический список карт, которые вы хотите прочитать.

step4:запросить разрешение на доступ к устройству NFC.

step5: создать намерение обнаружить карту и указать тип MIME, который вы хотите прочитать (в большинстве случаев это все типы MIME).

step6: включитьи отключите приоритетную отправку адаптера в onResume () и onPause (), чтобы ваше приложение получило приоритет для чтения карты, когда ваша деятельность находится на переднем плане.

step7: Когда карта входит в контакт с устройством, вы можетеполучить информацию тега от intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);

step8: прочитать информацию о карте, т.е.тип карты, технический список и т. д.

step9: для чтения данных на карте необходимо подключиться к карте с помощью информации тега, полученной выше.

step10: выполнить итерацию по всем секторам.Аутентифицируйте каждый сектор с помощью ключа по умолчанию // https://developer.android.com/reference/android/nfc/tech/MifareClassic.html#authenticateSectorWithKeyA(int,%20byte[])

step11: при успешной аутентификации считайте двоичные данные в блоках каждого сектора.

step12: преобразуйте двоичные данные в строковые данные так, чтобычто мы можем его прочитать.

step13: Вот и все, делайте все, что вы хотите с данными.

сюрприз!получите полный рабочий код в моем репозитории github здесь: https://github.com/codes29/RFIDReader

Примечание: я сочувствовал, как вы себя чувствуете как новичок, и получил эту задачу, где нет соответствующего учебника для того же.Поэтому я обновил свой код, который написал после многих дней борьбы.

Вот пример, который вы получите после успешной аутентификации и чтения данных.Карта, которую я отсканировал, пуста, как сейчас.Но если здесь есть данные, то они наверняка будут здесь вместо 0.

/tmp/mozilla_mobulous0/Screenshot_20190221-124444.png

Ура!Приятного кодирования, братан!

...