NDEF(Near field communication Data Exchange Format)について、いろいろな資料を読んでみましたが、いまいち、分からないんですよね。
なんで、具体的なデータで説明してくれないんだろう。
そこで、某ツールでICカードに書き込んだNDEFレコードを読み出して解析してみました。
NDEFレコードはTLVのVに入れ子構造になって格納される
NFC(Near Field Communication)でダイナミックメモリを用いる場合、しばしばTLV(Tag, Length, Value)ブロックが使われます。すなわち、Tag部でブロックの用途を示し、Length部でデータのサイズを表し、Value部にデータを格納します。
NDEFレコードは、NFC Forumが策定したタグ表現のための共通フォーマットです。このNDEFレコードは、TLVのVの部分に格納されます。
また、NDEFレコードにはいくつかのタイプがあります。例えば、スマートポスタレコードは、テキストレコードやURIレコードを包含することができます。
スマートポスタレコードの書き込み例
スマートポスタレコードをType 2のタグとして、MIFARE Ultralight Cのカードに書き込んだ例を示します。バイナリデータの右側にはアスキーデータも示しました。
01h: DA-1B-5C-80 ?_\?
02h: 1D-48-00-00 _H??
03h: E1-10-12-00 ?__?
04h: 01-03-A0-0C __?_
05h: 34-03-3E-D1 4_>?
06h: 02-39-53-70 _9Sp
07h: 91-01-15-54 ?__T
08h: 02-6A-61-E3 _ja?
09h: 81-95-E3-81 ????
0Ah: 97-E3-81-82 ????
0Bh: E3-81-9F-E3 ????
0Ch: 81-A3-E3-81 ????
0Dh: A6-11-01-15 ?___
0Eh: 55-04-6D-69 U_mi
0Fh: 73-63-65-6C scel
10h: 6C-61-6E-65 lane
11h: 6F-75-73-2E ous.
12h: 74-6F-6B-79 toky
13h: 6F-2F-51-03 o/Q_
14h: 01-61-63-74 _act
15h: 00-FE-00-00 ????
16h: 00-00-00-00 ????
~
27h: 00-00-00-00 ????
28h: 00-00-00-BD ????
29h: 04-00-00-FF _???
2Ah: 00-05-00-00 ?_??
2Bh: 00-00-00-00 ????
このうち、最初から05hページの0hバイト(34h)迄と15hページの2hバイト(00h)から最後までの内容は、こちらの記事で解説しているので、本記事では省略します。

