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

进阶:椭圆曲线计算加速

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