Pohlig-Hellman算法解决DLP问题及Python实现

InstructionInstructionInstruction

Pohlig-Hellman算法适用于求解特定条件下的DLP问题(离散对数问题),以数学表达该问题即是
ax≡b(modp)a^x\equiv b\pmod p ax≡b(modp)
其中xxx即是所需要求得的数,已知a,b,pa,b,pa,b,p;该算法应用的特定条件是指p−1p-1p−1是光滑数(光滑数即是该数的质因数都很小,其每个质因数大小在该算法中对应着算法复杂度)

该算法的原理及运行过程如下,需要假设其模数p−1p-1p−1是光滑数

假设模ppp的最小本原元为ggg,那么可以用本原元来表示在模ppp意义下的aaa和bbb
a≡gu(modp)b≡gv(modp)a\equiv g^{u} \pmod p\\ b\equiv g^{v} \pmod p a≡gu(modp)b≡gv(modp)
代回到初始问题上得到
ax≡b(modp)⇒gux≡gv(modp)a^x\equiv b\pmod p \\ \Rightarrow g^{ux} \equiv g^{v} \pmod p ax≡b(modp)⇒gux≡gv(modp)
从上式根据数论定理得到
ux≡v(modp−1)ux\equiv v\pmod {p-1} ux≡v(modp−1)
这样我们可以用u,vu,vu,v来表示出xxx
x≡v⋅u−1(modp−1)x \equiv v\cdot u^{-1} \pmod {p-1} x≡v⋅u−1(modp−1)
到这里我们将问题转换到了如何得到v,uv,uv,u的大小


回到用本原元表示a,ba,ba,b的同余式上,

  • 以解gu≡a(modp)g^u \equiv a\pmod pgu≡a(modp)为例,

我们已知a,g,pa,g,pa,g,p;根据算法做出的假设,p−1p-1p−1可以被多个小质因数分解,那么
p−1=p1q1⋅p2q2⋅p3q3⋯pnqnp-1 = p_1^{q_1} \cdot p_2 ^{q_2}\cdot p_3 ^{q_3} \cdots p_n^{q_n} p−1=p1q1​​⋅p2q2​​⋅p3q3​​⋯pnqn​​
其中qiq_iqi​表示的是质因数的指数;我们将目标uuu用每个素因子的大小作为进制表示,如以p1p_1p1​进制表示(进制表示如果不熟悉的话可以参照二进制的表示方式)
u=c0+c1p1+c2p12+c3p13+⋯+cq1−1p1q1−1+⋯+ckp1ku=c_0+c_1p_1+c_2p_1^2+c_3p_1^3+\dots + c_{q_1-1}p_{1}^{q_1-1} + \cdots + c_{k} p_1^{k} u=c0​+c1​p1​+c2​p12​+c3​p13​+⋯+cq1​−1​p1q1​−1​+⋯+ck​p1k​
其中cic_ici​均小于p1p_1p1​,变量kkk意味着可以到无限大;同理我们也将uuu以p2,p3,⋯,pnp_2,p_3,\cdots,p_np2​,p3​,⋯,pn​进制表示,这样就得到nnn个的等式;但是这样的进制表示并没有实质作用,因为我们很可能为了表示uuu,而将kkk拉到很大的数值,具体大小我们无从得知;所以我们用取模来解决这个问题,将等式两侧的大小变到我们能掌握的大小

