密码学算法 - BSGS 算法二
上一章我们介绍了 BSGS(Baby-Step Giant-Step)算法的基本原理和实现方法,帮助大家快速求解离散对数问题。接下来,我们将继续深入探讨 BSGS 算法的另一种应用。除了在离散对数问题中,BSGS 算法也可以用于求解 ECC(Elliptic Curve Cryptography)中的离散对数问题,这在现代密码学中具有重要的实际意义。
欢迎来到《密码学核心算法实战》的 BSGS 算法二专题!这里没有纸上谈兵的理论空谈(真的不画大饼😉),只有一把把能直接撬动数据安全的精密齿轮⚙️。
ECC中的BSGS算法 🌟
在 ECC 中,离散对数问题的形式是:给定一个椭圆曲线 $E$ 上的点 $P$ 和 $Q$,找到一个整数 $k$ 使得 $Q = kP$。这个问题被称为椭圆曲线离散对数问题(ECDLP),是 ECC 加密算法安全性的基础。而 BSGS 算法可以用来求解 ECDLP,从而在某些情况下破解 ECC 加密。
ECC中的BSGS算法的原理 😵
既然有前一章的铺垫,那么原理就直接简单讲解了。
求解 $x$ 使得 $Q = xP$,我们可以将 $x$ 表示为 $x = i \cdot m - j$,其中 $m = \lceil \sqrt{n} \rceil$,$i \in [0, m)$ (大步),$j \in [0, m)$ (小步)。这样我们可以将 ECDLP 转化为以下形式:
小步(Baby Step):计算 $Q + jP$,对于 $j \in [0, m)$,将结果存入哈希表(键为点的坐标,值为 $j$)。每次都是加 $P$,所以叫做小步。
大步(Giant Step):计算 $mP$,对于 $i \in [0, m)$,计算 $i \cdot mP$,检查是否在哈希表中存在对应的点,如果存在,则可以得到 $x = i \cdot m - j$。每次都是加 $mP$,所以叫做大步。
ECC中的BSGS算法的实现 🙃
import math
class EllipticCurve:
def __init__(self, a, b, p):
self.a = a
self.b = b
self.p = p
# 求逆元 (Fermat's little theorem)
def inverse(self, val):
return pow(val, self.p - 2, self.p)
# 点加运算 P + Q
def add(self, P, Q):
if P is None: return Q
if Q is None: return P
x1, y1 = P
x2, y2 = Q
if x1 == x2 and (y1 + y2) % self.p == 0:
return None # 也就是无穷远点 O
if P == Q:
# 斜率 k = (3x^2 + a) / 2y
lam = (3 * x1 * x1 + self.a) * self.inverse(2 * y1) % self.p
else:
if x1 == x2: return None # 垂直切线
# 斜率 k = (y2 - y1) / (x2 - x1)
lam = (y2 - y1) * self.inverse(x2 - x1) % self.p
x3 = (lam * lam - x1 - x2) % self.p
y3 = (lam * (x1 - x3) - y1) % self.p
return (x3, y3)
# 标量乘法 k * P (Double-and-Add 算法)
def multiply(self, k, P):
res = None
current = P
while k > 0:
if k % 2 == 1:
res = self.add(res, current)
current = self.add(current, current)
k //= 2
return res
def bsgs_ecc(curve, P, Q, order):
"""
ECC 上的 BSGS 算法
求解 x 使得 Q = xP
原理: x = i * m - j => i * mP = Q + jP
:param curve: 椭圆曲线对象
:param P: 基点 (Generator)
:param Q: 目标点 (Public Key)
:param order: 群的阶 n (或者一个足够大的数)
:return: 离散对数 x
"""
# 1. 计算步长 m = ceil(sqrt(n))
m = math.ceil(math.sqrt(order))
# 2. 小步 (Baby Step)
# 计算 Q + jP,其中 j ∈ [0, m)
# 我们构建一个哈希表: { Point: j }
step_dict = dict()
current_point = Q # 初始值为 Q + 0P
for j in range(m):
# 将点作为 key 存入 (注意点需要是可哈希的类型,元组是可以的)
if current_point not in step_dict:
step_dict[current_point] = j
# 下一步:Q + (j+1)P = (Q + jP) + P
current_point = curve.add(current_point, P)
# 3. 大步 (Giant Step)
# 计算 i * (mP),其中 i ∈ [1, m] (通常遍历到 m+1 保证覆盖)
# 先算出 mP
mP = curve.multiply(m, P)
current_giant = mP # 初始值为 1 * mP
for i in range(1, m + 1):
# 检查 i * mP 是否在 Baby Steps 中
if current_giant in step_dict:
j = step_dict[current_giant]
# 找到碰撞:i * mP = Q + jP
# Q = i * mP - jP = (i * m - j) P
x = i * m - j
return x
# 下一步:(i+1)mP = imP + mP
current_giant = curve.add(current_giant, mP)
return None
SageMath 偷懒 🤓👆
有同学说:“博主,博主,你的算法确实很厉害,但是还是太吃操作了,有没有更加简单无脑的用法?”👻
有的,兄弟有的,这样的算法在 SageMath 中早就已经被封装好了🤫,我们直接调用就行了:
from sage.all import discrete_log
# 1. 定义椭圆曲线 E: y² = x³ + ax + b mod p
p = p
E = EllipticCurve(GF(p), [a, b]) # 格式:EllipticCurve(有限域, [a, b]),对应 y²=x³+ax+b
# 2. 定义基点 P 和公钥 Q
P = E(x_p, y_p) # 基点
Q = E(x_q, y_q) # 公钥
n = P.order()
# 3. 求解离散对数:找 x 使得 x*P = Q(底层用BSGS/Pollard's Rho等算法,更加完善)
private_key = discrete_log(Q, P, n, operation='+')
print(f"私钥 x = {private_key}")
怎么样,是不是非常简单?🤣👉🤡
上一章:密码学算法 - BSGS一 算法 👈
下一章:密码学算法 - AMM 算法 👈
回到开始:关于我 👈
相关链接:
加解密模式分析 - ECC 加密算法 👈











