続・NFCおじさん
nfcpy 0.10.0でハマった話
IoTLT Vol.6
山本 允葵
2015/08/19
自己紹介
• 山本 允葵
(Masaki Yamamoto)
• つまみ食いエンジニア
• デバイス好きのおっさん
• 気が付けばソニーまみれ
• VAIOをWindows10にしたいけど
失敗した!(瀕死)
• Jsboard Shibuya やろう
Twitter @m2wasabi
GitHub https://github.com/m2wasabi
前回のあらすじ
簡易認証ツールを作ったよ!
デバイス:Felicaリーダー S380
RaspberryPi (カメラ付)
ソース:python +nfcpy
Node.js +Milkcocoa
INTERMISSION
前回(IoTLT5)の懇親会にて
い○らしさん曰く、オム○ンの体温計とか
NFCでデータやりとりしてるらしい
WellnessLink
よーしhackしてやるぜー!
INTERMISSION
失敗しました…
・ServiceCodeや通信内容が非公開
・情報があまりにも少ない
・Androidアプリのリバースエンジニアリング
⇒できるけど法的にアウト
足りないもの:情報公開 or Hackのお許し or 時間
助けて中の人ー
今回の内容
nfcpyのマイナーバージョンが変わりました
https://launchpad.net/nfcpy
Suicaの履歴を取得する辺りがゴッソリ変更されたので
今までのコードが動かない場合があります。
そこで、0.10.0 での変更点と対応方法についてご紹介します。
Nfcpy 0.10.0 での変更点
・よく知られているNFCタグの判別、メソッドの刷新
⇒Suicaを読んだ場合、 tag オブジェクトが
nfc.tag.tt3.Type3Tag から nfc.tag.tt3_sony.FelicaStandard
に変わっている
移行のためのドキュメントなどがない
・NFCタグのパスワード認証に対応
・Type4Bのタグに対応
⇒運転免許証など 参考:Launchpad
https://launchpad.net/nfcpy/+announcement/13551
参考:hiro99ma site
https://sites.google.com/site/hiro99ma/nfc
Nfcpy 0.10.0 での変更点(詳細)
旧メソッド
例:nfc.tag.tt3.Type3Tag
__init__
__str__
poll
read
write
新メソッド
__init__
__str__
_format
_is_present
authenticate
dump
dump_service
format
polling
protect
read_from_ndef_service
read_without_encryption
send_cmd_recv_rsp
write_to_ndef_service
write_without_encryption
nfc.tag.tt3_sony.FelicaStandard 追加
request_response
request_service
request_system_code
search_service_code
参考:
http://nfcpy.readthedocs.org/en/latest/modules/tag.html
Nfcpy 0.10.0 での変更点(詳細)
str nfc.tag.tt3.Type3Tag.read(int[] blockList, int serviceCode)
以前のデータ取得メソッド
bytearray nfc.tag.tt3.Type3Tag.read_without_encryption(
nfc.tag.tt3.ServiceCode[] blockList
, nfc.tag.tt3.BlockCode[] serviceCode
)
新しいデータ取得メソッド
nfc.tag.tt3.ServiceCode( number, attribute )
number : 16bitの serviceCodeの上位10bit で、service type
attribute : 16bitの serviceCodeの下位6bit で、アクセス権限
nfc.tag.tt3.BlockCode( number, access=0, service=0 )
number : データブロックの番号(suicaなら0~19)
access : 3bit の access mode
service : 4bit ServiceCodeリストのindex
nfcpy/nfc/tag/tt3.py
70行~ に定義
対応方法(アップしたくない人用)
bzr branch lp:nfcpy/0.9
・インストール時に旧バージョンを指定する
以上!
対応方法(0.10.0に移行する場合)
Before
After
data = tag.read ([i],service_code)
# data は str型
print "" . join(['%02x ' % ord(s) for s in data])
sc = nfc.tag.tt3.ServiceCode(service_code >> 6 ,service_code & 0x3f)
bc = nfc.tag.tt3.BlockCode(i,service=0)
data = tag.read_without_encryption([sc],[bc])
# data は bytearray型
print "" . join(['%02x ' % s for s in data])
ポイント:
・従来のサービスコードから、上位10bit,下位6bitで分離してServiceCodeを生成する
・読出し用のメソッドは read_without_encryption
・結果は bytearray 型で返る
対応方法(0.10.0に移行する場合)
Before After
import nfc
service code = 0x090f
num_blocks = 20
def connected(tag):
if isinstance(tag, nfc.tag.tt3.Type3Tag):
try:
for i in range(num_blocks):
sc = nfc.tag.tt3.ServiceCode(service_code >> 6 ,service_code & 0x1f)
bc = nfc.tag.tt3.BlockCode(i,service=0)
data = tag.read_without_encryption([sc],[bc])
# data は bytearray型
print "" . join(['%02x ' % s for s in data])
except Exception as e:
print "error: %s" % e
else:
print "error: tag isn't Type3Tag"
# 接続開始
clf = nfc.ContactlessFrontend('usb')
clf.connect(rdwr={'on-connect': connected})
import nfc
service code = 0x090f
num_blocks = 20
def connected(tag):
if isinstance(tag, nfc.tag.tt3.Type3Tag):
try:
for i in range(num_blocks):
data = tag.read ([i],service_code)
# data は str型
print "" . join(['%02x ' % ord(s) for s in data])
except Exception as e:
print "error: %s" % e
else:
print "error: tag isn't Type3Tag"
# 接続開始
clf = nfc.ContactlessFrontend('usb')
clf.connect(rdwr={'on-connect': connected})
Suicaのデータを垂れ流すだけのコード
まとめ
nfcpyが0.10.1 にアップしました
⇒バージョンアップで嵌った・・・
⇒得られた対策を共有しました!
以上、ご清聴ありがとうございました
0.10.0用のサンプルコードはGitHubにあります。
https://github.com/m2wasabi/nfcpy-suica-sample

nfcpy 0.10.0 でハマった話