我们在每个等式中取模piqi{p_i^{q_i}}piqi​​,将其转换为同余式,以p1p_1p1​进制为例
u≡c0+c1p1+c2p12+c3p13+⋯+cq1−1p1q1−1(modp1q1)u\equiv c_0+c_1p_1+c_2p_1^2+c_3p_1^3+\dots + c_{q_1-1}p_{1}^{q_1-1}\pmod {p_1^{q_1}} u≡c0​+c1​p1​+c2​p12​+c3​p13​+⋯+cq1​−1​p1q1​−1​(modp1q1​​)
那么将原来的nnn个等式转换为nnn个同余式后,联立起来得到同余式组
{u≡c0+c1p1+c2p12+c3p13+⋯+cq1−1p1q1−1(modp1q1)u≡c0′+c1′p2+c2′p22+c3′p23+⋯+cq2−1′p2q2−1(modp2q2)u≡c0′′+c1′′p3+c2′′p32+c3′′p33+⋯+cq3−1′′p3q3−1(modp3q3)⋯u≡c0′′′+c1′′′pn+c2′′′pn2+c3′′′pn3+⋯+cqn−1′′′pnqn−1(modpnqn)\left\{ \begin{aligned} & u\equiv c_0+c_1p_1+c_2p_1^2+c_3p_1^3+\dots + c_{q_1-1}p_{1}^{q_1-1} \pmod {p_1^{q_1}} \\ & u\equiv c_0'+c_1'p_2+c_2'p_2^2+c_3'p_2^3+\dots + c_{q_2-1}'p_2^{q_2-1}\pmod {p_2^{q_2}} \\ & u\equiv c_0''+c_1''p_3+c_2''p_3^2+c_3''p_3^3+\dots + c_{q_3-1}''p_3^{q_3-1}\pmod {p_3^{q_3}} \\ & \cdots \\ & u\equiv c_0'''+c_1'''p_n+c_2'''p_n^2+c_3'''p_n^3+\dots + c_{q_n-1}'''p_n^{q_n-1} \pmod {p_n^{q_n}} \end{aligned} \right. ⎩⎨⎧​​u≡c0​+c1​p1​+c2​p12​+c3​p13​+⋯+cq1​−1​p1q1​−1​(modp1q1​​)u≡c0′​+c1′​p2​+c2′​p22​+c3′​p23​+⋯+cq2​−1′​p2q2​−1​(modp2q2​​)u≡c0′′​+c1′′​p3​+c2′′​p32​+c3′′​p33​+⋯+cq3​−1′′​p3q3​−1​(modp3q3​​)⋯u≡c0′′′​+c1′′′​pn​+c2′′′​pn2​+c3′′′​pn3​+⋯+cqn​−1′′′​pnqn​−1​(modpnqn​​)​
分别对每个同余式求解cic_ici​得到满足单个同余式的uuu,再对整个同余式组使用中国剩余定理得到最终满足所有同余式的解uuu

  • 以解u≡c0+c1p1+c2p12+c3p13+⋯+cq1−1p1q1−1(modp1q1)u\equiv c_0+c_1p_1+c_2p_1^2+c_3p_1^3+\dots + c_{q_1-1}p_{1}^{q_1-1} \pmod {p_1^{q_1}}u≡c0​+c1​p1​+c2​p12​+c3​p13​+⋯+cq1​−1​p1q1​−1​(modp1q1​​)为例,

接下来为了将p1p_1p1​进制表示的uuu应用于求解过程,我们构造
(gu)p−1p1r≡ap−1p1r(modp)(g^u)^{\frac{p-1}{p_1^r}}\equiv a^{\frac{p-1}{p_1^r}} \pmod p (gu)p1r​p−1​≡ap1r​p−1​(modp)
其中rrr是我们设置的变量,后面会对其进行赋值;该式的模数应该也可以换作这里的p1q1p_1^{q_1}p1q1​​或者是其他满足条件的数

将uuu替换成p1p_1p1​进制表示,得到
(gc0+c1p1+c2p12+c3p13+⋯+cq1−1pp1q1−1)p−1p1r≡ap−1p1r(modp)(g^{c_0+c_1p_1+c_2p_1^2+c_3p_1^3+\dots + c_{q_1-1}p_{p_1}^{q_1-1}})^{\frac{p-1}{p_1^r}}\equiv a^{\frac{p-1}{p_1^r}} \pmod p \\ (gc0​+c1​p1​+c2​p12​+c3​p13​+⋯+cq1​−1​pp1​q1​−1​)p1r​p−1​≡ap1r​p−1​(modp)
我们令rrr为111,得到
gc0p−1p1⋅gc1(p−1)⋅gc2(p−1)p1⋯gcq1−1(p−1)p1q1−2≡ap−1p1(modp)g^{c_0\frac{p-1}{p_1}} \cdot g^{c_1(p-1)}\cdot g^{c_2(p-1)p_1} \cdots g^{c_{q_1-1}(p-1)p_1^{q_1-2}} \equiv a^{\frac{p-1}{p_1}} \pmod p gc0​p1​p−1​⋅gc1​(p−1)⋅gc2​(p−1)p1​⋯gcq1​−1​(p−1)p1q1​−2​≡ap1​p−1​(modp)
由费马小定理gp−1≡1(modp)g^{p-1}\equiv 1 \pmod pgp−1≡1(modp),上式等价于
gc0p−1p1≡ap−1p1(modp)g^{c_0\frac{p-1}{p_1}}\equiv a ^ {\frac{p-1}{p_1}} \pmod p gc0​p1​p−1​≡ap1​p−1​(modp)
此时c0c_0c0​的大小范围已知为(0,p1−1)(0,p_1-1)(0,p1​−1)之间,其余变量大小已知,我们爆破c0c_0c0​大小直到满足该同余式;这里就对应了为什么该算法应用条件需要p−1p-1p−1有较小的质因数

这样就可以得到c0c_0c0​,但是我们要知道所有cic_ici​的值来表示出在模p1q1{p_1^{q_1}}p1q1​​意义下的uuu

我们通过更改rrr的值,并应用费马小定理来达到求解cic_ici​的目的,如我们再令rrr为222,得到
gc0p−1p12⋅gc1p−1p1⋅gc2(p−1)⋯gcq1−1(p−1)p1q1−3≡ap−1p12(modp)g^{c_0\frac{p-1}{p_1^2}} \cdot g^{c_1\frac{p-1}{p_1}}\cdot g^{c_2(p-1)} \cdots g^{c_{q_1-1}(p-1)p_1^{q_1-3}} \equiv a^{\frac{p-1}{p_1^2}} \pmod p gc0​p12​p−1​⋅gc1​p1​p−1​⋅gc2​(p−1)⋯gcq1​−1​(p−1)p1q1​−3​≡ap12​p−1​(modp)
由费马小定理gp−1≡1(modp)g^{p-1}\equiv 1 \pmod pgp−1≡1(modp),上式等价于
gc0p−1p12⋅gc1p−1p1≡ap−1p12(modp)g^{c_0\frac{p-1}{p_1^2}} \cdot g^{c_1\frac{p-1}{p_1}}\equiv a ^ {\frac{p-1}{p_1^2}} \pmod p gc0​p12​p−1​⋅gc1​p1​p−1​≡ap12​p−1​(modp)
其中同余式左侧第一项实际上我们已知,那么只用爆破c1c_1c1​的大小即可;其他cic_ici​以此类推

当我们求出整个同余式组里的满足各个同余式模意义下的uuu,使用孙子定理即可得到满足原始问题gu≡a(modp)g^u \equiv a\pmod pgu≡a(modp)的uuu

那么用相同的方法再求解出gv≡b(modp)g^v \equiv b\pmod pgv≡b(modp)的vvv即可,代回同余式x≡v⋅u−1(modp−1)x \equiv v\cdot u^{-1} \pmod {p-1}x≡v⋅u−1(modp−1)求得xxx

看完整个流程,可能会想为什么不直接对ax≡b(modp)a^x\equiv b \pmod pax≡b(modp)使用之后将xxx转化为p−1p-1p−1的素因子的进制等等操作,这样就可以直接得到xxx,而不用拐弯抹角地去求u,vu,vu,v,再来求xxx;这是因为该算法只针对原根起效,也就是说,如果aaa是原根,那么这样操作是可以的;但如果aaa不是原根,就无法求得正确结果,其具体原因可以见ReferenceReferenceReference部分的文章

PythonImplementationPython\ ImplementationPython Implementation

from Crypto.Util.number import *
from sympy.polys.galoistools import gf_crt
from sympy.polys.domains import ZZ
import gmpy2
import randomdef Pohlig_Hellman(g, h, p):# 模数分解p_1 = p - 1d, factors = 2, []while d*d <= p_1:while (p_1 % d) == 0:factors.append(d)p_1 //= dd += 1if p_1 > 1:factors.append(p)factors = [[i, factors.count(i)] for i in set(factors)]# 求每个素因子进制下的c_ix = []for factor in factors:c_i_list = []for i in range(factor[1]):if i != 0:beta = (beta * pow(g, -(c_i_list[-1] * (factor[0] ** (i - 1))), p)) % pelse:beta = he1 = pow(beta, (p-1) // (factor[0] ** (i + 1)), p)e2 = pow(g, (p-1) // factor[0], p)for c_i in (range(factor[0])):if pow(e2, c_i, p) == e1:c_i_list.append(c_i)breakx.append(c_i_list)# 将模p_i意义下的p_i进制表示转换为模p_i意义下的十进制system = []for i, factor in enumerate(factors):res = 0for j, x_j in enumerate(x[i]):res += x_j * (factor[0] ** j)res = res % (factor[0] ** factor[1])system.append(res)# 中国剩余定理factors = [factors[i][0] ** factors[i][1] for i in range(len(factors))]result = gf_crt(system, factors, ZZ)return resultif __name__ == "__main__":p = 7863166752583943287208453249445887802885958578827520225154826621191353388988908983484279021978114049838254701703424499688950361788140197906625796305008451719a = random.randint(0, 2 ** 512)x = random.randint(0, 2 ** 256)b = pow(a, x, p)print("real_x = {}".format(x))res = Pohlig_Hellman(a, b, p)print("x1 = {}".format(res))# sage: p = 7863166752583943287208453249445887802885958578827520225154826621191353388988908983484279021978114049838254701703424499688950361788140197906625796305008451719
# sage: primitive_root(p)
# 13g = 13 # p的本原元为13u = Pohlig_Hellman(g, a, p)v = Pohlig_Hellman(g, b, p)try:x = gmpy2.invert(u, p - 1) * v % (p - 1)print("x2 = {}".format(x))except: # u 和 p-1 可能不互素,导致之间没有逆元;该情况将u除以最大公因数使得两者之间互素即可,最后结果除以相应的数即可i = 0 gcd = gmpy2.gcd(u, p - 1)while True:if gmpy2.gcd(u, p - 1) != 1:u = u // gmpy2.gcd(u, p - 1)      i += 1else:breakassert gmpy2.gcd(u, p - 1) == 1x = (gmpy2.invert(u // gmpy2.gcd(u, p - 1), p - 1) * v) % (p - 1) // (gcd ** i)print("x = {}".format(x))"""
a ^ x \equiv b (mod p) 之中a不是原根
real_x = 17475167858715014509948693871106677723065342839264165381680037187400995034209
x1 = 3931583376291971643604226624722943901442979289413760112577413310595676694494454509217307369704071534867821221958389972909818020158235480633350085553499260068
x = 17475167858715014509948693871106677723065342839264165381680037187400995034209
""""""
a ^ x \equiv b (mod p) 之中a是原根
real_x = 59538927048508916825466804038603833711975305674466217174924215808245351055236
x1 = 59538927048508916825466804038603833711975305674466217174924215808245351055236
x2 = 59538927048508916825466804038603833711975305674466217174924215808245351055236
"""

ReferenceReferenceReference

(10条消息) Pohlig-Hellman算法求解离散对数问题_国科大网安二班的博客-CSDN博客_pohlig-hellman

Pohlig_hellman/Pohlig_hellman.py at master · Sarapuce/Pohlig_hellman (github.com)

【应用代数】本原元和极小多项式 | Hope (leohope.com)

Pohlig-Hellman算法解决DLP问题相关推荐

  1. Pohlig-Hellman算法求Elgamal算法私钥+大步小步法解决DLP(离散对数问题)

    目录 问题描述:在利用Elgamal算法公钥中,已知参数(本题中数字均为十进制整数) 一.大步小步法 (一).原理: (二).实现思路 (三).代码实现 二.Pohlig-Hellman (一). 原 ...

  2. 舞伴问题数据结构java_Gale-Shapley算法解决舞伴问题过程详解(C++实现)

    舞伴问题是这样的:有 n 个男孩与 n 个女孩参加舞会,每个男孩和女孩均交给主持一个名单,写上他(她)中意的舞伴名字.无论男孩还是女孩,提交给主持人的名单都是按照偏爱程度排序的,排在前面的都是他们最中 ...

  3. 部分背包的贪婪算法 java_使用JAVA实现算法——贪心算法解决背包问题

    packageBasePart;importjava.io.BufferedReader;importjava.io.FileInputStream;importjava.io.IOException ...

  4. 一致性哈希算法——算法解决的核心问题是当slot数发生变化时,能够尽量少的移动数据

    一致性哈希算法--算法解决的核心问题是当slot数发生变化时,能够尽量少的移动数据 参考文章: (1)一致性哈希算法--算法解决的核心问题是当slot数发生变化时,能够尽量少的移动数据 (2)http ...

  5. 用贪心算法解决马踏棋盘问题

    用贪心算法解决马踏棋盘问题 参考文章: (1)用贪心算法解决马踏棋盘问题 (2)https://www.cnblogs.com/Allen-win/p/7095293.html 备忘一下.

  6. A*算法解决八数码问题 Java语言实现

    A*算法解决八数码问题 Java语言实现 参考文章: (1)A*算法解决八数码问题 Java语言实现 (2)https://www.cnblogs.com/beilin/p/5981483.html ...

  7. 【算法】模拟退火算法解决TSP问题的matlab实现

    [算法]模拟退火算法解决TSP问题的matlab实现 参考文章: (1)[算法]模拟退火算法解决TSP问题的matlab实现 (2)https://www.cnblogs.com/wenyehoush ...

  8. Hash算法解决冲突的四种方法

    Hash算法解决冲突的四种方法 参考文章: (1)Hash算法解决冲突的四种方法 (2)https://www.cnblogs.com/lyfstorm/p/11044468.html 备忘一下.

  9. 用BFS(广度优先搜索queuelist)算法解决农夫过河问题

    用BFS(广度优先搜索queue&&list)算法解决农夫过河问题 一.问题需求分析 一个农夫带着一只狼.一只羊和一棵白菜,身处河的南岸.他要把这些东西全部运到北岸.问题是他面前只有一 ...

最新文章

  1. java 1%10_Java 操作符与运算符详解
  2. 导出txt文件宏_XLM宏反混淆工具:提取和反混淆XLM宏
  3. 如何将 Nginx 性能提升10倍?这10个“套路”请收好!
  4. QT的QCheckBox类的使用
  5. 基于Docker的GoldenGate部署
  6. 《编写高质量代码:改善c程序代码的125个建议》——建议14-2:在右移中合理地选择0或符号位来填充空出的位...
  7. textarea如何实现高度自适应?
  8. 甜品果汁饮品拍摄设计海报,美如蓬莱仙境!
  9. 如何修改游戏服务器端的数据,如何修改网络游戏服务器数据
  10. python-opencv使用摄像头
  11. java构造函数_Java开发人员也会犯的十大错误
  12. 在JavaScript面向对象编程中使用继承(5)
  13. 语义分割和实例分割概念
  14. 第三百七十二天 how can I 坚持
  15. triz矛盾矩阵_怎样利用项目TRIZ矛盾定义法,突破产品“创
  16. 小米平板1-专用解账号锁激活设备救砖线刷包 一键刷机
  17. [ActiveForm] -- ActiveForm::begin表单用法
  18. multicast msdp 1
  19. Menu键_subMenu设置
  20. BUG一词是如何来的?

热门文章

  1. taptap领礼包怎么显示服务器繁忙,原神taptap预约奖励领取教程 taptap预约奖励怎么领取...
  2. 文件备份 服务器,服务器文件备份
  3. 【微信篇】PC端微信文件夹里的“微信号“
  4. Poi 自定义封装方法 合并excel中的单元格
  5. 百度地图行政区划边界线获取,只要界线,遮罩层透明设置方法
  6. android开发指纹解锁,Android-指纹解锁技术
  7. webpack基础配置
  8. Dolby fMP4视频seek后卡顿问题分析
  9. 编程理念-程序基本编写IPO方法
  10. 全国计算机一级选择题免费,全国计算机一级考试选择题试题与详细答案