Skip to content
On this page

S1C4: Who Can Sign This?

1. 问题

合约要求调用者提供一个 ECDSA 签名来证明身份。mintFlag 函数检查签名是否由某个 authorized signer 签发。

2. 原因

合约使用 ECDSA 签名恢复(ecrecover)来验证调用者。签名必须由硬编码的 authorized signer 地址签发。需要找到该 signer 的私钥或通过其他方式获取有效签名。

3. 方案

  1. 从合约 storage 读取 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 的 account index 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