カードの識別とメモリの読み書き
用語
名前 | 正式名称 | つまり |
---|---|---|
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 のことか?
部品
配線
センサ側 | Arduino Uno 側 |
---|---|
RST | D9 |
SDA(SS) | D10 |
MOSI | D11 |
MISO | D12 |
SCK | D13 |
3.3V | 3.3V |
GND | GND |
電源電圧がいつもと異なるので注意する。
ライブラリ
リポジトリの 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
となっているが実際はエラーメッセージを返す。
メモリへの書き込み手順
ライブラリが用意してくれているサンプルを読む。
- 認証時に使うキー FFFFFFFFFFFF を用意する
- 読み書きできる種類か判定する
- 書き込むデータ16バイト分を用意する
- A で認証する
- 書き込み前のデータを読み込む (これは単に確認のためと思われる)
- B で認証する
- 新しいデータ16バイトを書き込む
- 読み出す
- 書き込んだ値と同じになっているか確認する
- PICC を止める
- 暗号化を停止する
ライブラリ化されていてもあまり抽象化されておらず、どこのどこに何を何バイト書き込むか、または書き込んではいけない場所など、正確に仕様を把握していないと扱うのは難しい。
書き込みの際にはまったこと
データの長さに特別意味があるとはおもわず "Hello"
などを書き込もうとして動かなくなった。1度に書き込める容量はなんと 16 バイト固定だった。
メモリへの読み書きと認証キー A B の関係
出荷状態のMIFARE ClassicカードのKEYはA、Bともに"FF FF FF FF FF FF"になっています。そして出荷状態ではKEY_Aしか使用できません。ということらしいです。なので読み込み時はKEY_Aで認証をおこない、認証が成功したので読み込めています。書き込み前にKEY_Bで認証をおこなった後に認証を失敗しているので書き込みが出来ていないのです。
だから最初に A で認証している。
UIDを変更するには?
ライブラリのサンプルを一通り見たがよくわからなかった。でも Amazon には書き換え可能と思われるカードが販売されていて、
UIDカードブロック0(UIDのブロック)は任意に変更できます
とあるので通常のメモリへの書き込みと同様の手順で、UIDが書き込まれているアドレスに書き込めば変更できるのかもしれない(未検証)
認証キーを変更した方が良い?
データを書き換えられないようにするには出荷時のキー FFFFFFFFFFFF を変更するべき? これも通常のメモリへの書き込みと同様の手順で変更できる? (TODO)
iPhone を近づけると反応する
ウォレットの画面になる。許可しても何も情報は取れなかった。どうやったら読み取れる? (TODO)
-
PICC_GetTypeName の表示にそう書いてあった ↩︎
Discussion