AIエージェント間通信の署名検証にERC-8128を使う理由と仕組み
目次
DEVに「Verifiable AI Agent Communications with ERC-8128 Message Signing」という記事が出ていて、AIエージェントが暗号資産を保有して自律的に取引するときの通信を、Ethereumの署名標準で検証するという話だった。
切り口は新しいが、ERC標準・メッセージ署名・nonceやtimestampあたりを既知前提で書かれているので、Web3の中身は詳しくない側からだと前提知識が足りない。
ここでは基礎から積み上げて、ERC-8128が何を解決するか、APIキーやOAuthと何が違うかを整理する。
前提となる用語をざっと
ERC-8128の話の前に、Web3まわりで暗黙に使われがちな用語だけ先に並べておく。
ニュースで聞いたことはあっても中身は曖昧、というレベルの語をまとめている。
| 用語 | 中身 |
|---|---|
| ブロックチェーン | 取引履歴を時系列で繋いだ改ざんしにくい台帳。世界中のノード(参加コンピュータ)が同じコピーを持ち、過去のデータを書き換えるには全ノードを書き換える必要があるので実質改ざんできない |
| Bitcoin | 世界で最初に普及したブロックチェーン。基本は「誰から誰へいくら送ったか」を記録する仕組みで、デジタル通貨としての用途に特化している。プログラムは載せられない |
| Ethereum | Bitcoinの後発で、お金の送金だけでなく「プログラム」を載せて動かせるように拡張したブロックチェーン。ERC標準が定義されている主戦場で、NFTやAIエージェント用途も基本ここで進む |
| スマートコントラクト | Ethereum上に置かれる自動実行プログラム。条件を満たすと送金や記録更新が自動で走る。一度デプロイすると基本的に書き換えられない |
| トークン | スマートコントラクトが管理する識別子付きの値。お金として使える代替可能トークン(ERC-20)と、1点物として扱う代替不可能トークン(ERC-721 = NFT)に大別される |
| ウォレット | 秘密鍵を持って署名するためのソフト・ハード。ChromeのMetaMaskやハードウェアのLedgerなどが代表例 |
| ウォレットアドレス | 公開鍵から導出されるID。 0x で始まる40文字の16進数。銀行口座番号のように公開してOK |
| ガス代 | スマートコントラクトを実行するための手数料。実行内容が重いほど高くなる |
| IPFS | 中央サーバなしでファイルを共有する分散ストレージ。NFTの画像は多くがここに置かれる |
ここまで頭に入っていれば、後の話は読みやすくなる。
「ブロックチェーン上に何かが載っている」と言ったとき、実際に載っているのは台帳の数字と識別子だけで、画像や動画そのものは別の場所にある、という感覚を持っておくと混乱しにくい。
そもそもERCって何
ERCは Ethereum Request for Comments の略。
Ethereum上で使う共通仕様の番号付き提案で、IETFのRFCに近い立ち位置にある。
誰でも草案を出せて、議論を経てFinalになると標準として扱われる。
代表的なものを並べると、何のための番号かが見えやすい。
| 番号 | 内容 | 身近な例 |
|---|---|---|
| ERC-20 | 代替可能トークン(同じ価値で交換できる) | USDCのようなステーブルコイン |
| ERC-721 | 1点物トークン(NFT) | 「世界に1枚」を売るNFTマーケット |
| ERC-1155 | 1コントラクトで複数種類のトークンを扱う | ゲーム内アイテムをまとめて発行 |
| ERC-4337 | スマートコントラクトを使ったアカウント抽象化 | 秘密鍵に縛られない柔軟なウォレット |
| ERC-8128 | エージェント通信向けのメッセージ署名 | 今回の本題 |
NFTマーケットを作ったことがあるなら、画像にトークンを紐づけて売っていたあの規格がERC-721だった、と思い出すと位置が掴みやすい。
ERC-8128はそれと同じ系譜で、「エージェントが他のエージェントに送るメッセージ」を扱うために増えた標準だ。
NFTの中身をざっくり
ERC-721の名前が出たので、NFTの中で何が起きているのかを軽く押さえておく。
ニュースだと「画像が高額で売れた」「権利が記録される」のような取り上げ方が多く、実装側の感覚と一般のイメージがけっこうずれている。
実際には画像販売以外の用途も多くて、たとえば次のようなものがある。
| 用途 | 例 |
|---|---|
| デジタルアート | Beeple、CryptoPunks のような画像コレクション |
| IPコラボのゲームアイテム | キャプテン翼 RIVALS、Sorare のサッカー選手カード |
| スポーツの瞬間 | NBA Top Shot のハイライト動画 |
| ゲーム内キャラクター | Axie Infinity の対戦用キャラ |
| 会員権・チケット | クラブ会員権、限定イベント入場権 |
画像コレクション系のニュースが目立つせいで「NFT = アート画像」のイメージが強いが、規格としてはIPコラボのカードゲーム・スポーツ・ゲーム内資産といった分野でもそれなりに残っている。
NFTは Non-Fungible Token の略で、日本語だと「代替不可能トークン」になる。
Fungibleかどうかは、お札と切手の違いで考えると分かりやすい。
| 種類 | 例 | 1つ1つの区別 |
|---|---|---|
| Fungible(代替可能) | 1万円札、USDC、ビットコイン | 区別不要、同じ単位で交換できる |
| Non-Fungible(代替不可) | 切手の発行番号、コンサートの座席指定券、NFT | それぞれが固有のIDを持ち、同じ価値で交換できない |
ERC-721はこの「固有ID付きトークン」をスマートコントラクトで管理する規格になっている。
コントラクト内部では、ざっくり次のような対応表が記録されている。
| トークンID | 所有者アドレス | メタデータURI |
|---|---|---|
| 1 | 0xAlice... | ipfs://.../1.json |
| 2 | 0xBob... | ipfs://.../2.json |
| 3 | 0xAlice... | ipfs://.../3.json |
ここでよく誤解されるのが、画像そのものがブロックチェーンに載っているという話。
実際はチェーンに載っているのはトークンID・所有者・メタデータの場所(URI)だけで、画像はIPFSや普通のWebサーバに置かれていることが多い。
だから「画像のリンク先が消えるとNFTの中身が見えなくなる」みたいな事故が定期的に起きる。
NFTマーケットがやっているのは、このコントラクトの transferFrom を呼んで所有者欄を書き換える処理と、メタデータURIをUIで取りに行って表示する処理の組み合わせになる。
Web側の見た目は派手だが、コントラクト側は意外と地味な台帳更新をしているだけだ。
ウォレットはどう盗まれるか
ERC-8128の話は「署名が偽装されたら資産が抜かれる」という前提で進むが、そもそもウォレットがどんな経路で抜かれるのかが分かっていないと、ありがたみが伝わりにくい。
先にウォレットの種類と、典型的な盗難パターンを押さえておく。
ホットとコールドの違い
ウォレットは秘密鍵がネットに繋がっているかどうかで2種類に分けられる。
| 種類 | 中身 | 例 | 強み | 弱み |
|---|---|---|---|---|
| ホットウォレット | ネット接続環境で秘密鍵を扱う | MetaMaskブラウザ拡張、スマホアプリ、取引所のWebウォレット | すぐ署名できてUIも軽い | マルウェアやフィッシングに弱い |
| コールドウォレット | ネットから切り離して秘密鍵を保管 | Ledger・Trezor等のハードウェアウォレット、紙に書いたシード(ペーパーウォレット) | リモート攻撃を受けにくい | 使うたびに物理デバイス接続や手動操作が必要 |
定石は「日常使う少額はホット、長期保管の大金はコールド」。
取引所も内部で「顧客出金用はホット、大半の資産は別環境のコールド」と分けて運用している。
よくある盗難パターン
実際に多発している攻撃を整理する。
1. 秘密鍵そのものを抜かれる
| 経路 | 内容 |
|---|---|
| マルウェア感染 | 情報窃取マルウェアがMetaMaskの保存ファイルやブラウザ拡張からシードフレーズを抜く |
| シードを写真・クラウドに保存 | iCloud写真やGoogle Driveに残し、アカウント乗っ取りで芋づる |
| フィッシングサイト | 「ウォレット復元のため」と偽サイトでシードフレーズを入力させる |
シードフレーズ(12〜24単語の復元キー)は秘密鍵そのものなので、漏れた瞬間にウォレットの中身が即抜かれる。
2. 署名フィッシング(中身が見えない署名をさせる)
ウォレットで署名するとき、画面に出るのは生のトランザクションデータで、人間には何の操作か分かりにくいことが多い。
ありがちなパターンが次の流れ。
- 偽NFTサイトに接続させて「ガス代不要のミントです」と称して署名要求
- 実際の中身は
setApprovalForAll、つまり「このコントラクトがあなたのNFTを全部動かしてOK」という許可 - 後で攻撃者がそのコントラクト経由でまとめて転送し、全部消える
Permit、approve、setApprovalForAll の署名は実質「白紙委任状」になるので、これが攻撃の主流になっている。
3. Approveの悪用
UniswapなどのDEXを使うと「このトークンを使う許可」を求められる。
楽だからと「無制限(unlimited)」で許可を出すと、後でそのコントラクトに脆弱性やアップグレードが入った瞬間、許可した分が一気に抜かれる。
定期的に revoke.cash 等で過去のapproveを取り消すのが推奨される。
4. アドレス毒入れ(address poisoning)
最近多い手口。
- 自分のアドレスの先頭4文字・末尾4文字だけ似せた偽アドレスを生成
- そのアドレスから0.0001 ETHを送金して履歴に残す
- ユーザーが次に送金するとき、履歴からコピペして「前に使ったやつだ」と勘違いし、偽アドレスに送金
ウォレットUIがアドレスを 0xAb12...cd34 のように省略表示することで成立する。
5. クリップボード書き換え
PCに入ったマルウェアがコピーしたアドレスを検出し、別アドレスに置き換える。
ユーザーは自分でコピペしたつもりが、ペースト時には攻撃者のアドレスになっている。
6. SIMスワップ
電話番号を乗っ取り、SMSの2FAを突破する。
取引所アカウントが2FAだけだとログインされて資産を移される。
取引所のホットウォレット運用ではこれが一番多い。
7. 取引所自体のハック
| 事件 | 内容 |
|---|---|
| Mt.Gox(2014) | 約85万BTC消失 |
| Coincheck(2018) | 約580億円分のNEM流出(ホットウォレットに大量保管していた) |
| DMM Bitcoin(2024) | 約482億円分のBTC流出 |
取引所が顧客資産をホットウォレット側に置きすぎていて、内部システム経由で攻撃されるパターンになる。
コールドウォレットでも防げないもの
ハードウェアウォレットを使えば「マルウェアによる秘密鍵抜き取り」「クリップボード書き換え」「シードフレーズの直接入力フィッシング」あたりはブロックできる。
ただし、署名フィッシング(自分で物理ボタンを押して署名してしまう)は防げない。
結局のところ「自分が何に署名しているか理解する」リテラシーが土台として必要になる。
AIエージェントとの関係
ここがERC-8128と直結する。
AIエージェントが暗号資産を持って自律取引する場合、頻繁に署名する必要があるので、物理操作前提のコールドウォレットは実質使えない。
必然的にホットウォレット側で動かすことになり、署名鍵が漏れやすい環境に置かれる。
さらに、エージェントは人間のように「この署名画面、ちょっと変だぞ」とは判断できないので、署名対象が正規エージェントから来ているかをプロトコルレベルで保証する仕組みが要る。
ERC-8128はそこに対する答えのひとつになる。
メッセージ署名の基礎
ERC-8128の前に、そもそも署名で何ができるのかを押さえる。
公開鍵暗号には2つの鍵がある。
| 鍵 | 役割 |
|---|---|
| 秘密鍵 | 自分だけが持つ。これでメッセージに署名する |
| 公開鍵 | 誰でも持っていい。署名を検証するために使う |
仕組みとしては次の流れになる。
flowchart LR
A[送信者<br/>秘密鍵保有] -->|メッセージ + 署名| B[受信者<br/>公開鍵保有]
B --> C{署名検証}
C -->|OK| D[送信者本人と確認]
C -->|NG| E[改ざんまたは別人]
パスワードやAPIキーは「合言葉を知っているかどうか」で確認する。
署名は「秘密鍵を持っている人にしか作れない暗号データ」を毎回作って渡す方式で、公開鍵さえあれば誰でも検証できる。
ただし、ナイーブに署名するだけだと攻撃が刺さる。
代表的なのは次の2つで、対応する防御要素もセットで覚えておくと混乱しない。
| 攻撃 | 内容 | 対策要素 |
|---|---|---|
| リプレイ攻撃 | 過去の正規メッセージをそのまま再送して、もう一度実行させる | nonce、timestamp |
| ドメイン混同攻撃 | テスト環境向けの署名を本番環境で使い回される | domain binding |
防御側で署名対象のメッセージに埋め込むのが定番の3要素になる。
| 要素 | 役割 |
|---|---|
| nonce | 1回しか使えない使い捨ての番号。受信側が消費済みを覚えておくことでリプレイを止める |
| timestamp | 古すぎる署名を弾くための時刻 |
| domain binding | ドメイン名やコントラクトアドレスをメッセージに含めて、別環境への流用を防ぐ |
ERC-8128はこの3点をエージェント通信向けに型として定義したものになる。
ERC-8128の中身
ERC-8128は、エージェントが送るメッセージを構造化したうえで署名するための型を定めている。
EthereumにはEIP-712という「構造化データに型情報込みで署名する」標準が既にあり、ERC-8128はそれをエージェント通信向けに拡張する位置にある。
メッセージに含まれる主な要素は次の通り。
| 要素 | 役割 |
|---|---|
agent_id | 送信元エージェントの識別子(ウォレットアドレス等) |
domain | バインドされたドメイン名・コントラクト |
nonce | 使い捨ての番号 |
timestamp | 発行時刻 |
payload | エージェントが送りたい本文(指示・データ等) |
signature | 上記すべてを秘密鍵で署名した結果 |
検証側はpayloadを使う前に署名を確認する。
- 署名が
agent_idの公開鍵で復号できるか - nonceが過去に使われていないか
- timestampが許容範囲内か
- domainが自分の環境と一致するか
これが全部通ったときだけ、payloadの指示を実行する。
APIキーやOAuthと何が違うか
APIキーやOAuthトークンは「文字列を持っているかどうか」で認証する。
盗まれたら、盗んだ側が同じことをそのまま実行できる。
一方、ERC-8128の署名方式では、メッセージごとに秘密鍵で署名を作るので「過去の通信を盗み見ても、新しい指示は出せない」状態になる。
比較すると差が見えやすい。
| 観点 | APIキー / OAuth | ERC-8128署名 |
|---|---|---|
| 認証情報の所在 | サーバ側に保存 | 秘密鍵は手元のみ、サーバに送らない |
| 漏洩時の影響 | キー期限まで全権限が悪用可能 | 1つのメッセージは漏れても再利用は困難 |
| 監査証跡 | アクセスログ程度 | 各メッセージに暗号的に検証可能な署名が残る |
| マルチエージェント連携 | 共有シークレットが増えると管理難 | 各エージェントが独自鍵を持てば集約不要 |
特に最後のマルチエージェント連携が効いてくる。エージェントの数が増えるほど、共有シークレット方式は鍵配布と失効管理が破綻していく。
なぜAIエージェントの通信で必要になるのか
ここまでは署名そのものの利点だが、AIエージェント文脈で署名が押し出される理由は別にある。
エージェントが暗号資産を保有して自律的に取引する世界では、1つのエージェントが大きな金額を動かす。
そこに別のエージェントから「ポジションを縮小しろ」「この取引を実行しろ」といった指示が飛んでくるとき、その指示の出元が本当に正規のエージェントか即時に検証できないと、指示の偽装で資産が抜かれる。
DEVの元記事が挙げているシナリオは次のような流れ。
flowchart TD
A[市場監視エージェント] -->|異常検知| B[署名付きアラートを生成]
B -->|ERC-8128署名 + payload| C[取引エージェント]
C --> D{署名検証}
D -->|OK| E[reduce_position_size を実行]
D -->|NG| F[指示を破棄してログ記録]
ここで監視エージェントの署名が検証できなかった指示は、見た目が正規でも実行されない。
これが「APIキーで Authorization ヘッダだけ確認している」設計だと、ヘッダを盗んだ攻撃者からも同じ指示が通ってしまう。
なお、この署名検証はAIエージェントのメモリ注入攻撃とEVMbenchによるスマートコントラクト自動悪用で触れたような、エージェントのメモリや判断ロジックそのものに対する攻撃を防ぐものではない。
あくまで「他のエージェントから来る指示の出所を検証する」レイヤーで、エージェント内部の安全性とは独立した話になる。
実装イメージ
DEV元記事が紹介しているSDKは、TypeScriptとPythonで提供されていて、署名・検証側ともに数行で書けるようになっている。
署名側のイメージはおおまかに次の形になる。
import { signMessage } from 'erc8128-sdk';
const signed = await signMessage({
agentId: '0xMonitorAgent...',
domain: 'trading.example.com',
nonce: generateNonce(),
timestamp: Date.now(),
payload: { action: 'reduce_position_size', symbol: 'ETH', factor: 0.5 },
}, privateKey);
// signed には payload + signature が入る
await fetch('https://trading-agent.example.com/instruction', {
method: 'POST',
body: JSON.stringify(signed),
});
検証側は受け取った構造体に対して、署名・nonce・timestamp・domainの4点を順にチェックする。
import { verifyMessage } from 'erc8128-sdk';
const result = await verifyMessage(received, {
trustedAgents: ['0xMonitorAgent...'],
domain: 'trading.example.com',
nonceStore, // 既使用nonceの記録
timestampToleranceMs: 30_000,
});
if (!result.valid) {
return reject(result.reason);
}
executeInstruction(received.payload);
nonceStore はRedisなど揮発しない外部ストレージで持つ前提になっていて、ここをサボると同じ署名の使い回しを止められない。
署名検証だけで満足せず、nonce管理・timestamp許容幅・信頼できる送信元一覧の3つをセットで設計する必要がある。
どこから手を付けるか
実運用で考えると、ERC-8128をいきなり全エージェント間に入れる必要はない。
最初に署名検証を入れる候補は次のあたり。
- 暗号資産や金融データを動かす指示の経路
- 複数の自律エージェントが並行して動くマルチエージェント構成
- 外部から指示を受ける形のエージェント(社外連携、APIゲートウェイ経由など)
逆に、内部完結している単一エージェントや、人間がすべての指示を発行する構成では、APIキー+HTTPSで十分なケースも多い。
署名検証は鍵管理とnonce管理の運用コストが乗るので、何でも入れればいいわけではない。