TLVブロック
NDEFレコードは05hページの1hバイトから始まります。すなわち、03-3E-…です。
03hはTagで、「NDEF Message TLV」を示します。
3EhはLengthで、データが3Ehすなわち、62バイトであることを示しています。
その次のD1hのバイトから62バイトを数えると、15hページの0hバイトの00hまでとなります。その次のFEhは、Tagで、「Terminate TLV」を示します。つまり、NDEFメッセージは、この1つのVの中に全て含まれています。
スマートポスタレコード
NDEF Message TLVのVである05hページの3hバイトからスマートポスタレコードが始まります。すなわち、D1-02-39-53-70-91–…の部分です。
NDEFレコードの先頭ビットは、上図に示すように、フラグ類から構成されます。略語の意味は次の通りです。略語 | 意 味 |
MB | Message Begin(メッセージ開始) |
ME | Message End(メッセージ終了) |
CF | Chunk Flag(分割されたPAYLOADに続きがある) |
SR | Short Record(ペイロード長が1バイト以下) |
IL | ID Length(IDの長さフィールドが存在する) |
TNF | Type Name Format(レコードタイプ) |
このスマートポスタレコードの先頭バイトは、D1hであり、これを2進法に直すと、「1101 0001」です。よって、MB、ME、SRフラグが立っていて、TNFは01hということになります。この意味は、メッセージの開始であって終わりということなので、NDEFレコードは1つだけです。また、SRフラグが立っているので、ペイロードは1バイトであらわされる数値以下、つまりFFh(255)バイト以下です。
次にTNFです。TNFは3ビットで、以下の表に示すように、レコードタイプを示します。
ここでは、001b = 01hなので、Well-knownです。
TNFの値 | レコードタイプ | 意 味 |
0h | Empty | 空 |
1h | Well-known | タイプにRecord Type Definition形式を用いる |
2h | MIME Media | MIMEタイプ |
3h | Absolute URI | 絶対URI |
4h | External | RTD外部 |
5h | Unknown | ペイロードが不明 |
6h | Unchanged | チャンクの最初ではない |
続く02hは、Typeの長さが2バイトであることを意味します。
39hは、ペイロードの長さが57バイトであることを意味します。
53-70はTypeであり、アスキーコードとして変換すると、「Sp」です。つまり、このNDEFはスマートポスタレコードです。
その次の91hからペイロードが始まります。ここから57バイトを数えると、15hページの0hバイトまでということになります。その次はNDEFの終わりを示すFEhですから、TLVのVの部分はスマートポスタレコードが1つだけ入っていることが分かります。
07hページの0hバイトからテキストレコードが始まります。すなわち、91-01-15-54-02-6A-61-E3-…の部分です。
91hは、NDEFの先頭ビットですから、フラグ類で構成されています。2進法に直すと「1001 0001」です。すなわち、MB、SRフラグが立っていて、TNFは01hということになります。よって、本NDEFはスマートポスタの最初のレコードであって、(MEが立っていないことから)後にまだ続くレコードがあることが分かります。また、SRフラグが立っているので、ペイロードは255バイト以下であることも分かります。
さらに、TNFは01hなので、このNDEFもWell-knownタイプです。
続く01hは、Typeの長さが1バイトであることを示します。
さらに、15hは、ペイロードの長さが21バイトであることを示します。
54hは1バイト長のTypeであり、アスキーコードと見なすと「T」です。よって、このNDEFがテキストレコードであることが分かります。
ペイロードの0バイト目、すなわち02hは、文字に関するフラグ類で構成されています。2進法に直すと「0000 0010」です。ここで、MSB(最上位ビット)をb7、以下LSB(最下位ビット)をb0と呼ぶことにします。ここで、b7は、0ならUTF-8、1ならUTF-16を表します。よって、このテキストはUTF-8でエンコードされていることが分かります。
さらに、b5~b0は、言語コードの長さを示します。000010bは2バイトを意味するので、続く6A-61の2バイトが言語コードを示しています。アスキーコードを変換すると、「ja」です。つまり日本語です。
UTF-8では日本語の1文字は3バイトで表されます。ペイロードの21バイト中、3バイトを既に使っているので、残りの18バイトを3文字ずつ区切ってみます。すると、「E3-81-95」「E3-81-97」「E3-81-82」「E3-81-9F」「E3-81-A3」「E3-81-A6」となり、これをデコードすると「さしあたって」の6文字となります。本ブログのタイトルでした。
次は、URIレコードです。0Dhページの1hバイトから始まる11-01-15-55-04-6D-…の部分です。
11hは例によって、フラグ類で構成されています。2進数に直すと「0001 0001」です。よって、SRフラグのみが立っていて、TNFは1hです。すなわち、一連の途中のNDEFレコードであり、ペイロードは255バイト以下です。また、Well-knownタイプであることも分かります。
続く01hから、Typeの長さが1バイトであることがわかります。また、ペイロード長は15h、すなわち、21バイトです。
タイプは55hの1バイトで示され、文字に直すと「U」です。これは、URIレコードであることを示します。
04hからペイロードが始まりますが、その1バイト目は、URI識別コードです。文献[2]の表23-3から抜粋すれば、
コード | 接頭辞 |
0x01 | http://www. |
0x02 | https://www. |
0x03 | http:// |
0x04 | https:// |
となるので、「https://」であることがわかります。そこから、6D-69-73-63-65-6C-6C-61-6E-65-6F-75-73-2E-74-6F-6B-79-6F-2Fと続く20バイトを文字に直して接頭辞につなげると、「https://miscellaneous.tokyo/」となります。本ブログのURIでした。
最後に、アクションレコードがあります。
51-03-01-61-63-74-00という短いレコードです。
例によって、51hを2進数に直すと、「0101 0001」ですので、MEとSRフラグが立っています。また、TNFは1hです。これらのことから、最後のレコードであること、ペイロードが255バイト以下、Well-knownであることが分かります。
TYPEの長さ及びIDの長さはそれぞれ、03hバイト、01hバイトです。TYPEを示す61-63-74の3バイトを文字に直すと、「act」なので、アクションレコードであることが分かります。そのアクションは、00hなので、実行することが推奨されています。
最後に終了コードであるFEhが来て、NDEFは終了です。
まとめ
NDEFのバイナリデータをカードから読み出して、解析しました。ここで示したタグを適当なリーダで読めば、本ブログが開くはずです。残念ながら、僕の手元にリーダが無いので、試すことはできませんでした。
[1] https://learn.adafruit.com/adafruit-pn532-rfid-nfc/ndef
[2] 株式会社ブリリアントサービス:NFC HACKSプロが教えるテクニック&ツール、オライリー・ジャパン、pp.128-134、2013、ISBN978-4-87311-624-2
コメント