Fragments of verbose memory

冗長な記憶の断片 - Web技術のメモをほぼ毎日更新

Feb 26, 2026 - 日記

ERC-8004 + ERC-8128 = SIWA: AIエージェント認証スタックの2層構造を解剖する

ERC-8004 + ERC-8128 = SIWA: AIエージェント認証スタックの2層構造を解剖する cover image

前回の記事 で、ERC-8004 (Trustless Agents)がAIエージェントの「信頼の発見」をどう解決するかを見ました。Identity Registry、Reputation Registry、Validation Registryの3層で「このエージェントを信頼していいか」を判断できる、という話でした。

ただ、読んでいて気になっていた問題が一つ残っていました。「信頼できるエージェントだとわかった。でも、届いたHTTPリクエストが本当にそのエージェントから来たものかどうか、どうやって確認するの?」という問いです。

ERC-8128 (Signed HTTP Requests with Ethereum)は、その問いへの答えです。2026年1月に公開されたドラフトで、EthereumアカウントでHTTPリクエストに署名する標準を定義しています。

問題の整理: 2つの「信頼」

ERC-8004とERC-8128が解決する問題は、実は別々のレイヤーにあります。

問い担う規格
このエージェントを信頼していいかERC-8004(Identity + Reputation + Validation)
このリクエストは本当にそのエージェントからかERC-8128(HTTPリクエスト署名)

現状のAIエージェント認証の典型的な問題は、APIキーをエージェントのランタイムに直接埋め込むことです。エージェントが侵害されると、APIキーも漏洩します。また、「このAPIキーを持っているエージェントが、ERC-8004で登録されたあのエージェントと同一人物か」を確認する手段がありません。

ERC-8128はこの問題を、「リクエストそのものに暗号署名を付ける」ことで解決します。

ERC-8128の技術的核心

RFC 9421との関係

ERC-8128は、IETFの標準である RFC 9421 (HTTP Message Signatures)をベースにしています。RFC 9421はHTTPリクエストの特定の構成要素を選んで署名する仕組みを定義していますが、署名アルゴリズムは規定していません。ERC-8128はそこにEthereum署名(EIP-191personal_sign)を組み合わせたプロファイルです。

署名対象(Signature Base)はこんな形になります。

1
2
3
4
5
6
7
8
9
"@authority": api.example.com
"@method": POST
"@path": /orders
"@query": ?market=ETH-USD
"content-digest": sha-256=:X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE=:
"@signature-params": ("@authority" "@method" "@path" "@query" "content-digest");
  created=1618884473;expires=1618884533;
  nonce="abc123";
  keyid="erc8128:1:0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"

このバイト列をEIP-191のpersonal_signで署名し、Signature-InputSignatureヘッダーに付けてリクエストを送ります。

1
2
3
4
5
6
7
8
POST /orders HTTP/1.1
Host: api.example.com
Content-Type: application/json
Signature-Input: eth=("@authority" "@method" "@path" "content-digest");created=1618884473;expires=1618884533;nonce="abc123";keyid="erc8128:1:0xd8dA..."
Signature: eth=:MEUCIQDXtPCJ5...base64...:
Content-Digest: sha-256=:X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE=:

{"amount": "100"}

サーバー側はkeyidからEthereumアドレスを取り出し、EOA(外部所有アカウント)ならecrecoverで、SCA(スマートコントラクトアカウント)ならERC-1271isValidSignatureで検証します。

なぜEIP-712ではなくEIP-191か

仕様書に明確に理由が書かれています。EIP-712は構造化データの署名に最適化されており、ウォレットのUIで人間が読める形式で表示するために設計されています。しかしHTTPリクエストの署名は機械間通信が主用途で、署名対象はハッシュ、nonce、タイムスタンプなど人間が読んでも意味のない値が並びます。

EIP-191は任意のバイト列を署名できるため、RFC 9421のSignature Baseをそのまま署名できます。EIP-712を使うと、RFC 9421のSignature Baseを「型付きデータ」として再エンコードする追加レイヤーが必要になり、RFC 9421の汎用ツールとの互換性が下がります。

セキュリティモデルの逆転

ERC-8128で面白いのは、セキュリティポリシーの決定権がサーバーからクライアントに移る点です。

