見出し画像

SIM Appletのhttp通信を暗号化する方法

はじめに

皆さんはSIMアプレットだけでサーバーにデータを送りたいと思ったことはありませんか?
実は、 ETSI TS 102 223 - V17.0.0 にあるように、BIP (Bearer Independent Protocol) を使うことで、TCPやUDPによるデータ送受信ができます。
PCやサーバーのソケット通信のように、SIMアプレットでは端末に対して通信のチャネルを開くことで、端末の通信機能を使ってデータをやりとりします。

さて、実際にデータを送るとなると、TCPでbyteをそのまま送るのではなく、HTTPSでJSONを送りたくなりませんか?(私は送りたいです!)
残念ながら、標準ライブラリである uicc.toolkit.* ではHTTPクライアントは実装されていません。
しかし、HTTPはTCPの上位のプロトコルなので、自前でHTTPクライアントを実装すればHTTP通信はできます。
HTTP/2からはUDPが使用される上に、事実上TLSが必須なので、HTTP/1.1の実装が選択肢に入ります。
HTTP/1.1は RFC 9112 に定義されているので、頑張れば実装できます。
問題は、HTTPSでデータを暗号化する方法です。
HTTPクライアントが無いので、当然HTTPSクライアントもありません。
ルート証明書はインストールされていませんし、頑張ってルート証明書を入れたとしても、HTTPSクライアントを書くのは一苦労です。
ここでは、簡単に共通鍵でbody部分だけ暗号化してみましょう。

暗号化をやってみる

JavaCard上で暗号化するには、 javacard.security.* と、 javacardx.crypto.* を使うことで、AESをはじめとする方式で暗号化できます。
使用する共通鍵は、自分で用意したものでも、SIMに事前に設定されているものでも、どちらでもよいでしょう。

例えば、 dataBuffer のbyte配列をJavaCard上でAES 128bitで暗号化するには、以下のようなコードで行います。

Cipher cipher = Cipher.getInstance(Cipher.ALG_AES_BLOCK_128_CBC_NOPAD, false);
RandomData randomData = RandomData.getInstance(RandomData.ALG_TRNG);
AESKey aesKey = (AESKey) KeyBuilder.buildKey(
		KeyBuilder.TYPE_AES_TRANSIENT_RESET,
		KeyBuilder.LENGTH_AES_128,
		false);

byte[] dataBuffer = JCSystem.makeTransientByteArray(
		(short) 256, JCSystem.CLEAR_ON_RESET);
byte[] encryptedBuffer = JCSystem.makeTransientByteArray(
		(short) 256, JCSystem.CLEAR_ON_RESET);
byte[] ivBuffer = JCSystem.makeTransientByteArray(
		(short) 16, JCSystem.CLEAR_ON_RESET);
		
short paddingLen = (short) (16 - (len % (short) 16));
if (paddingLen == (short) 0) {
    paddingLen = 16;
}
short paddedLen = (short) (len + paddingLen);
Util.arrayFill(dataBuffer, len, paddingLen, (byte) paddingLen);

randomData.nextBytes(ivBuffer, (short) 0, (short) 16);
Util.arrayCopy(ivBuffer, (short) 0, encryptedBuffer, (short) 0, (short) 16);

encryptKey.setKey(aesKey, (short) 0);
cipher.init(aesKey, Cipher.MODE_ENCRYPT, ivBuffer, (short) 0, (short) 16);
cipher.doFinal(dataBuffer, (short) 0, paddedLen, encryptedBuffer, (short) 16);

あとは encryptedBuffer をサーバーに送信すれば、安全にデータをやりとりできます。

ちなみに、 Cipher.ALG_AES_BLOCK_256_CBC_NOPAD などの強度の高いbit数は、deprecatedになっています。

今回のbody暗号化機能付き簡易HTTPクライアントは、後日GitHubで公開予定です。
お楽しみに!

おわりに

コモン・クリエーションは一緒にSIM Applet事業を作っていける仲間を募集しています。 現在募集中のポジションはこちらからご確認いただけます。

noteを読んでいただいた皆さんと一緒にお仕事できる日を楽しみにしています。