はじめに
初めまして。
『DApps開発入門』という本や色々記事を書いているかるでねです。
以下でも情報発信しているので、興味ある記事があればぜひ読んでみてください!
今回は「EIP8030」についてまとめていきます。
EIP8030は、EIP7932で定義される追加署名アルゴリズムのレジストリに、P256署名を0x01として登録する提案です。
これにより、sigrecoverプリコンパイルがP256署名を検証し、公開鍵からEthereumアドレスを導出できるようになります。
概要
EIP8030は、新しいトランザクション型や新しいP256検証プリコンパイルを定義する提案ではありません。
役割は、EIP7932の署名アルゴリズムレジストリに「P256をどう扱うか」を追加することです。
全体像は以下です。
EIP7932は、複数の署名アルゴリズムを1つのsigrecoverプリコンパイルから扱うための土台です。
EIP8030は、その土台にP256用のエントリを追加します。
実際のP256署名検証には、EIP7951のP256VERIFYと同じ検証ロジックを使います。
EIP7932: Secondary Signature Algorithms
[EIP7951] secp256r1プリコンパイルでApple Secure EnclaveやPasskeyをEthereumに繋ぐ仕組みを理解しよう
EIP8030が追加する値は以下です。
| 項目 | 内容 |
|---|---|
| 対象 | P256署名 |
| 署名アルゴリズム種別 | 0x01 |
| 署名コンテナサイズ |
129バイト |
| 検証ロジック | EIP7951のP256Verify
|
| 返す値 | `x |
129バイトの内訳は、先頭1バイトのアルゴリズム種別と、32バイトずつのr、s、x、yです。
P256では公開鍵の復元ではなく、署名コンテナ内に含まれる公開鍵に対して署名を検証します。
動機
EIP7932は、secp256k1以外の署名アルゴリズムをEthereumアドレス導出に使えるようにするための共通レジストリとsigrecoverプリコンパイルを定義します。
ただし、EIP7932本体だけでは各アルゴリズムの詳細までは決めません。
新しいアルゴリズムは、別のEIPでALG_TYPE、署名サイズ、ガスコスト、検証処理を定義する必要があります。
P256は、secp256r1とも呼ばれるNIST標準の楕円曲線です。
Apple Secure Enclave、Android Keystore、FIDO2やWebAuthnの認証器などで広く使われています。
Ethereum実行クライアント側でもEIP7951のP256検証実装があるため、EIP7932の追加アルゴリズムを検証する題材として扱いやすい位置にあります。
EIP8030の狙いは、P256をEIP7932の処理モデルへ接続することです。
P256署名を受け取り、署名データを必要に応じてハッシュし、低いs値を確認し、EIP7951相当の検証を通して公開鍵を返します。
その公開鍵はEIP7932のアドレス導出ルールへ渡されます。
仕様
EIP8030の仕様は、アルゴリズム定数、ガスコスト、署名検証、分離署名の結合、P256Verify関数の扱いに分かれます。
EIP7932のsigrecoverプリコンパイルは、入力の先頭バイトからアルゴリズムを選び、登録された検証処理を呼び出します。
アルゴリズム定数
P256アルゴリズムの定数は以下です。
| 定数 | 値 | 役割 |
|---|---|---|
ALG_TYPE |
Bytes1(0x01) |
EIP7932のレジストリでP256を識別する1バイト値です。 |
SIZE |
129 |
アルゴリズム種別を含む署名コンテナ全体のサイズです。 |
N |
0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551 |
P256の部分群の位数です。 |
署名コンテナは以下の順で構成されます。
| 位置 | サイズ | 内容 |
|---|---|---|
0 |
1バイト |
ALG_TYPEです。P256では0x01です。 |
1..32 |
32バイト | 署名コンポーネントrです。 |
33..64 |
32バイト | 署名コンポーネントsです。 |
65..96 |
32バイト | 公開鍵のx座標です。 |
97..128 |
32バイト | 公開鍵のy座標です。 |
P256の署名は、rとsだけでは公開鍵を復元できません。
そのため、EIP8030の署名コンテナには公開鍵座標も含まれます。
ガスコスト
P256の追加ガスは、EIP7951のP256検証プリコンパイルの6900ガスから、EIP7932の基礎ガス3000ガスを引いた3900ガスを基準にします。
署名データが32バイトではない場合は、keccak256でハッシュする分のコストを足します。
ガス計算は以下です。
def gas_cost(signing_data: Bytes) -> Uint64:
BASE_GAS = Uint64(3900)
if len(signing_data) == 32:
return BASE_GAS
else:
minimum_word_size = (len(signing_data) + 31) // 32
return BASE_GAS + Uint64(30 + (6 * minimum_word_size))
署名データが32バイトなら、すでにハッシュ済みの値として扱われます。
32バイト以外ならkeccak256で32バイトのハッシュへ変換し、そのための追加ガスを計算します。
事前検証
EIP7932のアルゴリズムは、verifyの前にvalidateを呼び出す構造です。
P256では、validateは追加チェックを行いません。
def validate(signature: Bytes) -> None | Error:
pass
P256の署名コンポーネント、公開鍵座標、曲線上の点であることの確認は、verify内で呼び出すP256Verify側に寄せられます。
そのため、EIP8030のvalidateは署名コンテナを事前に分解する処理を持ちません。
検証処理
署名コンテナに含まれる値と検証の関係は以下です。
この図では、EIP7932が受け取る署名コンテナが、方式番号、署名値、公開鍵をまとめて持つことを示しています。
P256では署名だけから公開鍵を復元せず、渡された公開鍵で署名を検証します。
P256署名検証の流れは以下です。
処理は、署名コンテナの分解、署名データのハッシュ、低いs値の確認、P256署名検証、公開鍵の返却という順に進みます。
EIP8030は、公開鍵を復元するのではなく、署名コンテナに含まれるxとyが署名データに対応することを確認します。
検証処理は以下です。
def verify(signature: Bytes, signing_data: Bytes) -> Bytes | Error:
if len(signing_data) != 32:
signing_data = keccak256(signing_data)
signature = signature[1:]
(r, s, x, y) = (
signature[0:32],
signature[32:64],
signature[64:96],
signature[96:128],
)
assert(s <= N / 2)
assert(P256Verify(signing_data, r, s, x, y) == Bytes(
"0x0000000000000000000000000000000000000000000000000000000000000001"
))
return x || y
最初に、signing_dataが32バイトかどうかを確認します。
32バイトではない値は、署名検証前にkeccak256でハッシュされます。
その後、署名コンテナの先頭1バイトを外し、残り128バイトをr、s、x、yへ分割します。
s <= N / 2の確認は、署名の可鍛性を抑えるための制約です。
同じECDSA署名でもsとN - sがどちらも有効になり得るため、高いs値を拒否して表現を1つへ寄せます。
これはEIP2がsecp256k1署名で導入した低いs値の制約に近い考え方です。
EIP2: Homestead Hard-fork Changes
最後に、EIP7951で定義されたP256Verifyと同じロジックへsigning_data、r、s、x、yを渡します。
検証結果が32バイトの1であれば、x || yを連結した64バイト公開鍵を返します。
この公開鍵は、EIP7932のpubkey_to_addressで20バイトアドレスへ変換されます。
分離署名の結合
EIP7932では、署名本体と公開鍵を別々に持っている場合に、アルゴリズムごとの署名コンテナへまとめる関数も定義します。
EIP8030のP256では、分離署名と公開鍵をそのまま連結します。
def merge_detached_signature(detached_signature: bytes, public_key: bytes) -> bytes:
return detached_signature + public_key
ここでdetached_signatureはr || s、public_keyはx || yです。
結合後は、EIP7932の署名コンテナとして使えます。
P256Verify
EIP8030のP256Verifyは、EIP7951で定義されるP256検証プリコンパイルのロジックを指します。
ただし、EIP8030内の関数として使う時は追加でガスを課しません。
ガスはEIP7932のsigrecover側で、アルゴリズムごとのgas_costに基づいて課されるためです。
この分離により、P256の暗号検証ロジックはEIP7951と揃えつつ、EIP7932のアルゴリズムレジストリ上では「P256署名から公開鍵を得る処理」として扱えます。
補足
P256とsecp256k1の違い
Ethereumの通常の署名では、secp256k1曲線が使われます。
一方、P256はsecp256r1とも呼ばれ、スマートフォンやセキュリティキーの認証機構で広く使われています。
EIP7932は、secp256k1以外の署名アルゴリズムも同じsigrecoverプリコンパイルから扱う設計です。
EIP8030は、P256をその最初の追加アルゴリズムとして登録する役割を持ちます。
公開鍵を署名コンテナに含める理由
secp256k1の既存署名では、r、s、y_parityから公開鍵を復元できます。
そのため、署名だけで署名者の公開鍵を取り出せます。
P256では、EIP8030の処理は公開鍵復元ではなく、指定された公開鍵に対する署名検証です。
そのため、署名コンテナにxとyを含め、P256Verifyで署名データと公開鍵の対応を確認します。
32バイト以外の署名データ
P256検証そのものは32バイトのメッセージハッシュを入力にします。
EIP8030では、signing_dataが32バイトではない場合、keccak256(signing_data)を計算してから検証します。
この扱いはEIP7932のsecp256k1アルゴリズムと揃っています。
アプリケーション側は、すでに32バイトのハッシュを渡す場合と、任意長の署名対象データを渡す場合の両方を扱えます。
互換性
EIP8030は、新しいP256アルゴリズムをEIP7932のレジストリへ追加する提案です。
既存のsecp256k1署名、既存のコントラクト、既存のECRECOVERプリコンパイルの挙動は変更しません。
P256署名を使いたい処理だけが、ALG_TYPE = 0x01の署名コンテナを作り、EIP7932のsigrecoverを通じて検証します。
そのため、EIP8030単体で既存アプリケーションの署名方式を置き換えるものではありません。
セキュリティ
EIP8030で重要なのは、P256署名の可鍛性と、公開鍵を署名コンテナに含める設計です。
s <= N / 2の制約により、同じ署名内容に対して高いs値と低いs値の2種類が通る状態を避けます。
これにより、署名のバイト列表現が変わることによる混乱を減らせます。
公開鍵xとyは署名コンテナに含まれるため、検証処理は「この公開鍵がこの署名データへ署名したか」を確認します。
検証に成功した公開鍵だけがEIP7932のアドレス導出へ渡されます。
公開鍵と署名の対応を確認せずにアドレスを導出すると、署名者ではない公開鍵からアドレスを作る危険があります。
EIP8030はP256検証ロジックとしてEIP7951のP256Verifyを使います。
そのため、入力長、rとsの範囲、公開鍵座標の範囲、曲線上の点であること、無限遠点ではないことは、EIP7951側の検証要件と同じ前提で扱われます。
引用
James Kempton (@SirSpudlington), "EIP8030: P256 algorithm support [DRAFT]," Ethereum Improvement Proposals, no. 8030, September 2025. Available: https://eips.ethereum.org/EIPS/eip-8030.
最後に
今回は「EIP8030」についてまとめてきました。
EIP8030は、P256署名をEIP7932の署名アルゴリズムとして登録する提案です。
P256の実際の検証にはEIP7951のP256Verifyロジックを使い、検証に成功した公開鍵をEIP7932のアドレス導出へ渡します。
P256をsigrecoverの共通インターフェースで扱えるようにすることで、セキュアハードウェアやWebAuthn系の署名をEthereumのアドレス導出ルールへ接続しやすくなります。
他でも色々記事を書いているのでぜひよろしければ読んでいってください!