従来のAPI認証では、サーバーがトークンを発行し、スコープを定義し、有効期限を管理します。ERC-8128では、クライアント(エージェント)が「何を署名するか」「リプレイ可能にするか」を選択します。

この選択は2つの軸で表現されます。

Request Binding(リクエスト束縛)

  • Request-Bound: @authority@method@path@querycontent-digestをすべて署名。特定の1リクエストにのみ有効。改ざんすると検証失敗。
  • Class-Bound: 一部のコンポーネントのみ署名。「このドメインへの全GETリクエスト」のような広い認可が可能。

Replay Protection(リプレイ保護)

  • Non-Replayable: nonceパラメータを含める。サーバーはnonceの一意性を強制する必要がある。
  • Replayable: nonceを省略。有効期限内なら再利用可能。

すべての準拠実装は「Request-Bound + Non-Replayable」を受け入れなければなりません。これがベースラインです。クライアントが最強のセキュリティ設定を選べば、どの準拠サーバーとも通信できることが保証されます。

ERC-8004との組み合わせ: 2層の役割分担

2つの規格がどう連携するかを、シーケンス図で整理します。

sequenceDiagram
    participant Agent as AIエージェント
    participant Server as APIサーバー
    participant Registry as ERC-8004
Identity Registry participant Chain as Ethereum Note over Agent,Chain: Phase 1: Identity Verification(初回のみ) Server->>Registry: agentId=42 の情報を取得 Registry-->>Server: 登録ファイルURL、supportedTrust Server->>Server: Reputation / Validation スコアを確認 Note over Agent,Chain: Phase 2: Request Authentication(毎リクエスト) Agent->>Agent: RFC 9421 Signature Baseを構築 Agent->>Agent: EIP-191で署名 Agent->>Server: POST /api/task
Signature-Input: eth=...
Signature: eth=:... Server->>Chain: keyidのアドレスを検証
(EOA: ecrecover / SCA: ERC-1271) Chain-->>Server: 署名有効 Server-->>Agent: 200 OK

ERC-8004は「このエージェントIDを持つエンティティを信頼していいか」を判断するための情報を提供します。ERC-8128は「このHTTPリクエストが、そのエンティティのEthereumアドレスの秘密鍵で署名されたか」を検証します。

2つを組み合わせることで、「ERC-8004で信頼を確認したエージェントのアドレスと、リクエストの署名者が一致するか」を確認できます。これが、APIキーでは実現できなかった「エージェントの同一性確認」です。

SIWA: 2つの規格を統合した実装

SIWA (Sign In With Agent)は、ERC-8004とERC-8128を組み合わせた実用的なSDKです。Builders Garden が開発したオープンソースプロジェクトで、2026年2月に公開されました。

SIWAの設計で重要なのは、秘密鍵がエージェントのランタイムに渡らない点です。

