mobile wallpaper 1mobile wallpaper 2mobile wallpaper 3mobile wallpaper 4
1681 文字
4 分
EOA向けEVMウォレットのログイン画面
2026-06-08
2026-06-09

以下は筆者の現時点での理解にすぎません。

=====================

最近、主にフロントエンドで構成されたEOAウォレットのログイン画面を作りました。ブロックチェーン開発に触れる第一歩になっただけでなく、EVMが実際にどのように動作するのかを知る機会にもなりました。

dreaifeHebi
/
web3WalletLogin
Waiting for api.github.com...
00K
0K
0K
Waiting...

一度のウォレットログイン#

一度とはいっても、実際にはウォレット側での確認を必要とするやり取りが2回あります。1回目は、ページから要求されたウォレットアドレスの取得を確認するものです。2回目は、サーバー側が認証用メッセージ、呼び出し元ドメイン、nonceなどをプロトコルに準拠した構造に含め、そのメッセージをウォレットへ送信して検証を要求するものです(現在使用している構造はEIP-4361を模倣しています。ただ、個人的にはUIや追跡可能性を重視した設計という印象があり、実際にはnonceだけでもリクエストの混同を防げるはずです)。

なぜ検証を始める前にウォレットアドレスを取得する必要があるのでしょうか。おそらく、ブラウザとウォレットのどちらも信頼できないものとして扱われるためです。両者の間で直接やり取りされるデータがすべて信頼できないと考えるなら、ウォレットによって確認されたアドレスだけが信頼でき、その後で次のウォレット検証へ進めることになります。

このウォレットを管理しているのは私です!#

あなたのウォレットアドレスは何ですか?#

ここでは、Webサイトに提供することを許可するウォレットアドレスを選択するために、ブラウザとウォレットの間でやり取りが行われます。

このプロジェクトでは、実際にwagmiのconnectを使ってウォレットとのやり取りを要求しています。

// wagmi config
export const wagmiConfig = createConfig({
...,
connectors: [injected({ shimDisconnect: true })],
...
});
// get wagmi injected connector
const injectedConnector = useMemo(
() => connectors.find((connector) => connector.id === "injected") ?? connectors[0],
[connectors]
);
// connect wallet
connect({ connector: injectedConnector });
// auto get wallet connect info
const { address, chainId, isConnected } = useAccount();

ここでもwagmiのuseAccountを通じて、ウォレットでの確認後に更新された情報を自動的に取得しています。

では、そのウォレットは本当にあなたのものですか?#

この情報を証明してもらう必要があります#

検証対象のアドレスが分かれば、標準プロトコルであるSIWE(Sign-In with Ethereum)に準拠したログイン署名メッセージを用意できます。形式はおおよそ次のようになります。

localhost:3000 wants you to sign in with your Ethereum account:
0xYourWalletAddress
Sign in to web3walletLogin with this wallet.
URI: http://localhost:3000
Version: 1
Chain ID: 1
Nonce: <server-issued nonce>
Issued At: <generated timestamp>

次に、このメッセージをEIP-191に従って標準化し、ほかの署名や通常のトランザクションと区別します。

"\x19Ethereum Signed Message:\n" + len(message) + message

実装では、wagmiのsignMessageAsyncを使ってウォレットへ実際の認証リクエストを送信しています。

const { signMessageAsync, isPending: isSigning } = useSignMessage();
// make a siwe message
const siweMessage = new SiweMessage({
domain: window.location.host,
address,
statement: "Sign in to web3walletLogin with this wallet.",
uri: siteOrigin,
version: "1",
chainId,
nonce
});
const preparedMessage = siweMessage.prepareMessage();
// send sign request to wallet
const signature = await signMessageAsync({ message: preparedMessage });

この証明は私の秘密鍵でしか作れません#

