🦔

Hedgehog 【open-source, client-side Ethereum wallet】vo1

2023/02/11に公開

はじめに

HedgehogとはAudius社が開発している、Metamaskを使用することなくウォレットの作成・トランザクションの実行などを行うためのパッケージです。Defiなど高額の金銭が取引されるdAppsでは組み込みが難しいようですが金銭的取引が少ない、もしくはないものであればdApps構築のお手伝いをしてくれます。(それこそAudiusとか)
何回かに分けてHedgehogのドキュメント・ソースコードを読み解きながら、簡単な実装まで行ってみます。
https://hedgehog.audius.org/

公式ドキュメント

Hedgehogはnpm(node package manager)として利用可能、ソースコードもGithubから公開されています。最初から読んでいくこともできますが、まずはドキュメントで概要を掴んでみます。
https://audiusproject.github.io/hedgehog-docs/#installation

概要

Hedgehogはユーザーのエントロピー(秘密鍵の元)を作成・管理できる機能を提供しています。npmとしてフロント側からバックエンドサーバのREST APIとやり取りを行います。

REST APIとは?
Hedgehogは一連のアーティファクトをMyEtherWalletなどと同じように生成しデータベースに保存します。秘密鍵についてはクライアントサイドで管理します。
https://www.myetherwallet.com/

ウォレットの作成

ウォレットはBIP-39の仕様に添ったウォレットシードとエントロピーの生成から作成されます。
BIP-39が分からないので調べてみると、メタマスクなどのリカバリーフレーズとウォレットを紐付けているプロトコルだとの理解ができました。概要を知るには以下の記事がかなり分かりやすいです。
https://www.ledger.com/academy/bip-39-the-low-key-guardian-of-your-crypto-freedom
エントロピーを用いることで、BIP-32の仕様に添ったウォレットを導出することができます。ここでもBIP-32がわからないので調べてみます。

BIP32(階層的決定性ウォレット)は、マスターとなる128bitsのエントロピーからなるシード値から、m/i/0/kのような階層構造で決定論的に秘密鍵を生成できる汎用性の高いウォレット管理プロトコルの標準規格で、英語では Hierarchical Deterministic Wallet(HD Wallet)と言います。
https://bitbank.cc/glossary/bip0032 より)

以下の記事が分かりやすく、概要を掴むことができました。
https://blockchain.gunosy.io/entry/2017/12/21/165314

エントロピーはlocalStorageに保存され、他にもいくつかの値が同時に生成されています。

https://audiusproject.github.io/hedgehog-docs/#wallet-creation
難しく理解が追いつかないのでDeepLの力を借りて、何となく理解しておきます。

ヘッジホッグはエントロピーに加えて、初期化ベクトル(iv)、lookupKey、およびcipherTextを生成する。これらの3つの値は、データベースに安全に保存され、ユーザーを認証するためにサーバーから取得することができる。ivはユーザーごとに生成されるランダムな16進文字列で、認証を安全に行うためのものである。lookupKeyは、ユーザ名とパスワードに、あらかじめ定義された一定の初期化ベクトル(データベースに格納されているivとは異なる)を組み合わせたものである。この lookupKey は、cipherText と iv の値を取得するためのデータベース内の主キーとして機能する。cipherText は iv と aes-256-cbc 暗号を使用して生成され、scrypt を使用してユーザーのパスワードと iv の組み合わせから得られるキーがエントロピーを保存する。

エントロピーはcipherTextに格納されているので、ivと鍵(ユーザーのパスワードとivのscrypt)が分かれば、そこから導出することができる。エントロピーは復号化された後、ブラウザ上でローカルのethereumjs-walletオブジェクトに格納されるとともに、localStorageにも格納されます。暗号化と復号化のプロセスはクライアントサイドのみで行われ、ユーザーのパスワードやエントロピーが最初に暗号化されることなくブラウザから離れることはない。

ウォレットの状態にアクセスし、変更するための関数のAPIについては、APIセクションを参照してください。

ウォレットの永続性

ウォレット情報はバックエンド側で保持することになりますが、技術的制約はないので開発者は自身が好きなものを使用することができます。
ただしデータベース設計をする上で認証情報とユーザー情報のテーブルを分けることを意識する必要があります。lookupkeyはivとユーザー名、ウォレットアドレスの組み合わせによって作成されているため、DBの情報が外部に公開されてしまった場合レインボーテーブルアタックを受けてしまう可能性が増加するからです。
レインボーテーブルとは?

安全性

安全性の面ではいくつかの点に考慮する必要があります。

  1. エントロピーをlocalStorageに保存することによる問題
    例えばストレージに保存してあるキーを片っ端からサードパーティサーバーに投げることで、悪意あるトランザクションを承認させようとするなどの方法が挙げられます。
  2. ユーザー名を認証情報のテーブルに紐付けない
    認証情報と関連付けられるとRainbow table attackが増加する危険があります。
  3. サーバーサイド
    サーバーが侵入や悪意のある使われ方をしてしまった場合、力任せに認証アーティファクトを解読するには多くのリソースが必要になります。ただ理論上は可能であるため、それに見合う価値のあるものはHedgehogの導入には向きません。(Defi関連など)

注意点

万が一ユーザーがパスワードを紛失してしまった場合にはアカウントを回復することはできません。なぜならエントロピーはクライアント側で暗号化されてからサーバーに送られるため復元する方法がないからです。

最後に

今回は公式ドキュメントから概要の部分をご紹介しました。次回以降自分でもパッケージを入れて触ってみたいと思います。

Discussion