クマは森で用を足しますか?

アウトプットは重要です。

Python3では動かないんですか?

SIMツールキット用アプレットのサンプルコードからcapファイルを生成できたので、wikiに記載されている手順に従ってsysmoUSIM-SJS1 4FFにインストールします。

cheerio-the-bear.hatenablog.com

ここから少し手間がかかります

アプレットのロードからインストールまでを行なうコマンドは、こうなります。wikiで紹介されているコマンドの、capファイルとKIcとKIDを差し替えただけのものです。

$ python shadysim.py --pcsc -l ../../hello-stk/build/javacard/org/toorcamp/HelloSTK/javacard/HelloSTK.cap -i ../../hello-stk/build/javacard/org/toorcamp/HelloSTK/javacard/HelloSTK.cap --enable-sim-toolkit --module-aid d07002ca44900101 --instance-aid d07002CA44900101 --nonvolatile-memory-required 0100 --volatile-memory-for-install 0100 --max-menu-entry-text 15 --max-menu-entries 05 --kic 9A665E9CDA096DAE9C04894785EB0B18 --kid 1A8DD88431450CAF8D3719F6380F0A18

ツールのソースコードこちらから参照できますが、これが全然ダメでした。Pythonについてはあまり明るくなかったのですが、2.xと3.xの間でかなり互換性を失っているんですね。2to3.pyを使ってある程度コンバージョンできたようですが、幾らか基本的なエラーが残ります。でも、開発環境にはPython 3.7.0を入れてしまったことですし、良い機会なのでこのまま動くようにしてみましょう。

TypeError: %x format: an integer is required, not float

整数が入るべきところに、小数が入っちゃってるそうです。

Traceback (most recent call last):
...
  File "shadysim.py", line 142, in send_wrapped_apdu_internal
    envelopeData = ('%04x' % (len(envelopeData) / 2 + len_sig)) + envelopeData
TypeError: %x format: an integer is required, not float

Pythonって、バージョンが変わると演算子の機能も変わっちゃうんですね。知らなかったので、斬新な感じでした。

    envelopeData = ('%04x' % (len(envelopeData) / 2 + len_sig)) + envelopeData

端数を繰り上げて整数にします。

    envelopeData = ('%04x' % (len(envelopeData) // 2 + len_sig)) + envelopeData

TypeError: can only concatenate str (not "bytes") to str

「バイト列」を「文字列」に繋げようとしたそうです。

Traceback (most recent call last):
...
  File "shadysim.py", line 157, in send_wrapped_apdu_internal
    envelopeData = part_cnt + binascii.b2a_hex(ciph[len(ciph) - 8:]) + data;
TypeError: can only concatenate str (not "bytes") to str

なるほど、binascii.b2a_hex()が16進表現のバイト列なので、その他の文字列に繋げられないんですね。

    envelopeData = part_cnt + binascii.b2a_hex(ciph[len(ciph) - 8:]) + data;

こうすればいいでしょうか。

    envelopeData = part_cnt + str(binascii.b2a_hex(ciph[len(ciph) - 8:]), 'utf-8') + data;

AttributeError: 'bytes' object has no attribute 'encode'

encode()が使えなくなったんだそうです。

Traceback (most recent call last):
...
  File "shadysim.py", line 313, in generate_load_file
    data = header.encode("hex")
AttributeError: 'bytes' object has no attribute 'encode'

エラーを出しているのは、これですね。

    data = header.encode("hex")

また16進表現のバイト列にしてから、それを文字列にします。あれ。さっきのもhexlify()で良さそうですね。

    data = str(binascii.hexlify(header), 'utf-8')

もう少しだけ微調整してパッケージも追加して

print文に括弧をつけたり、足りないパッケージを追加インストールしたり。そうこうしているうちに、アプレットのロードからインストールまでを行なうコマンドを実行しても、エラーが出力されないようになりました。

この時点で、入っているパッケージはこんな感じ。Cryptoを解決するためにpycryptodomeを、smartcardを解決するためにpyscardを追加したんだと思います。

$ pip list

Package      Version
------------ ---------
certifi      2018.8.24
chardet      3.0.4
idna         2.7
lxml         4.2.5
Naked        0.1.31
pip          18.1
pycryptodome 3.6.6
pyscard      1.9.7
python-docx  0.8.7
PyYAML       3.13
requests     2.19.1
setuptools   39.0.1
shellescape  3.4.1
urllib3      1.23

できあがったものはこちら

動くようになりましたが、さらに遊んでいるうちに壊してしまうかもしれません。Python 3.7.0で動くようになったツールを、GitHubに預けておくことにしました。

github.com