Skip to content
On this page

S1C4: Who Can Sign This?

1. 問題

コントラクトは、呼び出し元に対して身元を証明するための ECDSA 署名の提供を要求します。mintFlag 関数は、署名が特定の authorized signer によって発行されたものであるかをチェックします。

2. 原因

コントラクトは ECDSA 署名復元(ecrecover)を使用して呼び出し元を検証します。署名はハードコードされた authorized signer アドレスによって発行されたものでなければなりません。その signer の秘密鍵を見つけるか、他の方法で有効な署名を取得する必要があります。

3. 方案

  1. コントラクトのストレージから authorized signer アドレスを読み取る
  2. 既知の Hardhat デフォルト mnemonic から signer の秘密鍵を導出する(index 12)
  3. その秘密鍵でメッセージに署名する
  4. 署名を 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スマートコントラクト署名検証の標準インターフェース

Built with AiAda