1. 概要
symbolブロックチェーンにおける秘密鍵データをNFCタグに書き込み、それをpythonで読み取って、XYM送金する。
2. 環境・前提条件
windows10
Python 3.10.9
NFCリーダーライター RC-S380
Zadig 2.8
libusb 1.0.26
WinUSB 6.1.7600.16385
NFCタグ NTAG215
symbol-desktop-wallet 1.0.13
3. pythonライブラリ
symbol-sdk-python v3.0.3
nfcpy v1.0.4
4. 環境構築
まず、はじめにpythonのNFC読取・書込用ライブラリであるnfcpyをインストールします。
pip install nfcpy
※symbol-sdk-pythonをインストールしていない場合も同じくインストール
pip install symbol-sdk-python
次に、windowsでNFCを認識させるため、Zadigを以下のリンクからダウンロードします。
Zadig公式ホームページ
zadigの画面を開いたら、optionからList All Devicesをクリックします。
プルダウンメニューからRC-S380を選択し、Reinstall Driverをクリックします。
ドライバーを変更してしまうとnfcpy以外では、RC-S380は認識されなくなってしまうので、ご注意ください。例えば、マイナンバーカードの読み取りなどやe-taxのログインが出来なくなります。
元に戻す場合は専用のドライバを再インストールしてください。
NFCポートソフトウェアのダウンロード
加えて、libusbを以下のリンクからダウンロードします。
libusbホームページ
必要に応じて、 7-Zipなどの解凍ソフトで解凍してください。
エクスプローラーを別ウィンドウで開き、「C:\Windows\System32」にアクセスします。
解凍したフォルダの中から、以下のファイルを「C:\Windows\System32」へ移動させてください。
「libusb-cygwin-x64」
「libusb-MinGW-x64」
「VS2015-x64」
次に、別ウィンドウを「C:\Windows\System32」→「C:\Windows\SysWOW64」へ変更します。
解凍したフォルダから、以下のファイルを「C:\Windows\SysWOW64」へ移動させてください。
「libusb-cygwin-Win32」
「libusb-MinGW-Win32」
「VS2015-Win32」
これでnfcpyでNFCタグを読み書きする環境構築が完了しました。
5. コード(NFCタグ ID読取)
用意したNFCタグを試しに読み込みます。
ファイル名:Read_nfc.py
import binascii
# ICカードの待機
clf = nfc.ContactlessFrontend("usb")
print("カードをかざしてください:")
try:
tag = clf.connect(rdwr={"on-connect": lambda tag: False})
finally:
clf.close()
# ICカードのID情報抽出して表示する
if tag.TYPE == "Type3Tag":
id_info = binascii.hexlify(tag.idm).decode()
elif tag.TYPE == "Type4Tag":
id_info = binascii.hexlify(tag.identifier).decode()
elif tag.TYPE == "Type2Tag":
id_info = binascii.hexlify(tag._nfcid).decode()
print(tag)
ターミナルで以下のように表示されました。
カードをかざしてください:
Type2Tag 'NXP NTAG215' ID=0438EFDA216E81
6. コード(NFCタグに書き込み)
IDの読み込みが成功したら、Symbolアカウントの秘密鍵を書き込んでいきます。
ファイル名:Write_nfc.py
import nfc
import sys
def on_connect(tag):
global data
if tag.ndef is not None:
for record in tag.ndef.records:
print(record)
if tag.ndef.is_writeable:
from ndef import TextRecord
tag.ndef.records = [TextRecord(data)]
print("write complete")
def main():
with nfc.ContactlessFrontend("usb") as clf:
rdwr = {
'on-connect': on_connect
}
clf.connect(rdwr=rdwr)
if __name__ == '__main__':
global data
if len(sys.argv) > 1:
data=sys.argv[1]
print("Put NFC-Tag")
main()
else:
print("Need Record-Text")
ターミナル上で、以下のように実行します。
python Write_nfc.py your_privatekey
your_privtekey部分にアカウントの秘密鍵を入力して下さい。
書き込まれると以下のようにターミナルに出力されます。
Put NFC-Tag
NDEF Text Record ID '' Text '6C7***************************************3664A50799' Language 'en' Encoding 'UTF-8'
write complete
7. コード(NFCタグを読込み・XYM送金)
先ほど、読み込んだ秘密鍵データを元にXYM送金を行います。
ファイル名:nfc_read_and_send_xym.py
import binascii
import nfc
from binascii import unhexlify
from symbolchain.CryptoTypes import PrivateKey
from symbolchain.symbol.KeyPair import KeyPair
from symbolchain.facade.SymbolFacade import SymbolFacade
import http.client
import datetime
class TagTool():
def __init__(self):
pass
def on_rdwr_connect(self, tag):
# タッチ処理
print("on_rdwr_connect:run")
# タグ情報を表示
print(tag)
# IDmの表示
self.idm = binascii.hexlify(tag._nfcid)
#print("IDm : " + str(self.idm))
# 詳細の表示
if tag.ndef:
#print("NDEF Capabilities:")
#print(" readable = %s" % ("no", "yes")[tag.ndef.is_readable])
#print(" writeable = %s" % ("no", "yes")[tag.ndef.is_writeable])
#print(" capacity = %d byte" % tag.ndef.capacity)
#print(" message = %d byte" % tag.ndef.length)
if tag.ndef.length > 0:
print("NDEF Message:")
for i, record in enumerate(tag.ndef.records):
#print("record", i + 1)
#print(" type =", repr(record.type))
#print(" name =", repr(record.name))
#print(" data =", repr(record.data))
#参考:https://qiita.com/nofrmm/items/96eba75085ea2987e28e
mydict = {}
key = str(record.text)
mydict[key] = key
for my_privatekey in mydict :
print(" Text data =",my_privatekey)
#XYM送信に必要な項目を入力
node = "sym-test-04.opening-line.jp"
private_key = my_privatekey
recipient_address = "TAFQVD2HJY55JHFX3L7Q2BPVONS3FLM6VM5QKHQ"
fee = 0.1
amount = 1
msg_txt = "Send from nfc tag!"
#秘密鍵から公開鍵を導出
unhex_privatekey = unhexlify(private_key)
privatekey = PrivateKey(unhex_privatekey)
keypair = KeyPair(privatekey)
publickey = keypair.public_key
#print(str(publickey))
#testnet or mainnet
facade = SymbolFacade("testnet")
deadline = (int((datetime.datetime.today() + datetime.timedelta(hours=2)).timestamp()) - 1667250467) * 1000
#トランザクションを生成
tx = facade.transaction_factory.create({
'type': 'transfer_transaction',
'signer_public_key': publickey,
'fee': int(fee * 1000000),
'deadline': deadline,
'recipient_address': recipient_address,
'mosaics': [{'mosaic_id':0X72C0212E67A08BCE, 'amount':int(amount * 1000000)}],
'message': bytes(1) + msg_txt.encode('utf8')
})
#署名&ペイロード生成(v3.0.3から書き方変更)
signature = facade.sign_transaction(keypair, tx)
json_payload = facade.transaction_factory.attach_signature(tx, signature)
#ネットワークへアナウンス
headers = {'Content-type': 'application/json'}
conn = http.client.HTTPConnection(node, 3000)
conn.request("PUT", "/transactions", json_payload, headers)
responce = conn.getresponse()
print("symbol block chain responce status & reason : " + str(responce.status), str(responce.reason))
#確認
hash = facade.hash_transaction(tx)
print("https://sym-test-04.opening-line.jp:3001/transactionStatus/" + str(hash))
print("on_rdwr_connect:over")
print("END: input Ctrl + C")
return True
def read_tag(self):
print("read_tag:run")
cl = nfc.ContactlessFrontend('usb')
try:
cl.connect(rdwr={'on-connect': self.on_rdwr_connect})
finally:
cl.close()
print("read_tag:over")
if __name__ == '__main__':
tt = TagTool()
for _ in range(1):
tt.read_tag()
ターミナル出力とウォレットで送金を確認します。
read_tag:run
NFCタグをかざしてください:
on_rdwr_connect:run
Type2Tag 'NXP NTAG215' ID=0438EFDA216E81
NDEF Message:
Text data = 6C7***************************************3664A50799
symbol block chain responce status & reason : 202 Accepted
https://sym-test-04.opening-line.jp:3001/transactionStatus/8A7C582F***********917BBE570E4F
on_rdwr_connect:over
END: input Ctrl + C
Ctrl + Cで終了します。
#print()の#を消せば、タグの情報も見ることが出来ます。
8. あとがき
今回は交通系ICカードに代表されるNFCとsymbolを繋げてみました。スマホでのNFC読み取りアプリなどでも読み取ることが可能でした。また、C#やunityでもNFCの取り組みをされている方もいたので詳しい方はやってみてはいかがでしょうか。
9. 引用
NFCpy ドキュメント
NFCpy Github
PythonでSymbol ブロックチェーン上のXYMを送金する。(23年02月)
NFCpyでタグに書き込む
NFCリーダを制御する