公钥密码体制把钥匙拆成公私两半:私钥保密、公钥公开,配合椭圆曲线等数学难题实现"加密通信用公钥、授权签署用私钥";数字签名则是私钥对消息摘要的签署,任何人可用对应公钥验证、却无人能伪造,从而同时支撑真实性与不可否认性。本节走通"私钥→公钥→地址→签名→验签"全链路,并用玩具级 RSA 复算签名与防伪。
凌晨,交易所风控收到一笔大额提币请求,页面显示的签名与该账户登记的公钥对不上,系统秒级拒绝。没有人工值守,没有电话回访,拦截依据只是纯粹的数学判断:这枚"私章"盖出来的印,不是这个公钥对应的私钥盖的。传统银行做同样的事要靠柜员核对预留印鉴或短信验证码——本质上都是"验证发起者身份"。公钥密码的革新在于,验证凭证可以公开分发、离线校验、人人可复算,验签不再需要与签发方通信。
这把能拆成两半的钥匙是现代密码学送给区块链最贵重的材料。理解它要抓住两个方向:公钥加密、私钥解密(保密通信方向,链上反而少用);私钥签署、公钥验证(授权方向,链上每笔交易都在用)。两个方向共用一对钥匙,却服务完全不同的化验单条目。

公私钥的数学关系可以这样叙述:从私钥算公钥是一趟快速的单程车,从公钥倒推私钥则是公认的难解问题。比特币与多数新链选用的椭圆曲线方案,难解问题落在"已知曲线上两点与标量,求标量"的离散对数上;老牌方案则落在"大整数分解"或"模乘方求根"上。方向的不可逆,正是安全性的全部来源——公钥因此可以像名片一样散发。
签名流程分三步:对消息做哈希得摘要;用私钥对摘要做签名运算,得到一对或一串数;验证方用公钥反向运算还原出一个摘要,与自行哈希消息得到的摘要比对。比对一致即证明:消息未被改动(完整性),且签署者持有该私钥(真实性);由于私钥仅此一份,签署者事后无法抵赖(不可否认性)。注意签名直接签的是摘要而非原文——哈希把任意长度压到定长,签名运算量随之可控,两种材料在此完成第一次合练。
用小素数搭一个能跑的签名模型,亲眼看"签名成立、篡改失败、伪造失败"(真实系统参数规模不同、算法换为椭圆曲线,但逻辑一致):
# 教学用玩具 RSA:素数取得极小,只为复算流程 p, q = 61, 53 n = p * q # 模数 phi = (p - 1) * (q - 1) # 欧拉函数值 e = 17 # 公钥指数(与 phi 互素) d = pow(e, -1, phi) # 私钥指数:e 的模逆元 def sign(m: int) -> int: return pow(m, d, n) # 私钥签署:m 的 d 次方模 n def verify(m: int, s: int) -> bool: return pow(s, e, n) == m # 公钥验签:s 的 e 次方模 n 还原 m msg = 72 # 约定:真实系统先哈希消息再取整数 sig = sign(msg) print("签名:", sig, "| 验签:", verify(msg, sig)) # True # 攻击一:篡改消息(金额被改) print("改金额后验签:", verify(7, sig)) # False # 攻击二:伪造签名(无私钥者随机盖章) print("伪造验签: ", verify(msg, sign(msg + 1))) # False
再看地址派生的真实套路。比特币地址是"公钥先做哈希、再做校验编码"的产物,教学版用双轮哈希模拟:
import hashlib def fake_pubkey(priv_int: int) -> bytes: # 真实系统:椭圆曲线标量乘得到公钥点;此处用摘要演示"单向派生" return hashlib.sha256(b"pub-from-" + str(priv_int).encode()).digest() def address_from(pub: bytes) -> str: h1 = hashlib.sha256(pub).digest() # 第一轮:SHA-256 h2 = hashlib.sha256(b"ripemd|" + h1).digest()[:20] # 第二轮:模拟 RIPEMD-160 截断 checksum = hashlib.sha256(hashlib.sha256(h2).digest()).digest()[:4] return (h2 + checksum).hex() priv = 0x7F3A1C pub = fake_pubkey(priv) print("公钥:", pub.hex()[:24], "...") print("地址:", address_from(pub)[:26], "...") print("换个私钥 ->", address_from(fake_pubkey(priv + 1))[:26], "...")
从私钥到地址的每一步都不可逆,且换一个私钥地址就完全不同——这就是"私钥即所有权"的机械原理:没有私钥,你连一张合法的出厂授权单都开不出来。
真实链上的签名算法生态:比特币与以太坊长期使用 ECDSA(曲线为特定的椭圆曲线参数集),比特币后来增配 Schnorr 以获得线性特性——多签聚合、批量验证因此便宜,门限签名也更容易构造。工程上还要懂几条"脾气":验签必须拒绝畸形的公钥与签名编码,否则会引入可延展性漏洞(同一签名可被改写出另一个合法编码,曾干扰过交易确认逻辑);签名的随机数必须每次全新且保密,确定性派生的随机数方案正是为根治这一条而生。
⚠️ 产业史上最疼的一类事故就是随机数:某安卓钱包的随机数生成器缺陷导致同一随机数被两笔签名复用,攻击者列方程解出私钥直接清空账户;某游戏主机生态的签名密钥被同类方法攻破。数学无懈可击,实现一念之差。
💡 记忆锚点:公钥是身份证号,私章是本人。地址则像收件信箱——信箱号公开可查,但要取件(动用资产)必须有章。
签名挡得住伪造,挡不住"合法签署者被骗":钓鱼页面骗你签下一笔转账,签名完全合法,损失照旧——签名证明意愿的来源,不证明意愿的明智。签名也不保护隐私:验签人人可做,公钥—地址—交易图谱因此可被分析(第 5 章的出厂检验正为此设)。至于量子计算对这类难题的潜在冲击与后量子迁移,材料清单先记账,第 6 章统一结算。
单一铸件的钢印(哈希)与授权(签名)都已到位。下一节解决规模问题:一整批铸件如何打包质检、如何让轻装上阵的验证者只查一件就敢确认整批——Merkle 树登场。