9 · 有限域与区块链密码学
前面的线代都在实数上。区块链与密码学用的是有限域 F_p——运算规则一样,只是所有计算都在模 p 下进行。
前面的线代都在实数 上。但区块链与密码学用的是有限域 ——运算规则一样,只是所有计算都在「模 p」下进行。本节为你的区块链背景量身定制。
先澄清一个边界:这算线代还是数论?
这是个好问题,要分两层:
- 有限域 本身的构造——为什么要质数、模 p 运算、逆元为何存在——这属于数论 / 抽象代数,不是线性代数。你的直觉是对的。
- 在 上做的向量、矩阵、解方程、求逆、范德蒙插值——这是正经的线性代数,只是把标量所在的域从实数换成了有限域。
关键:线性代数的定义不依赖具体是哪个域,它对「任意域上的向量空间」都成立。所以「有限域上的线性代数」是个正式分支。本节只借用数论给出的域作为前提,重点是用线代工具解决区块链问题。
一、有限域
取一个素数 p,集合 配上「加减乘除都模 p」就构成有限域。关键性质:每个非零元素都有唯一逆元(模意义下),所以线性代数的一整套(解方程、求逆、行列式)在 上照样成立。
为什么用有限域:密码学需要精确、可逆、无浮点误差的运算,还需要「循环」结构来隐藏信息。整数模 p 恰好满足。
二、椭圆曲线密码(ECC)里的线代
椭圆曲线上的点构成一个群,点加法、标量乘(,即把 P 加 k 次)是核心运算。公钥 = 私钥×基点,这个「标量乘」和向量的数乘是同一种代数结构的推广。安全性来自「正向算很快、反推(离散对数)极难」。比特币、以太坊的签名(secp256k1)都基于此。
三、Reed–Solomon 纠删码(最贴近线代)
这是以太坊 Danksharding 数据可用性的核心。思路:
- 把 k 个数据块看成一个多项式的系数,多项式次数 < k。
- 在 n>k 个不同点上求值,得到 n 个编码块(带冗余)。求值过程就是乘一个范德蒙矩阵。
- 任意拿到其中 k 个块,对应的 k×k 范德蒙子矩阵行列式非零、必可逆,于是 恢复原数据(多项式插值)。
为什么轻节点能“抽查”就信任数据:因为编码后,要隐藏足够多数据必须损坏超过一半的块,随机抽查几个就能以极高概率发现造假——这是线性冗余给的数学保证。
四、KZG / 向量承诺
零知识证明(PLONK 等)常用 KZG 承诺:把一组数据编成多项式,用一个椭圆曲线点「承诺」整个多项式,之后可以只用很小的证据证明「某点的取值」而不泄露全部。多项式、求值、线性组合贯穿始终。
五、代码:有限域上的线代与 RS 恢复
import numpy as np
p = 97 # 小素数演示
def inv_mod(a, p): # 费马小定理求逆元
return pow(a, p-2, p)
# 有限域上解 a*x = b
a, b = 5, 3
x = (inv_mod(a, p) * b) % p
print("5x=3 (mod 97) 的解 x =", x, "验证:", (5*x) % p)
# Reed-Solomon 思路:多项式求值与插值恢复
data = [12, 34, 56] # k=3 个数据块(多项式系数)
xs = [1, 2, 3, 4, 5] # 在 5 个点求值 -> n=5 编码块
encoded = [sum(c * pow(xi, j, p) for j, c in enumerate(data)) % p for xi in xs]
print("编码块 =", encoded)
# 只用其中 3 个块恢复(范德蒙矩阵求逆的思路)
idx = [0, 2, 4]
A = np.array([[pow(xs[i], j) for j in range(3)] for i in idx], float)
bb = np.array([encoded[i] for i in idx], float)
rec = np.linalg.solve(A, bb)
print("恢复出的原数据 ≈", np.round(rec))
六、动手想一想
- 为什么 RS 编码要求点数 n 严格大于数据块数 k?
- 范德蒙矩阵什么情况下不可逆?这对「求值点」的选择有什么要求?
- ECC 的「标量乘」与第 1 节向量的「数乘」有何异同?
答案:(1) 多出的 n−k 个块才是冗余,是容错/采样的本钱;n=k 就没有任何恢复能力。(2) 有重复求值点时行列式为 0、不可逆;所以求值点必须两两不同。(3) 都是「把一个元素重复相加」的抽象:向量数乘是实数域上的版本,ECC 标量乘是椭圆曲线群上的版本。