はじめに

『DApps開発入門』という本や色々記事を書いているかるでねです。

今回は、異なる暗号方式に対応するため、1つのシードから複数の楕円曲線ごとの鍵を安全に生成・管理できるようにしたHDウォレットの仕組みを提案しているSLIP0010についてまとめていきます!

以下にまとめられているものを翻訳・要約・補足しながらまとめていきます。

他にも様々なEIPについてまとめています。

概要

SLIP0010(Slip Improvement Proposal 0010)は、階層的決定性ウォレット(HDウォレット)において、さまざまな種類の楕円曲線(secp256k1、NIST P-256、ed25519、curve25519)を使って、秘密鍵と公開鍵のペアを生成・派生するための共通の仕組みを定義した提案です。

HDウォレットは、1つのマスター鍵から複数の鍵ペアを階層的に派生させることで、管理の一貫性と利便性を高める仕組みです。 これまでBitcoinのBIP0032によってsecp256k1(Bitcoinで使われる曲線)向けのHDウォレットの派生方式が定義されてきましたが、SLIP0010ではこの仕組みを他の曲線にも対応させることを目的としています。

これにより、異なる暗号アルゴリズムを必要とするアプリケーションでも、安全かつ一貫性のある鍵管理が可能になります。

動機

Trezorなどのハードウェアウォレットでは、ビットコインのような暗号通貨だけでなく、SSHやGPGといった異なる暗号用途にも対応する必要があります。 これらの用途では、secp256k1だけでなく、NIST P-256やed25519などの他の曲線が使われます。

しかし、それぞれの曲線ごとに同じ秘密鍵を使うのはセキュリティ上望ましくありません。 なぜなら、異なる用途で同じ秘密鍵を共有することで、鍵の漏洩リスクや攻撃の影響範囲が広がる可能性があるからです。

そのため、用途や曲線ごとに異なる鍵ペアを確実に生成できる共通の仕組みが必要とされており、それを実現するためにSLIP0010が提案されました。

SLIP0010は、BIP0032の派生方式を汎用化することで、異なる楕円曲線にも対応可能なマスター鍵の派生方法を提供し、セキュリティと互換性を両立させることを目的としています。

鍵生成と階層的派生の仕組み

種々の曲線に対応する鍵生成の背景

Trezorのようなハードウェアウォレットでは、ビットコインやイーサリアムといった暗号通貨の利用だけでなく、SSHやGPGといった他の暗号機能も提供されています。 これらの用途では異なる楕円曲線(例えばNIST P-256やed25519)を使う必要があります。 SLIP0010は、そうした異なる曲線ごとに個別のマスター鍵を生成し、安全に運用できるようにするための標準仕様です。

SLIP0010は、BIP0039やSLIP0039といったニーモニック標準と連携して機能します。 これらのニーモニック(単語の羅列)とパスフレーズをもとに、共通のシード(128〜512ビットのバイト列)を生成し、それを元に曲線ごとのマスター鍵を導出します。

マスター鍵の生成方法

SLIP0010では、各曲線の種類に応じて異なる「HMACの鍵(Key)」を使って、マスター鍵とチェーンコードを導出します。 これはBIP0032と互換性を保ちつつ、曲線ごとの鍵の衝突を避ける工夫です。

例えば、secp256k1の場合は "Bitcoin seed" を、NIST P-256 では "Nist256p1 seed" を、ed25519 や curve25519 ではそれぞれ "ed25519 seed" と "curve25519 seed" をHMACに使用します。

また、ed25519やcurve25519では鍵の数学的構造が異なり、得られたバイト列をそのまま秘密鍵として使います。 これは、従来のように「曲線の生成点にスカラーを掛ける」方法ではなく、「ハッシュをそのまま鍵として使う」方式だからです。 そのため、これらの曲線では公開鍵からの子鍵派生(公開鍵のまま子鍵を導くこと)はできません。

マスター鍵生成アルゴリズムの概要

  1. ニーモニックから生成したシード(S)をもとに、HMAC-SHA512を実行します。 HMACの鍵には曲線ごとに異なる値(例:"ed25519 seed")を使います。
  2. HMACの出力を2つの32バイトに分割し、前半を秘密鍵、後半をチェーンコードとします。
  3. 一部の曲線(secp256k1やNIST P-256)では、秘密鍵が無効な場合(ゼロまたは曲線の次数以上)には再試行します。
  4. ed25519やcurve25519では、どんな32バイト列も有効な秘密鍵となるため、再試行は不要です。

