🪪

カードの識別とメモリの読み書き

2023/01/24に公開

用語

名前 正式名称 つまり
RFID Radio Frequency IDentification 全体の仕組みのこと
PCD Proximity Coupling Device カードリーダーのこと
PICC Proximity IC Card カードのこと
RFタグ Radio Frequency Tag 読み取られるメモリの部分のこと
MFRC522 PCDに搭載のチップのこと
Mifare カードの種類の一つ
SAK Select Acknowledge 承認を選択 (とは?)

タグもカードも同じだけど状況によって名称が変わる。

  • 物につけるとき → タグ
  • 人が持つとき → カード

MFRC522 は Mifare のカードを識別できる。そこからすると先頭の の MF は Mifare のことか?

https://www.denso-wave.com/ja/adcd/fundamental/rfid/rfridtec/

部品

https://www.amazon.co.jp/dp/B08516VNKQ

配線

センサ側 Arduino Uno 側
RST D9
SDA(SS) D10
MOSI D11
MISO D12
SCK D13
3.3V 3.3V
GND GND

電源電圧がいつもと異なるので注意する。

ライブラリ

https://github.com/miguelbalboa/rfid

リポジトリの README とコメントだらけの examples とソースがドキュメントになっている。

カード情報の読み取り方法

#include <SPI.h>
#include <MFRC522.h>

#define RST_PIN 9
#define SS_PIN  10

MFRC522 mfrc522(SS_PIN, RST_PIN);

void setup() {
  Serial.begin(9600);
  SPI.begin();
  mfrc522.PCD_Init();
  delay(4);
  mfrc522.PCD_DumpVersionToSerial();
}

void loop() {
  if (mfrc522.PICC_IsNewCardPresent()) {
    if (mfrc522.PICC_ReadCardSerial()) {
      mfrc522.PICC_DumpToSerial(&(mfrc522.uid));
    }
  }
}
表示
Card UID: E3 E6 02 11
Card SAK: 08
PICC type: MIFARE 1KB
Sector Block   0  1  2  3   4  5  6  7   8  9 10 11  12 13 14 15  AccessBits
  15     63   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ]
         62   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
(snip)
          1   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
          0   E3 E6 02 11  16 08 04 00  62 63 64 65  66 67 68 69  [ 0 0 0 ]

新しいカードがタッチされたらその1つを選択し情報を表示する。

UID はどこに入っている?

for (int i = 0; i < mfrc522.uid.size; i++) {
  Serial.println(mfrc522.uid.uidByte[i], HEX);
}
表示
E3
E6
2
11

mfrc522.uid.uidByte に mfrc522.uid.size バイト入っている。これでカードを判別できる。

ファームウェアのバージョン確認方法

mfrc522.PCD_DumpVersionToSerial();
表示
Firmware Version: 0x92 = v2.0

自己診断テスト方法

if (mfrc522.PCD_PerformSelfTest()) {
  // OK
}

カードの種類の確認方法

MFRC522::PICC_Type piccType = mfrc522.PICC_GetType(mfrc522.uid.sak);
Serial.println(mfrc522.PICC_GetTypeName(piccType));
表示
MIFARE 1KB

メモリの読み書きが可能か?

MFRC522::PICC_Type piccType = mfrc522.PICC_GetType(mfrc522.uid.sak);
if (piccType == MFRC522::PICC_TYPE_MIFARE_MINI) { /* OK */ }
if (piccType == MFRC522::PICC_TYPE_MIFARE_1K)   { /* OK */ }
if (piccType == MFRC522::PICC_TYPE_MIFARE_4K)   { /* OK */ }

PICC_TYPE_MIFARE_(MINI|1K|4K) にマッチするかどうかで判定する。MINI は 320 バイト持っている。[1]

status からエラーメッセージへの変換

mfrc522.GetStatusCodeName(status)

メソッドは CodeName となっているが実際はエラーメッセージを返す。

メモリへの書き込み手順

ライブラリが用意してくれているサンプルを読む。

https://github.com/miguelbalboa/rfid/blob/master/examples/ReadAndWrite/ReadAndWrite.ino

  1. 認証時に使うキー FFFFFFFFFFFF を用意する
  2. 読み書きできる種類か判定する
  3. 書き込むデータ16バイト分を用意する
  4. A で認証する
  5. 書き込み前のデータを読み込む (これは単に確認のためと思われる)
  6. B で認証する
  7. 新しいデータ16バイトを書き込む
  8. 読み出す
  9. 書き込んだ値と同じになっているか確認する
  10. PICC を止める
  11. 暗号化を停止する

ライブラリ化されていてもあまり抽象化されておらず、どこのどこに何を何バイト書き込むか、または書き込んではいけない場所など、正確に仕様を把握していないと扱うのは難しい。

書き込みの際にはまったこと

データの長さに特別意味があるとはおもわず "Hello" などを書き込もうとして動かなくなった。1度に書き込める容量はなんと 16 バイト固定だった。

メモリへの読み書きと認証キー A B の関係

https://qiita.com/moh-lee-3/items/9fd957db46473495a377#少しだけ解説

出荷状態のMIFARE ClassicカードのKEYはA、Bともに"FF FF FF FF FF FF"になっています。そして出荷状態ではKEY_Aしか使用できません。ということらしいです。なので読み込み時はKEY_Aで認証をおこない、認証が成功したので読み込めています。書き込み前にKEY_Bで認証をおこなった後に認証を失敗しているので書き込みが出来ていないのです。

だから最初に A で認証している。

UIDを変更するには?

ライブラリのサンプルを一通り見たがよくわからなかった。でも Amazon には書き換え可能と思われるカードが販売されていて、

https://www.amazon.co.jp/dp/B0BLH41Y1H

UIDカードブロック0(UIDのブロック)は任意に変更できます

とあるので通常のメモリへの書き込みと同様の手順で、UIDが書き込まれているアドレスに書き込めば変更できるのかもしれない(未検証)

認証キーを変更した方が良い?

データを書き換えられないようにするには出荷時のキー FFFFFFFFFFFF を変更するべき? これも通常のメモリへの書き込みと同様の手順で変更できる? (TODO)

iPhone を近づけると反応する

ウォレットの画面になる。許可しても何も情報は取れなかった。どうやったら読み取れる? (TODO)

脚注
  1. PICC_GetTypeName の表示にそう書いてあった ↩︎

Discussion