1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Felica Lite-S nfcpyのauthenticateメソッドでハマった話

Posted at

ドキュメントを真面目に読めば書いてるかもしれないが、ハマったので備忘録

結論

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]))

image.png

セッション鍵(SK)の生成方法

image.png
☆でバイトーオーダーを反転、⊕は排他的論理和です。

passwordとは?

以下のように記載があります。passwordってなんやねん!?!!?!?

Google翻訳

authenticate(password)
FeliCa Lite-S Tagで相互認証します。

FeliCa Lite-Sは強化されたセキュリティ機能をサポートしており、その一つがこの方式による相互認証です。相互認証の最初の部分は、FelicaLite.authenticate() でタグを認証することです。成功すると、共有セッション キーを使用して書き込み操作の整合性チェック値が生成され、特定のメモリ ブロックが更新されます。それが成功すると、タグはリーダーが正しいカード キーを持っていることが保証されます。

原文

>`authenticate(password)` Mutually authenticate with a FeliCa Lite-S Tag. > >FeliCa Lite-S supports enhanced security functions, one of them is the mutual authentication performed by this method. The first part of mutual authentication is to authenticate the tag with FelicaLite.authenticate(). If successful, the shared session key is used to generate the integrity check value for write operation to update a specific memory block. If that was successful then the tag is ensured that the reader has the correct card key.

わからないのでライブラリの中身を覗くと、どうやらSKを生成するための鍵がpasswordのようです。SKの生成方法の図を見ると、これはCKが該当するようです。

nfc.tag.tt3_sony.py
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を生成しています。
これを調整するため、passwordCKの値を渡すときにあらかじめリトルエンディアンに変換します。

nfc.tag.tt3_sony.py
sk = triple_des(
    key, # <-バイトオーダーを反転させてない
    CBC, 
    b'\00' * 8
    ).encrypt(rc)

補足

CKを生成する方法
image.png

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?