子鍵の生成(Child Key Derivation)

階層的決定性ウォレットの特徴として、マスター鍵から子鍵を順次導出することができます。 これにより、1つの種から複数のアカウントや用途別の鍵を安全に管理できます。SLIP0010では、「親の秘密鍵から子の秘密鍵」または「親の公開鍵から子の公開鍵」を導出する仕組みを定義しています。

ただし、ed25519やcurve25519では、公開鍵からの派生はできず、秘密鍵からのハードンド(hardened)派生のみに対応しています。

秘密鍵からの子鍵派生(CKDpriv)

親の秘密鍵とチェーンコードに加え、インデックス値(i)を使って、対応する子鍵を生成します。

ハードンド派生(i ≥ 2312^{31})の場合、秘密鍵に0x00を付けてHMACのデータとします。 通常派生(i < 2312^{31})の場合は、公開鍵を使います。 ただし、ed25519やcurve25519では通常派生はサポートされません。

出力から得られる32バイトの前半が子鍵、後半が次のチェーンコードになります。ed25519とcurve25519では前半がそのまま秘密鍵として使われます。 それ以外の曲線では、結果が無効な場合(曲線の次数以上など)は再試行されます。

公開鍵からの子鍵派生(CKDpub)

この方式は、ed25519やcurve25519では使用できません。 公開鍵から子の公開鍵を導出できるのは、secp256k1やNIST P-256のような通常の曲線のみです。

通常派生のみがサポートされており、ハードンド派生は公開鍵ではできません。 HMACの出力から生成されるベクトルに対して、親公開鍵との加算によって子の公開鍵が得られます。 無効な鍵になる場合は、再度ハッシュ処理を行い、再試行されます。

BIP-0032との互換性

BIP-0032における課題

BIP0032は、HDウォレット(階層的決定性ウォレット)の鍵派生仕様として広く利用されていますが、その設計上、マスター鍵や子鍵の生成時に無効な鍵が生まれる可能性があります。 例えば、マスター鍵生成時に得られた秘密鍵が楕円曲線の定義域を超えていた場合、その鍵は無効とされ、以降の鍵は未定義状態になります。 同様に、特定のインデックスでの子鍵派生が無効な値になる可能性もあります。

このような事態がsecp256k1では極めて稀(2−1272^{-127}の確率)であるため、現実的な問題にはなりにくい一方で、NIST P-256のような他の曲線では2322^{32}の確率で発生し得るため、実用面での影響が無視できません。

SLIP-0010による仕様拡張

SLIP0010では、上記のような鍵の無効化による不確定性をなくすために、BIP0032の仕様を拡張しています。 特に、NIST P-256のような失敗確率が高い曲線においても、すべてのインデックスで有効な子鍵が定義されるように変更されています。

この改良では、子鍵の派生時に無効な鍵が生成された場合でも、そのインデックスをスキップせず、再度ハッシュ処理を繰り返すことで有効な鍵が得られるまでリトライする仕組みを導入しています。

secp256k1との互換性

secp256k1曲線については、SLIP0010の鍵派生方式は理論的にはBIP0032と完全に一致します。 鍵生成において差異が生じる確率は1 - 2−1272^{-127}より高く、事実上の完全互換と見なせます。

ただし、理論上の話として、SLIP0010を使って資産を受け取ったウォレットのシードを、BIP0032ウォレットに移行した場合、ごくまれに特定の鍵がBIP0032側で無効と判断され、資産が表示されない可能性があります。

一方で、BIP0032で生成されたシードをSLIP0010ウォレットで読み込んだ場合は、SLIP0010が常に鍵を再試行して有効な鍵を生成するためべての資産が正しく認識されます。

最後に

今回は「異なる暗号方式に対応するため、1つのシードから複数の楕円曲線ごとの鍵を安全に生成・管理できるようにしたHDウォレットの仕組みを提案しているSLIP0010」についてまとめてきました! いかがだったでしょうか?

質問などがある方は以下のTwitterのDMなどからお気軽に質問してください!

他の媒体でも情報発信しているのでぜひ他も見ていってください!