Ethernaut 笔记
简介 最近从 Ethernaut 学习到了很多,抛开那些比较基础的,记录一些 ECDSA 相关的 以下公式中小写字母代表一个值,大写字母代表一个点,除了 N 是曲线的 order 我们知道 ECDSA 依赖于椭圆曲线上的离散对数问题,对于私钥 privkey,公钥 PubKey 是椭圆曲线上的一个点并且有 $\text{PubKey} = \text{privkey} \cdot G$,其中 G 是椭圆曲线的生成元,正是因为椭圆曲线上的离散对数问题,已知 PubKey 和 G 求 privkey 是困难的,才让数字签名得以可能 Sign 签名公式 $$ s = k^{-1} \cdot (h + r \cdot \text{privkey})\mod{N} $$k 是随机数,RFC6979 提供了生成方法,不建议真的随机生成,因为重用会导致私钥泄漏,后续会提到 h 是要被签名的 hash 值 r 是 k * G 这个点的 x 轴坐标 计算出 s 后,和 r 共同构成签名 (r, s),但在签名恢复的过程还会产生歧义,有两种结果,所以还要引入一个 v 来确认是哪一个结果,后续会提到 1import hashlib 2from eth_hash.auto import keccak 3from ecdsa import SECP256k1 4from ecdsa.rfc6979 import generate_k 5 6CURVE = SECP256k1 7N = CURVE.order 8G = CURVE.generator 9 10priv_key = 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 11 12h = keccak(b'hello') 13print(f'hash: 0x{h.hex()}') 14 15h_int = int.from_bytes(h, 'big') 16 17# random k, important 18k = generate_k( 19 order=N, 20 secexp=priv_key, 21 hash_func=hashlib.sha256, 22 data=h, 23) 24 25R = k * G 26r = R.x() % N 27k_inv = pow(k, -1, N) 28 29# s = k^-1 * (h + r * pk) 30s = (k_inv * (h_int + r * priv_key)) % N 31 32print(f'sig : 0x{r.to_bytes(32, 'big').hex()}{s.to_bytes(32, 'big').hex()}') 33print(f'r : 0x{r.to_bytes(32, 'big').hex()}') 34print(f's : 0x{s.to_bytes(32, 'big').hex()}') Recover 签名恢复公式,即从签名 (r, s) 中恢复出公钥 Pub ...