Appearance
S1C4: Who Can Sign This?
1. 問題
コントラクトは、呼び出し元に対して身元を証明するための ECDSA 署名の提供を要求します。mintFlag 関数は、署名が特定の authorized signer によって発行されたものであるかをチェックします。
2. 原因
コントラクトは ECDSA 署名復元(ecrecover)を使用して呼び出し元を検証します。署名はハードコードされた authorized signer アドレスによって発行されたものでなければなりません。その signer の秘密鍵を見つけるか、他の方法で有効な署名を取得する必要があります。
3. 方案
- コントラクトのストレージから authorized signer アドレスを読み取る
- 既知の Hardhat デフォルト mnemonic から signer の秘密鍵を導出する(index 12)
- その秘密鍵でメッセージに署名する
- 署名を
mintFlagに送信する
javascript
// ethers.js を使用して署名
const signer = ethers.Wallet.fromMnemonic(hardhatMnemonic, "m/44'/60'/0'/0/12");
const signature = await signer.signMessage(messageHash);
4. 遭遇したトラップ
Signer 秘密鍵の出所: ドキュメントによって異なる derivation path や mnemonic を指している場合があります。
5. トラップの原因
Hardhat のデフォルト mnemonic のアカウントインデックス 12 は、アドレス 0xFABB0ac9d68B0B445fB7357272Ff202C5651694a に対応します。これは CTF デプロイヤーが authorized signer として使用するアドレスです。
6. 解決方法
signer アドレスがコントラクトに保存されている authorized signer と一致することを確認します:
bash
cast storage <CHALLENGE> <SIGNER_SLOT>
正しい mnemonic と derivation path を使用して署名を生成します。
7. 技術ポイント
| ポイント | 説明 |
|---|---|
| ECDSA 署名復元 | ecrecover は署名から公開鍵/アドレスを復元し、認証に使用 |
| Hardhat デフォルトアカウント | Hardhat は固定の mnemonic を使用し、すべてのテストアカウントの秘密鍵は公開されている |
| EIP-191 | 署名メッセージの標準化されたプレフィックス形式 |
| ERC-1271 | スマートコントラクト署名検証の標準インターフェース |