このメッセージが認証リクエストとしてウォレットに届くと、ウォレットは自身の署名によって、先ほど提供したアドレスを管理していることを証明する必要があります。そのため、受け取った情報のハッシュに自身の秘密鍵で署名すると同時に、ウォレットアドレスとリクエストメッセージしか知らないWebサイトでも、その署名を検証できるようにしなければなりません。この検証方法の妥当性は、一連の数学的変換によって保証されます。とはいえ、ここではまずwagmiのアルゴリズムを使って、返されたsignを検証しているだけです(

// use the message (the client send) and sign(the wallet back)
const verifyResponse = await fetch("/api/auth/verify", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({ message: preparedMessage, signature })
});
// sign message verify
const siwe = new SiweMessage(body.message);
const result = await siwe.verify({
signature: body.signature,
domain: expectedDomain,
nonce: siwe.nonce
});
// the fail result
if (!result.success) {
return NextResponse.json({ error: "invalid signature" }, { status: 401 });
}

では、実際の検証計算はどうなっているのでしょうか?

そのためには、EOAウォレットの署名に使われるsecp256k1曲線を見る必要があります。EOAウォレットの構成は、おおよそ次のとおりです。

  • EOAの秘密鍵:約256-bitの乱数 d
  • 公開鍵:楕円曲線上の点 Q = d * G
  • アドレス:keccak256(publicKey) の末尾20バイト
  • 署名:secp256k1上のECDSA

とはいえ、私自身もこのあたりの実際の計算はあまり理解できていません(。ただ、署名とmessage hashから得られる公開鍵Qを使って秘密鍵dを逆算できないのは、およそ21282^{128}級の計算量(secp256k1は256bit級の曲線)が必要となるQ=dGQ = d * Gの楕円曲線離散対数問題を解かなければならないから、という程度には理解しています。

最終的には、返されたsign(r+s+vr + s + v)と送信したmessage hashから公開鍵を復元し、そこからアドレスを計算します。このアドレスが先ほど提供されたアドレスと一致すれば、そのウォレットがこのアドレスを管理していることを証明できます。

おわりに#

実際のブロックチェーン開発を始める第一歩としては、だいたいこのようなところでしょうか。正直なところ、秘密鍵による署名や署名の復元処理を見ていると、昔acmを学んでいた頃を少し思い出しました(

ただ、ブロックチェーン学習の入り口となるプロジェクトとしてはちょうどよく、学習への意欲も高まりました。

共有

この記事が役に立ったときは、ぜひ他の人に共有してください!

EOA向けEVMウォレットのログイン画面
https://dreaife.tokyo/jp/posts/evm-wallet-login/
著者
dreaife
公開日
2026-06-08
ライセンス
CC BY-NC-SA 4.0

一部の情報は古い可能性があります

関連した投稿 スマート
1
EOAウォレットの署名検証とその関連事項について
開拓 secp256k1の有限体と点演算からECDSAのr/s/v署名と公開鍵復元を導出し、SIWEを例に、サーバーが秘密鍵に触れずメッセージハッシュとkeccak-256でEOAアドレスの管理権を検証する仕組みを解説します。
2
EOAウォレットのオンチェーン基本操作について
開拓 ウォレットの視点からEOA/HDウォレットの鍵派生、EIP-1559トランザクション、SIWE・EIP-191・EIP-712署名を整理し、ethers.jsによる作成・検証・ブロードキャストの実装例を示します。
3
ブラウザ上でEVMトランザクションを手動で完了する
開拓 ブラウザのコンソールで EVM トランザクションを手動で実行します。JSON-RPC でローカルの Anvil テストチェーンに接続し、ウォレットを呼び出してトランザクションを送信し、手動でブロックを生成します。さらに、トランザクションハッシュの検証、署名者アドレスの復元、Merkle 包含証明の検証を通じて、ブロードキャストからブロックへの取り込み、オンチェーンでの承認までの一連の流れを直感的に理解できます。
4
ブロックチェーンの理解
学び ブロック、分散台帳、コンセンサスからブロックチェーンを解説。取引の流れ、分散性・改ざん耐性、暗号資産や供給網での用途、拡張性の課題を整理します。
5
取引履歴
整理 2025年初の暗号資産取引を振り返り、ローソク足と出来高による判断、レバレッジと資金配分、感情的な取引を避けるためのリスク管理を整理します。

目次