椭圆曲线的数学基础

一、引言

椭圆曲线密码学(Elliptic Curve Cryptography, ECC)是现代公钥密码学的核心工具之一。

相比传统的 RSA,ECC 可以用 更短的密钥长度 提供 同等甚至更高的安全性,因此被广泛应用于区块链、TLS、移动设备加密等场景。

要理解 ECC,必须先了解它背后的数学结构 ------ 椭圆曲线上的点运算。本文将从基础开始,逐步介绍椭圆曲线的数学原理。


二、椭圆曲线方程

一个椭圆曲线通常由如下方程表示:

y2=x3+ax+b y^2 = x^3 + ax + b y2=x3+ax+b

其中 a,ba, ba,b 是常数,要求曲线 无奇异点(即没有自相交和尖点),满足:

4a3+27b2≠0 4a^3 + 27b^2 \neq 0 4a3+27b2=0

在实数范围内,这条曲线看起来像一条光滑的对称曲线:

  • 关于 x 轴对称
  • 呈"S"形或"波浪"形

但在密码学中,我们不会在实数范围上研究,而是定义在 有限域 Fp\mathbb{F}_pFp (模素数 ppp)上的椭圆曲线。


三、有限域上的椭圆曲线

在有限域中,所有运算都取模 ppp:

y2≡x3+ax+b(modp) y^2 \equiv x^3 + ax + b \pmod p y2≡x3+ax+b(modp)

例如:

选择 p=17,a=2,b=2p = 17, a = 2, b = 2p=17,a=2,b=2,曲线为:

y2≡x3+2x+2(mod17) y^2 \equiv x^3 + 2x + 2 \pmod{17} y2≡x3+2x+2(mod17)

我们可以枚举 x∈[0,16]x \in [0,16]x∈[0,16],找到满足条件的点 (x,y)(x,y)(x,y),这就是曲线上的点集。


四、点运算(群结构)

ECC 的核心不是曲线方程本身,而是 曲线点上的运算规则

椭圆曲线上的点(包括一个"无穷远点" OOO)形成一个 ,支持以下运算:

  1. 点加法 P+QP+QP+Q

    • 几何直观:过两点作直线,直线与曲线相交于第三点 RRR,再取 RRR 关于 x 轴的对称点。
    • 特殊情况:P=QP=QP=Q 时,用切线定义加法。
  2. 点倍乘 kPkPkP

    • 相当于 P+P+...+PP+P+...+PP+P+...+P(共 kkk 次)。
    • 在 ECC 中,公钥计算就是 点倍乘

五、ECC 的安全性来源

  • 容易 :给定 PPP 和整数 kkk,计算 Q=kPQ = kPQ=kP 很快。
  • 困难 :给定 PPP 和 QQQ,求 kkk 很难(椭圆曲线离散对数问题,ECDLP)。

这种 单向性 是 ECC 的安全核心。


六、Go 语言小实验:有限域椭圆曲线点加法

下面我们用 Go 写一个小程序,在有限域 p=17p=17p=17 上实现椭圆曲线点加法。

go 复制代码
package main

import (
	"fmt"
	"math/big"
)

// 椭圆曲线参数: y^2 = x^3 + ax + b mod p
var p = big.NewInt(17)
var a = big.NewInt(2)
var b = big.NewInt(2)

// 点结构
type Point struct {
	x, y *big.Int
	inf  bool // 是否是无穷远点
}

// 取模
func mod(v *big.Int) *big.Int {
	r := new(big.Int).Mod(v, p)
	if r.Sign() < 0 {
		r.Add(r, p)
	}
	return r
}

// 逆元
func modInverse(v *big.Int) *big.Int {
	return new(big.Int).ModInverse(v, p)
}

// 点加法
func add(P, Q Point) Point {
	// 处理无穷远点
	if P.inf {
		return Q
	}
	if Q.inf {
		return P
	}

	var m *big.Int
	if P.x.Cmp(Q.x) == 0 && P.y.Cmp(Q.y) == 0 {
		// P == Q, 切线斜率
		num := new(big.Int).Mul(big.NewInt(3), new(big.Int).Mul(P.x, P.x))
		num.Add(num, a)
		den := new(big.Int).Mul(big.NewInt(2), P.y)
		m = new(big.Int).Mul(num, modInverse(den))
	} else {
		// P != Q, 直线斜率
		num := new(big.Int).Sub(Q.y, P.y)
		den := new(big.Int).Sub(Q.x, P.x)
		m = new(big.Int).Mul(num, modInverse(den))
	}

	m = mod(m)
	xr := mod(new(big.Int).Sub(new(big.Int).Sub(new(big.Int).Mul(m, m), P.x), Q.x))
	yr := mod(new(big.Int).Sub(new(big.Int).Mul(m, new(big.Int).Sub(P.x, xr)), P.y))
	return Point{xr, yr, false}
}

func main() {
	P := Point{big.NewInt(5), big.NewInt(1), false}
	Q := Point{big.NewInt(6), big.NewInt(3), false}
	R := add(P, Q)
	fmt.Printf("P=(%v,%v), Q=(%v,%v)\n", P.x, P.y, Q.x, Q.y)
	fmt.Printf("P+Q=(%v,%v)\n", R.x, R.y)
}

运行结果示例:

复制代码
P=(5,1), Q=(6,3)
P+Q=(10,6)

说明在有限域上,椭圆曲线点运算是完全可行的。


七、总结

本文介绍了椭圆曲线的数学基础,包括:

  • 椭圆曲线方程及有限域定义
  • 点加法和点倍乘运算
  • ECC 的安全来源 ------ 椭圆曲线离散对数问题
相关推荐
资深web全栈开发2 小时前
并查集(Union-Find)套路详解
leetcode·golang·并查集·unionfind
moxiaoran57534 小时前
Go语言的递归函数
开发语言·后端·golang
朝花不迟暮4 小时前
Go基础-闭包
android·开发语言·golang
西京刀客6 小时前
go语言-切片排序之sort.Slice 和 sort.SliceStable 的区别(数据库分页、内存分页场景注意点)
后端·golang·sort·数据库分页·内存分页
黄昏单车7 小时前
golang语言基础到进阶学习笔记
笔记·golang·go
moxiaoran575317 小时前
Go语言结构体
开发语言·后端·golang
Tony Bai1 天前
Cloudflare 2025 年度报告发布——Go 语言再次“屠榜”API 领域,AI 流量激增!
开发语言·人工智能·后端·golang
小徐Chao努力1 天前
Go语言核心知识点底层原理教程【变量、类型与常量】
开发语言·后端·golang
锥锋骚年1 天前
go语言异常处理方案
开发语言·后端·golang
moxiaoran57531 天前
Go语言的map
开发语言·后端·golang