Skip to content

ECC

数学基础

椭圆曲线

形如y2=x3+ax2+bx+c的曲线被称为椭圆曲线,其中Δ=16(4a3+27b2)0

常见曲线参数:

  • secp256k1: y2=x3+7

    a=1b=7p=225623229282726241n=0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8D0364141Gx=0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798Gy=0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8

  • P-256(FIST): y2=x33x+b

  • BLS128_381: y2=x3+4 二次扩域: y2=x3+4(1+i)

  • SM2: y2=x3+ax+b

    p=FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFFa=FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFCb=28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93n=FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123Gx=32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7Gy=BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0

  • BN128(zk-snark): y2=x3+3

    p=21888242871839275222246405745257275088548364400416034343698204186575808495617a=0b=3n=21888242871839275222246405745257275088548364400416034343698204186575808495617

一些特殊曲线
  • Baby Jubjub Elliptic Curve(扭曲爱德华曲线方程):ax2+y2=1+dx2y2

    r=21888242871839275222246405745257275088548364400416034343698204186575808495617a=168700d=168696n=21888242871839275222246405745257275088614511777268538073601725287587578984328=h×lh=8l=2736030358979909402780800718157159386076813972158567259200215660948447373041Gx=995203441582195749578291179787384436505546430278305826713579947235728471134Gy=5472060717959818805561601436314318772137091100104008585924551046643952123905Bx=5299619240641551281634865583518297030282874472190772894086521144482721001553By=16950150798460657717958625567821834550301663161624707787222815936182638968203

    • 对于运算 P+Q,运算如下:
x3=(x1y1+y1x2)/(1+dx1x2y1y2)modpy3=(y1y2ax1x2)/(1dx1x2y1y2)modp

点加法

对于椭圆曲线上的两个不同点 P1(x1,y1)P2(x2,y2),其和 P3=P1+P2 计算如下:

  1. 斜率计算

    λ=y2y1x2x1modp
  2. 新点坐标

    x3=λ2x1x2modpy3=λ(x1x3)y1modp

数学推导
  1. 直线方程:通过 P1(x1,y1)P2(x2,y2) 的直线:

    y=λx+c

    其中 c=y1λx1

  2. 求交点:将直线方程代入椭圆曲线 y2=x3+ax+b

    (λx+c)2=x3+ax+b

    展开得:

    λ2x2+2λcx+c2=x3+ax+b

    整理为三次方程:

    x3λ2x2+(a2λc)x+(bc2)=0
  3. 根的关系:设三个根为 x1,x2,x3,由韦达定理:

    x1+x2+x3=λ2

    因此:

    x3=λ2x1x2
  4. y坐标计算:将 x3 代入直线方程得到交点,然后取其关于x轴的对称点:

    y3=(λx3+c)=λx3(y1λx1)y3=λ(x1x3)y1

倍乘运算

P1=P2 时(P=2P=P+P),进行点倍乘操作:

  1. 斜率计算

    λ=3x12+a2y1modp
  2. 新点坐标

    x3=λ22x1modpy3=λ(x1x3)y1modp

数学推导同上

标量乘法

标量乘法 kP 是计算点 P 自身相加 k 次的结果。通常使用二进制展开法(类似于快速幂)来高效计算:

输入:点 P,标量 k
输出:k·P

1. 初始化 Q = O (无穷远点)
2. 将 k 表示为二进制
3. 从最低位开始:
   - 如果当前位为1,则 Q = Q + P
   - P = 2P (点倍乘)
   - 移到下一位
4. 返回 Q

ECDH(密钥交换)

密钥生成

私钥生成

私钥 d 是一个随机整数,满足:

1dn1

公钥生成

公钥 Q 通过标量乘法计算:

Q=dG

密钥交换

Alice 和 Bob 通过以下步骤交换密钥:

  1. Alice 生成私钥 dA 和公钥 QA=dAG,将 QA 发送给 Bob。
  2. Bob 生成私钥 dB 和公钥 QB=dBG,将 QB 发送给 Alice。
  3. Alice 接收到 QB 后,计算共享密钥:KA=dAQB=dA(dBG)=(dAdB)G
  4. Bob 接收到 QA 后,计算共享密钥:KB=dBQA=dB(dAG)=(dBdA)G
  5. 最终得到相同共享密钥 K=(dAdB)G

ECIES(公钥加密)

密钥生成

私钥生成

私钥 d 是一个随机整数,满足:

1dn1

公钥生成

公钥 Q 通过标量乘法计算:

Q=dG

加密过程

给定消息 M 和公钥 Q,ECIES加密过程如下:

  1. 生成随机数 k,满足 1kn1
  2. 计算点 P=kG=(x1,y1)
  3. 计算公钥 K=kQ=kdG
  4. 生成对称密钥 Ksym=H(K),其中 H 是哈希函数。
  5. 加密消息 C=MKsym
  6. 输出密文 (C,P)
  7. 发送密文 (C,P) 给接收方。

解密过程

