离散对数笔记
离散对数
学习参考:
1、harry0597师傅
2、lazzaro
在整数中,离散对数(DL)是一种基于同余运算和原根的一种对数运算
在任何群G中可为所有整数k定义一个幂数为$b^k$,而离散对数$log_{b^{a}}$使得$b^k=a$的整数k。
离散对数在一些特殊情况下可以快速计算,公钥密码学中几个重要算法的基础,是假设寻找离散对数的问题解,在仔细选择过的群中,并不存在有效率的求解算法。
基本定义
生成元
在一个群G中,如果g是G的生成元,即所有G中所有元素都可以被表示成y=g^x,此时x称为y在G中的对数
阶
设 𝑚≥1,gcd(𝑎,𝑚)=1,使得 𝑎^𝑑≡1(mod𝑚) 成立的最小正整数 𝑑 称为 𝑎 对模 𝑚 的指数或者阶。一为𝛿_𝑚(𝑎)。满足 𝑎^𝑑≡1(mod𝑚) 的 𝑑 一定满足 𝑑∣𝜑(𝑚)。
原根
当𝛿_𝑚(𝑎)=𝜑(𝑚)时,称a是模m的原根,简称m的原根
常规sage函数
参数:
- 求解以base为底
- a的对数
- ord为base的阶,可忽略
- operation可以是+或者*,默认*
- bounds是一个区间(ld,ud),需要保证所计算的对数在此区间内
函数使用:
-
discrete_log(a,base,ord,operation)通用的求离散对数的方法。(Pohlig-Hellman+?BSGS)
没有bounds
Pohig-Hellman算法是一种求解光滑阶循环群上的离散对数的方法。
- 要求中 g必须是原根 (对于 g 不是原根的情况,需要利用原根将原方程转化成两个关于原根的离散对数问题。
- 要求阶是光滑的(p-1可拆为多个素数相乘)
discrete_log_rho(a,base,ord,operation)求离散对数的Pollard-Rho算法。
- 主要解决循环群上的离散对数问题
- Pollard Rho算法主要利用循环群的生成序列呈现一个
ρ子形状 - 适用于生成元的阶的素因子都是大数的情形
Pollard Rho算法是一种随机性的概率型算法
理论基础是生日悖论:
在 $n$ 个元素的集合中随机选取元素,期望只需 $O(\sqrt{n})$ 次就能选到两个相同的元素(碰撞)。
ρ子形状由来:算法生成的序列 $x_0, x_1, x_2, \dots$ 在有限群中必然会进入一个循环,画出轨迹后形状像希腊字母 ρ(一条尾巴 + 一个环)
算法流程
目标求解$g^x\equiv h \pmod p$中的x
划分群元素将群G分成三个大小相近的子集S0,S1,S2(通常按mod3划分)
定义迭代函数
构造序列($a_i,b_i,x_i$)其中$x_i=g^{a_i}\cdot h^{b_i}$
因为 $h = g^x$,代入得:
$$ x_i = g^{a_i} \cdot (g^x)^{b_i} = g^{a_i + x \cdot b_i} $$
关键来了——这里 $x$ 和 $a_i, b_i$ 的关系是线性的:$a_i + x \cdot b_i$。
这样当碰撞发生时 $x_i = x_j$,我们得到:
$$ g^{a_i + x \cdot b_i} = g^{a_j + x \cdot b_j} \quad\Longrightarrow\quad a_i + x \cdot b_i \equiv a_j + x \cdot b_j \pmod{n} $$
移项就是一个一元一次方程:
$$ x \cdot (b_i - b_j) \equiv a_j - a_i \pmod{n} $$
$$ x \equiv \frac{a_j - a_i}{b_i - b_j} \pmod{n} $$
使用Floyd找碰撞
维护两个指针
- 乌龟:每次一步
- 兔子:每次两步
当乌龟兔子相遇($x_{slow}=x_{fast}$)找到
解出离散对数
将 $h = g^x$ 代入上式:
$$ g^{a_{\text{slow}}} \cdot g^{x \cdot b_{\text{slow}}} \equiv g^{a_{\text{fast}}} \cdot g^{x \cdot b_{\text{fast}}} \pmod{p} $$
$$ g^{a_{\text{slow}} + x \cdot b_{\text{slow}}} \equiv g^{a_{\text{fast}} + x \cdot b_{\text{fast}}} \pmod{p} $$
因此指数相等(模 $n$,$n$ 为 $g$ 的阶):
$$ a_{\text{slow}} + x \cdot b_{\text{slow}} \equiv a_{\text{fast}} + x \cdot b_{\text{fast}} \pmod{n} $$
$$ x \cdot (b_{\text{slow}} - b_{\text{fast}}) \equiv a_{\text{fast}} - a_{\text{slow}} \pmod{n} $$
令 $\Delta b = b_{\text{slow}} - b_{\text{fast}}$,$\Delta a = a_{\text{fast}} - a_{\text{slow}}$:
$$ x \cdot \Delta b \equiv \Delta a \pmod{n} $$
这是一个线性同余方程。当 $\gcd(\Delta b, n) = 1$ 时,直接求逆元即可:
$$ x \equiv \Delta a \cdot (\Delta b)^{-1} \pmod{n} $$
若 $\gcd(\Delta b, n) = d > 1$,则有 $d$ 个候选解,逐一检验即可
discrete_log_lambda(a,base,bounds,operation)求离散对数的Pollard-kangaroo算法(也称为lambda算法)。
- 适用于题目给出bounds
bsgs(base,a,bounds,operation)大步小步法。
1
from sage.groups.genertic import bsgs
- 用于解高次同余方程问题
- 适用于模p为质数的情况
- 适用于题目给出bound
原理介绍
Elgamal密钥生成
1 | #生成64位的素数p作为模数,int 32位 |
1 | g^x≡y(mod p) |
大步小步算法(BSGS)
解决高次同余方程的问题
为什么不直接暴力解$g^x\equiv y\pmod p$ ?(x的范围为0-p-2)暴力枚举需要O(p)
example:
同余方程$a^x\equiv b \pmod p$,p为质数,求解最小非负整数解x使得原方程成立离散对数问题
复杂度较低
原理
求解$g^x \equiv y \pmod p$
拆分x
x = q·m + r
设 $m = \lceil \sqrt{p-1} \rceil$,把 $x$ 写成带余除法的形式:
$$ x = \mathbf{q} \cdot m + \mathbf{r}, \quad 0 \le r < m $$
代入原方程:
$$ g^{qm + r} \equiv y \pmod{p} $$
移项(把含 $r$ 的放一边,含 $q$ 的放另一边):
$$ g^r \equiv y \cdot g^{-qm} \pmod{p} $$
费马小定理:g^(p-1) ≡ 1 (mod p) 模p乘法群的阶为p-1
| 变量 | 取值范围 | 可能取值数量 | |
|---|---|---|---|
| 左边 $g^r$ | $r$ | $0 \sim m-1$ | $m$ 个 |
| 右边 $y \cdot g^{-qm}$ | $q$ | $0 \sim m-1$ | $m$ 个 |
总共只有 $2m \approx 2\sqrt{p}$ 种可能,而不是原来的 $p$ 种。
Baby Step:枚举左边,建表
“小步”——每次指数只加 1,走得很慢:
$$ \begin{aligned} r=0&: \quad g^0 = 1 \ r=1&: \quad g^1 = g \ r=2&: \quad g^2 = g \cdot g \ &\vdots \end{aligned} $$
把每个 $g^r \to r$ 存入哈希表(用值查指数
Giant Step:枚举右边,查表
“大步”——每次乘 $g^{-m}$,相当于指数一步跨 $m$:
$$ \begin{aligned} q=0&: \quad y \cdot g^{0} = y \ q=1&: \quad y \cdot g^{-m} = y \cdot g^{-m} \ q=2&: \quad y \cdot g^{-2m} = y \cdot g^{-m} \cdot g^{-m} \ &\vdots \end{aligned} $$
每步算出一个值,就去哈希表里查:这个值出现过吗?对应的 $r$ 是多少?
一旦命中,直接拼出答案:
$$ x = q \cdot m + r $$
时空复杂度
| 暴力 | BSGS | |
|---|---|---|
| 时间 | $O(p)$ | $O(\sqrt{p})$ |
| 空间 | $O(1)$ | $O(\sqrt{p})$(存哈希表) |
脚本
1 | #sage |
1 | def babystep_giantstep(g,y,p): |




