立命館の学生証の話
こんにちは、M1のYukimuraです。
前回書いた記事で「学生証といえば、学生証リーダーを作った話もあるのですが、それはまた次の機会に。」と書いてしまい、機会が無いわけが無い(弊研のブログは当番制では無いので書きたいときに書けます)ので、その話をします。
はじめに、本記事内では学生証の内部構造について筆者が独自研究で解説をしますが、情報技術に関する知見を深めることを目的としており、なりすましなどの悪用をはじめとする不正な利用を推奨するものではありません。また、本記事内で書かれている内容を実践した場合に被った不利益については実践者本人の責任に帰するものとし、筆者は一切その責任を負いません。
ご理解いただけましたら記事をどうぞ!
基礎的な話
そもそも、学生証に使われている技術として、NFCがあります。このあたりGoogle大先生に「NFC 学生証」なんて聞いてもらえれば山ほど記事が出てくるのですが、要するにピッてするだけでデータ通信ができるあれです。身近なところだとICOCA等の交通系IC、マイナンバーカード、(立命館)生協カードなんかがあります。
理屈はかんたんで、実はあの名刺大のカードには中にコイルが入っていて、電磁石が入ったリーダに近づけるとファラデーの電磁誘導の法則で有名な電磁誘導作用によって誘導電流が流れ、内臓のICチップが動作する、とまあこういう仕組みです。(筆者は高校時代物理の評定が4/10だったので詳しいことはわかりません)
よく混乱する言葉として、「FeliCa」がありますが、基本的にNFC⊃FeliCaであり、FeliCaはNFCを元にSONYが開発した規格になります。(話の本筋ではない&筆者もよくわかっていないので、興味のある人は自身で調べてみてくださいm(_ _)m)
立命館の学生証をダンプした話
ここからが本題です。
今回利用した環境は以下。
- mac book pro(2018)
- SONY RC-S380
- python 3.9.7
以上の環境で、立命館の学生証をダンプしました。
RC-S380というのはSONYから発売されている、どこのご家庭にでもあるNFCリーダ・ライタでして、 PaSoRiという名前で売られています。
時たまハードオフでジャンクコーナーを漁っていると、500円くらいで売られていたりするので、一家に一台あるとなにかと便利だと思います。
こいつを使うことで学生証の中身を読めます。
それでは実際にコードを書いて読んでみましょうということで、完成したコードがこちらです。
import nfc
def on_connect(tag):
print(tag)
for i in tag.dump():
print(i)
clf = nfc.ContactlessFrontend('usb')
clf.connect(rdwr={'on-connect': on_connect})
↑こんな感じでpythonで書いてやって、実行すると結果が以下です。
白く塗られているところが学生証番号です。一応個人情報なので隠しました(ちなみに情理研究科計算機科学コースの22年度入学生の学生証番号上6桁は「661122」です。意味は「立命館の学生証番号の話」を参照)。
本当にダンプできてるか気になる人は自分の環境で自分の学生証でやってみてください。
それで、ここで何に注目すべきかと言うと、service 106です。ここ、隠している通りblock code 0000には学生証番号が書かれているのですが、よくよく見てみると名前も書かれています。
service code 106のblock code 0001を見てやると、「b7 d1 d7 20 d5 b3 b7」と書かれている事がわかります。
このhexをShift-JISとして読んでやると「キムラ ユウキ」となり無事私の本名です。
他にも、service code 106のblock code 0002には「32 30 32 32 30 34 30 31」と書かれていて、これは(右側にも書いてあるとおり)「20220401」と読めて、おそらく入学年月日でしょう。
生年月日とかも書かれているかなと(学生証表面に記載があるので)思ったのですが、少なくとも公開エリアには書かれていなかったので少々意外です。
おまけの話
半角カタカナ氏名と学生証でピンと来た人もいると思うんですが、この2つが表示されるサービスが立命館にはあったなと思い出しました。
そう、出席を取るときにピッてすると「ピロリロリーン」と音がするアレです(伝われ)。
こんなところにマニュアルが落ちてたのでちょっと確認してみましょう。
上記のマニュアル内から画像を引用すると、↓こんなやつ
確かに表示は学生証番号と半角の氏名で、かつ(おそらく)サーバと通信している雰囲気も無いので、ローカルでカード情報を読んでるだけなんでしょうね(おそらく)(おそらく)。ならservice code 106の中身さえ偽造できれば学生証が偽造できるのでは?
ちなみに本当に余談ですが、近年(近年?)主に学部生の間では、代返ならぬ「代ピッ」が横行しているらしく、何らかの対処が必要なんじゃないかなと思います。っていうかいくら授業に行きたくない(or行けない事情がある)からといって、そもそも他人に学生証を預けられるのが(セキュリティ意識的に)すごいとは思いますが...
入退室管理ソフトを作った話
さて、ここまで読めればもうかんたんで、あとは名前と学生証番号だけを切り出してやれば、如何様にでも料理ができます。
こんなふうにpythonで書いてやれば...
import nfc
import sys
import binascii
def on_connect(tag):
idm, pmm = tag.polling(system_code=0xfe00)
tag.idm, tag.pmm, tag.sys = idm, pmm, 0xfe00
sc = nfc.tag.tt3.ServiceCode(106, 0x0b)
bc = nfc.tag.tt3.BlockCode(0, service=0)
data_num = tag.read_without_encryption([sc], [bc])
data_num = data_num.decode('shift_jis')
print(data_num[2:-3])
bc = nfc.tag.tt3.BlockCode(1, service=0)
data_name = tag.read_without_encryption([sc], [bc])
data_name = data_name.decode('shift_jis')
print(data_name)
def read_student_info():
with nfc.ContactlessFrontend('usb') as clf:
try:
clf.connect(rdwr={'on-connect': on_connect})
except :
pass
if __name__ == '__main__':
while True:
read_student_info()
名前と学生証番号を出力するコードの出来上がり。というわけで長々記事を書きましたが、前回の記事で書いた「学生証リーダーを作った話もあるのですが、それはまた次の機会に。」はこれにて達成となります。
ちなみに、これをちょっと工夫してGUIにしてやると、
こんな感じで入退室管理ソフトができちゃいます。
これは学生証をタッチするだけで入退室を記録して、更に誰が入退室したかをslackに通知を送ってくれるスグレモノで、現在、立命館大学学友会中央事務局BKCと同衣笠で運用中です。
感染症対策のための入退室管理のために、21年の3月に作りました。紙に名前と入退室時間を書くなんてアホらしいし、なんてったって物理接触機会が増えますからね。
こいつの話もいつかします、機会があれば。
おわりに
いかがだったでしょうか、学生証。
dumpするだけのものがすぐ書けてしまうので、python便利だなーと思いながら記事を書いていました。
技術力と時間が許す方は、是非中身を覗いて見てください。僕が見逃してる要素があるかも知れません。
それではまた次回...
(文責:2022年度M1 木村 悠生)