给定密文 (C,P) 和私钥 d,ECIES解密过程如下:

  1. 计算共享密钥 K=dP=dkG
  2. 生成对称密钥 Ksym=H(K)
  3. 解密消息 M=CKsym
  4. 输出明文 M

ECDSA(签名)

域参数

  • p:有限域的大小
  • a,b:椭圆曲线参数
  • G:基点(生成元)
  • n:基点的阶(即 nG=O

密钥生成

私钥生成

私钥 d 是一个随机整数,满足:

1dn1

公钥生成

公钥 Q 通过标量乘法计算:

Q=dG

其中 G 是椭圆曲线的基点。

签名生成

给定消息的哈希值 h 和私钥 d,ECDSA签名过程如下:

步骤1:生成随机数

生成一个随机数 k,满足:

1kn1

!!!:这里是简化的,具体参照这里,简单说就是Hash(h||d)

步骤2:计算点

计算椭圆曲线点:

P=kG=(x1,y1)

步骤3:计算 r

r=x1modn

!!!:取点 Px 坐标模 n,作为签名的第一部分。如果 r=0,则重新选择 k

步骤4:计算 s

s=k1(h+rd)modn

!!!

  • k1k 在模 n 下的乘法逆元
  • (h+rd) 将消息哈希与私钥信息结合
  • 整个表达式确保了签名与私钥和消息的绑定关系

如果 s=0,则重新选择 k

步骤5:输出签名

签名为 (r,s)

签名验证

给定消息哈希 h、签名 (r,s) 和公钥 Q,验证过程如下:

步骤1:参数验证

验证 rs 在有效范围内:

1rn11sn1

步骤2:计算逆元

计算 s 的乘法逆元:

w=s1modn

步骤3:计算标量

u1=hwmodnu2=rwmodn

步骤4:计算验证点

P=u1G+u2Q=(x1,y1)

步骤5:验证结果

如果 x1modn=r,则签名有效;否则无效。

数学原理

从签名生成有:

s=k1(h+rd)modn

重排得到:

k=s1(h+rd)modn(α)

在验证过程中:

P=u1G+u2Q

替换 u1u2

P=(hs1)G+(rs1)Q

由于 Q=dG

P=(hs1)G+(rs1)(dG)P=s1(h+rd)G

根据签名生成中(式α)的关系:

P=kG=P

这证明了验证点 Px 坐标确实等于 r,从而验证了签名的有效性。

Add-On v的生成与公钥恢复

由于压缩传输空间的需要以及ECDSA可以从签名恢复公钥的性质,往往只传输 (r,s) ,而不传输公钥 Q

// TODO

进阶:椭圆曲线计算加速

Jacobian坐标

由于椭圆曲线是 modp 的,并且显然在计算 λ=y2y1x2x1 时需要在 Fp 中求逆,故而需要较大的计算量。

在椭圆曲线上,我们定义单位元为无穷远点 O,但是在仿射坐标系 y2=x3+ax+c 中,而在射影坐标系中,方程可以表示为 Y2Z=X3+aXZ2+cZ3,于是,存在如下转换:(别问我是怎么来的,我也不是很明白,都是从py_ecc.secp256k1里看的)

  • 仿射 射影:(x,y)(X,Y,Z)=(x,y,1)
  • 射影 仿射:(X,Y,Z)(x,y)=(X/Z,Y/Z)

而对于实际应用中常使用Jacobian坐标,其转换如下:

  • 仿射 Jacobian:(x,y)(X,Y,Z)=(x,y,1)
  • Jacobian 仿射:(X,Y,Z)(x,y)=(X/Z2,Y/Z3)

注意这里所有的运算都是在mod p下的

加法

注意这里所有的运算都是在mod p下的

对于 P(X1,Y1,Z1),Q(X2,Y2,Z2),其和 R=P+Q=(X3,Y3,Z3) 计算如下:

u1=X1Z22u2=X2Z12s1=Y1Z23s2=Y2Z13h=u2u1r=s2s1H2=h2X3=r2h32u1H2Y3=r(u1H2X3)s1h3Z3=hZ1Z2

如果 P=Q 直接用倍乘

倍乘

注意这里所有的运算都是在mod p下的

S=4X1Y12M=3X12+aZ14X3=M22SY3=M(SX3)8Y14Z3=2Y1Z1

(里面的a是椭圆曲线的参数)

注意倍乘时可以用类似平方快速幂的方式加速

python
    if a[1] == 0 or n == 0:
        return cast("PlainPoint3D", (0, 0, 1))
    if n == 1:
        return a
    if n < 0 or n >= N:
        return jacobian_multiply(a, n % N)
    if (n % 2) == 0:
        return jacobian_double(jacobian_multiply(a, n // 2))
    if (n % 2) == 1:
        return jacobian_add(jacobian_double(jacobian_multiply(a, n // 2)), a)
    raise ValueError("Unexpected case in jacobian_multiply: This should never happen.")

扩展域

// TODO

Code

ECC_Simple