ドキュメントを真面目に読めば書いてるかもしれないが、ハマったので備忘録
結論
password
はカード鍵(CK
)のこと。メソッドに渡す際にはCK1,CK2それぞれをリトルエンディアンに変換する必要があるようです。
# リーダーの読み込み
clf = nfc.ContactlessFrontend("usb")
tag:Type3Tag = clf.connect(rdwr={'on-connect': lambda tag: False})
# IDブロックの値を読み出し、カード鍵を生成
# ここで生成されるCKは図3-13に従ったビッグエンディアン(デフォルト)の値です
ID = tag.read_without_encryption([ServiceCode(0, 0x0b)], [BlockCode(0x82)])
CK = auth.generate_personalized_card_key(ID)
# カード鍵を用いて相互認証
print(tag.authenticate(CK[7::-1]+CK[:7:-1]))
セッション鍵(SK)の生成方法
passwordとは?
以下のように記載があります。password
ってなんやねん!?!!?!?
Google翻訳
authenticate(password)
FeliCa Lite-S Tagで相互認証します。FeliCa Lite-Sは強化されたセキュリティ機能をサポートしており、その一つがこの方式による相互認証です。相互認証の最初の部分は、FelicaLite.authenticate() でタグを認証することです。成功すると、共有セッション キーを使用して書き込み操作の整合性チェック値が生成され、特定のメモリ ブロックが更新されます。それが成功すると、タグはリーダーが正しいカード キーを持っていることが保証されます。
原文
わからないのでライブラリの中身を覗くと、どうやらSK
を生成するための鍵がpassword
のようです。SK
の生成方法の図を見ると、これはCK
が該当するようです。
from pyDes import triple_des, CBC
def _authenticate(self, password):
# 色々あるけど省略
key = b"\0" * 16 if not password else password[0:16]
# The session key becomes the triple_des encryption of the random
# challenge under the card key and with an initialization vector of
# all zero.
sk = triple_des(key, CBC, b'\00' * 8).encrypt(rc)
CKをリトルエンディアンに変換するのはなぜ?
察しの良い方はもう気づいているかもしれません。図を見るとCK1
,CK2
のバイトオーダーを反転させているのに、ライブラリでは反転させずにSK
を生成しています。
これを調整するため、password
でCK
の値を渡すときにあらかじめリトルエンディアンに変換します。
sk = triple_des(
key, # <-バイトオーダーを反転させてない
CBC,
b'\00' * 8
).encrypt(rc)