Closed7

ETHGlobalTokyo上位チーム勝手に解説 Myna

kozayupapakozayupapa

マイナンバーカードとWalletの紐付け

Demoをみていて、分かりやすい マイナンバーカードをつかったWallet管理
https://ethglobal.com/showcase/myna-uxzdd

上記リンク先のプロジェクトの説明も分かりやすいです。

Myna browser wallet enables Japanese residents to use their My Number Card like a hardware wallet, giving them a simple and safe way to self-custody their crypto and send/receive payments with just a few taps of their card.

EIP-4337 compliant contract wallets are generated for each My Number Card, abstracting away the wallet creation process for users, and enabling features such as social recovery. This will empower Japanese residents to securely transfer wallet ownership during any emergency situation.

とのことなので、 EIP-4337を理解しながら コードを読んでいきたいと思います

動作概要

  • My Number Card:

    • The My Number Card is a NFC-type B card and it stores a RSA keypair.
  • Wallet generation:

    • he NFC reader sends the My Number Card public key to our Browser Wallet via Web Bluetooth.
    • The browser wallet software deterministically calculates the ERC-4337 compliant contract wallet address based on My Number Card public key, even before deploying the contract wallet, and can receive payments.
  • Send transaction:

    • Browser requests a signature of the transaction from the contract wallet (User Operation) to My Number Card.
    • User enters PIN and taps My Number Card onto NFC reader to generate User Operation signature.
    • ERC-4337 compliant smart contract verifies the RSA signature and executes the operation.

こちらのコードは下記リポジトリで公開されています。
https://github.com/a42io/ETHGlobalTokyo2023

kozayupapakozayupapa

Repository 構成

  • BrowserWallet/
    • bootstrap, jquery, ethres, navigator.bluetooth を利用したシンプルなwebapp
  • DappExample/
  • MynaSigner/
    • android app: my number から呼び出したり、署名をするアプリ browserとbluetoothでつながる
  • MynaWalletExtension/
    • browser extension : wallet との接続をFookするために必要?
  • Server/
    • Node express server :contract address, nonce, UserOperationCallData 生成, transaction実行等
  • playground/test-contract/src/samples
    • Smart Contract : SimpleAccount, SimpleAccountFactory
kozayupapakozayupapa

マイナンバー読み込みのためのセットアップ

Demoで、 PCにはNFCリーダがないので、スマホとBluetoothで接続して マイナンバーカードの読み取りを行っていると説明していました。

Web bluetooth ?

BrwowserWallet の下記の部分でbluetoothデバイスに接続に言っています。

main.js
async function connectMynaSigner() {
	mynaSigner.device = await navigator.bluetooth.requestDevice({
		filters: [{
			services: [SERVICE_UUID]
		}]
	});

BrowserWalletのrun.sh で local server を立ち上げて
ConnectMynaSignerボタンを押すと デバイスをスキャンする画面は立ち上がります。ただ、iphoneでマイナンバーカードを読んでも、androidでマイナンバーカードを読んでも一向にデバイスに出てこない。

対応するandroid app を準備する

よくよく上記web のコードを見てみると SERVICE_UUID でフィルターしています。
対応するUUIDでグレップすると下記のソースコードが出てきました。
MynaSigner という専用のAndroidAppのみと通信する前提なんですね。

MainActivity.kt
    private fun createBlePeripheral() {
        if (ActivityCompat.checkSelfPermission(
                this, Manifest.permission.BLUETOOTH_CONNECT
            )
            != PackageManager.PERMISSION_GRANTED
        ) {
            return
        }

        btManager = getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager

        btGattServer = btManager.openGattServer(this, btGattServerCallback)

        btGattService = BluetoothGattService(SERVICE_UUID, BluetoothGattService.SERVICE_TYPE_PRIMARY)

久しぶりにAndroidStudioをDownloadして、AppをBuild、 
手持ちのAndroidPhoneのOSが古すぎたので Permission, target version等を微修正してインストールしました。

web blue tooth 規格化状況

web bluetooth という仕組みもはじめて使うのでその設定が問題なのかなとも調査しました。面白い技術ですがAppleさんのセキュリティ上の懸念とうもあり一般のWebページで使える日がくるかどうかはわかりません

ここのマイナンバーと連携させる部分は開発のしやすさでweb app, bluetoothにしているのだと思いますが、
今後の普及させていくフェーズにはいると android, ios のアプリとして作っていくのだろうと予想しました。

kozayupapakozayupapa

コードの中の重要箇所解説

MynaSigner(AndroidApp)

MynumberからRSA pubkey をよみとるのは下記のコード
https://github.com/ishihatta/mynacard-android-demo/blob/main/app/src/main/java/com/ishihata_tech/myna_card_demo/myna/JpkiAP.kt

このなかで使用しているのは下記の部分です。

class JpkiAP(private val reader: Reader) {
    fun lookupAuthPin(): Int {
        reader.selectEF("0018".hexToByteArray()) // JPKI認証用PIN
        return reader.lookupPin()
    }

    fun verifyAuthPin(pin: String): Boolean {
        reader.selectEF("0018".hexToByteArray())
        return reader.verify(pin)
    }

....
    fun readAuthCertificate(): X509Certificate {
        return readCertificate("000A".hexToByteArray())
    }
...

    fun authSignature(nonce: ByteArray): ByteArray {
        reader.selectEF("0017".hexToByteArray()) // JPKI認証用秘密鍵
        return reader.signature(nonce)
    }
}

この"0018"とか"000A"とか、気になりますよね。
これはそもそもマイナンバーカードにどんな情報が入っているのかの理解が必要です。
下記でとても丁寧に解説してくれています。
https://www.jnsa.org/seminar/pki-day/2017/data/170419_hamano.pdf

ちょっと理解が難しいですが2種類の証明書がはいっていて引用すると下記のように使い分けるようです。

公的個人認証APには従来の住基カードに含まれていた署名用証明書に加え、新たに認証用証明書が格納されています。
署名用証明書は銀行口座の開設など、これまで免許証で本人確認していたビジネスシーンで名前や住所を証明する為に利用できます。
一方、認証用証明書はWebサイトなどにログインする用途で利用する事が想定されていますが、今回の様にSSHやPAM、PGP、Windowsログオン、無線LANの認証(WPA-EAP-TLS)で利用することもできるでしょう。

今回Walletにつかうには認証用証明書 EF000Aを読めばよいということですね!

補足

この解説資料を作ってくれている人が、OpenSC(Open source smart card tools and middleware)という
世界で進んでいる各国電子ID用のスマートカードミドルウェアにPullReqを送って、日本のマイナンバーの普及を応援しているというのも知りました。 素晴らしい活動ですね。

下記にもマジックナンバーしっかり定義されていました
https://github.com/OpenSC/OpenSC/pull/801/files#

src/libopensc/jpki.h
#define JPKI_AUTH_KEY "0017"
#define JPKI_AUTH_PIN "0018"

#define JPKI_SIGN_KEY "001A"
#define JPKI_SIGN_PIN "001B
このスクラップは2023/05/06にクローズされました