flowchart LR
    subgraph Agent["AIエージェントランタイム"]
        Runtime["タスク実行"]
    end

    subgraph KeyProxy["署名プロキシ(外部)"]
        Signer["秘密鍵"]
    end

    subgraph Onchain["オンチェーン"]
        ERC8004["ERC-8004
Identity Registry"] end Runtime -->|"署名リクエスト"| KeyProxy KeyProxy -->|"署名済みメッセージ"| Runtime Runtime -->|"ERC-8128署名付きHTTP"| Server["APIサーバー"] Server -->|"NFT所有確認"| ERC8004

エージェントは「署名してほしい」とプロキシに依頼するだけで、秘密鍵には触れません。Privy、Bankr、Circleなど既存のウォレットプロバイダーを署名プロキシとして使えます。

エージェント側の実装

@buildersgarden/siwaパッケージを使うと、認証フローをこう書けます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
import { signSIWAMessage } from "@buildersgarden/siwa";
import { createLocalAccountSigner } from "@buildersgarden/siwa/signer";

// ウォレットは外部プロバイダーでも秘密鍵でも可
const signer = createLocalAccountSigner(account);

// Phase 1: ERC-8004のIDを使ってSign-In
const { message, signature } = await signSIWAMessage({
  domain: "api.example.com",
  uri: "https://api.example.com/siwa",
  agentId: 42,                              // ERC-8004のエージェントID
  agentRegistry: "eip155:84532:0x8004...", // どのレジストリに登録されているか
  chainId: 84532,
  nonce,
  issuedAt: new Date().toISOString(),
}, signer);

// Phase 2: 以降のリクエストはERC-8128で署名(SDKが自動処理)

サーバー側の実装

サーバーは2つのことを検証します。ERC-8004でNFT所有を確認し、ERC-8128で署名を検証します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
import { verifySIWA } from "@buildersgarden/siwa";
import { createPublicClient, http } from "viem";
import { baseSepolia } from "viem/chains";

const client = createPublicClient({
  chain: baseSepolia,
  transport: http(),
});

const result = await verifySIWA(
  message,
  signature,
  "api.example.com",
  { nonceStore },
  client,
);

// result.valid: 署名が有効か(ERC-8128の検証結果)
// result.agentId: ERC-8004のエージェントID(レピュテーション確認に使える)
// result.address: 署名者のEthereumアドレス

result.agentIdを使えば、ERC-8004のReputation Registryを参照して「このエージェントのスコアが閾値以上か」を追加チェックすることもできます。

技術的なトレードオフ

nonce管理のステートフルネス

Non-Replayableを選択すると、サーバーは(keyid, nonce)のペアを有効期限まで保持する必要があります。これはサーバーをステートフルにします。

水平スケールする環境では、nonce storeを共有する必要があります。SIWAのSDKはcreateMemorySIWANonceStore()(インメモリ、単一インスタンス向け)を提供していますが、本番環境ではRedisなどの共有ストアが必要です。

ERC-8128の仕様書はこの問題を正直に認めています。expires - createdがサーバーのnonce保持期間を超えるリクエストは拒否しなければならない、と明記されています。「Non-Replayable」という保証が成立するのは、サーバーがその期間中nonceを保持できる場合に限られます。

SCA検証のレイテンシ

EOAの検証はecrecoverで完結するため、オフチェーンで即座に処理できます。一方、SCA(スマートコントラクトアカウント)の検証はERC-1271のisValidSignatureを呼び出すため、オンチェーンのRPCコールが必要です。

高頻度のAPIリクエストでSCAを使う場合、このレイテンシが問題になる可能性があります。ERC-8128の仕様書では、Replayableモードでの検証結果キャッシュを許容していますが、その場合はリプレイ保護が弱まるというトレードオフがあります。

マルチチェーンのレピュテーション集約

keyiderc8128:<chainId>:<address>形式で、チェーンを明示します。ERC-8004のレジストリもチェーンごとに独立しています。

あるエージェントがEthereumメインネットとBaseの両方にERC-8004 IDを持っている場合、レピュテーションはチェーンごとに別々に蓄積されます。「Ethereumで高評価のエージェントがBaseでも同じか」を確認するには、両方のチェーンのデータを別途集計する必要があります。この集約は現時点では仕様外です。

まとめ: 「誰か」と「本物か」の分離

ERC-8004とERC-8128が解決する問題を改めて整理すると、こうなります。

問い解決する規格手段
このエージェントは誰かERC-8004 Identity RegistryNFT(ERC-721拡張)
信頼できる実績があるかERC-8004 Reputation Registryオンチェーンフィードバック
仕事の質は保証されるかERC-8004 Validation RegistryzkML / TEE / 再実行
このリクエストは本物かERC-8128RFC 9421 + EIP-191署名
秘密鍵を漏らさずに認証できるかSIWA署名プロキシパターン

Web2の認証スタックに対応させると、ERC-8004はOAuth(アイデンティティの発見と信頼)、ERC-8128はJWT(リクエストの認証)に相当します。ただし決定的に違うのは、JWTはサーバーが発行するのに対して、ERC-8128の署名はクライアントが生成するという点です。サーバーは「発行者」ではなく「検証者」に徹します。

SIWAはまだwork in progressで、本番利用には注意が必要です。ただ、ERC-8004とERC-8128という2つの規格が組み合わさると何ができるかを示す、具体的な実装例として参考になります。

エージェント経済のインフラがどう整備されていくか、引き続き追いかけていきたいと思います。

参考リンク