椭圆曲线的数学基础

一、引言

椭圆曲线密码学(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 的安全来源 ------ 椭圆曲线离散对数问题
相关推荐
ERP老兵-冷溪虎山9 小时前
Python/JS/Go/Java同步学习(第二篇)四语言数据基本类型对照表: 老板让我统一系统数据类型?(附源码/截图/参数表/老板沉默术)
java·javascript·python·golang·基本数据类型·多语言编程·中医编程
Lojarro9 小时前
Go学习1:常量、变量的命名
开发语言·学习·golang
Lu Yao_1 天前
golang -- viper
服务器·数据库·golang
澡点睡觉1 天前
【golang长途旅行第36站】golang操作Redis
开发语言·redis·golang
yjx233321 天前
《应用密码学》——基础知识及协议结构模块(笔记)
笔记·密码学
静谧之心2 天前
从“叠加”到“重叠”:Overlay 与 Overlap 双引擎驱动技术性能优化
linux·网络·设计模式·性能优化·golang·overlay·overlap
Swift社区2 天前
GoLand IDE 无法识别 Go 工作区中的引用,如何解决?
开发语言·ide·golang
007php0072 天前
Go 面试题: new 和 make 是什么,差异在哪?
后端·算法·docker·容器·面试·职场和发展·golang
扯淡的闲人2 天前
Go语言入门学习笔记
笔记·学习·golang