首页 > 其他分享 >离散对数(持续更新中)

离散对数(持续更新中)

时间:2023-07-24 10:26:22浏览次数:34  
标签:pow self 更新 离散 key print 对数 pi mod

1,DH&DLP

题目源码:

from Crypto.Util.number import *
import hashlib


class D_H():
    def __init__(self):
        self.a = getPrime(128)
        self.b = getPrime(128)
        self.p = getPrime(1024)
        self.g = getPrime(128)
        print("p =", oct(self.p))
        print('g =', oct(self.g))

    def Alice(self):
        A = pow(self.g, self.a, self.p)
        print('A =', oct(A))

    def Bob(self):
        B = pow(self.g, self.b, self.p)
        print('B =', oct(B))

    def key_exchange(self):
        key = pow(self.g, self.a * self.b, self.p)
        return key


DH = D_H()
DH.Alice()
DH.Bob()
key = DH.key_exchange()
flag = "flag{" + hashlib.md5(str(key).encode()).hexdigest() + "}"

"""
p = 0o100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002320461720107654672567257101774542402073
g = 0o2065141432751712040220440246142105771015421
A = 0o43613040531475331260645277703363154024375552447624145423154467212453566671627031247565752140361214442354760036367561323225723114644705564775357161722423055427767542147531265612413043244400626062610066133355056455656354327315127131604056020315605217552254443755433425633455524145337447120342451441170743174123742307207301542043164563340422677
B = 0o60346662663461540211665020605034076206107430140346645020415164214412402345454104341770532135130621505726240703066624656170403450176106112505427262227076032102233051024443206700250621734407223434463067213634725130117240556410501066411312272344517322556714720077305705512606154144764640154454705523667767514601216365471777467432753500477011706
"""

 先分析源码,可知 求 key 即可得flag,求key 需先求 self.a ,self.b

而self.a , self.b 分别为A , B 的指数,所以涉及DLP (离散对数)

至此,目标清晰(self.a 默认为 a, self.b默认为 b)

 

继续:

这是道 密钥交换协议 (Diffie Hellman) 加 DLP 的 Pohlig-Hellman 算法 ,涉及p-1 光滑数 Diffie Hellman 原理较为简单,无需解释也可自行看懂 原理:   所以采用 中间人攻击 ,如图   即 我们自行 生成两个私钥,X1,X2,用相同的a,q分别生成两个公钥,Y1,Y2,分别发给Alice ,Bob 由于我们 必然知道 自己的两个私钥, $$K1=(Y1)^{XB} mod q=(YB)^{X1} mod q$$   X1,YB,q,Y1已知,据此通过离散对数求指数XB,即此题的 b ,同理可得 a   自行生成两个私钥 a1,b1,两个公钥,W1,W2
from Crypto.Util.number import *
import hashlib

class D_H():
    def __init__(self):
        self.a = getPrime(128)  #私钥a
        self.b = getPrime(128)  #私钥b
        self.p = 0o100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002320461720107654672567257101774542402073
        self.g = 0o2065141432751712040220440246142105771015421

        print('a =',oct(self.a))
        print('b =', oct(self.b))

    def Alice(self):
        A = pow(self.g, self.a, self.p)
        print('W1 =', oct(A))    #Ya

    def Bob(self):
        B = pow(self.g, self.b, self.p)
        print('W2 =', oct(B))    #Yb

    def key_exchange(self):
        key = pow(self.g, self.a * self.b, self.p)
        return key

DH = D_H()
DH.Alice()
DH.Bob()
key = DH.key_exchange()
flag = "flag{" + hashlib.md5(str(key).encode()).hexdigest() + "}"


# # 中间人
# a1 = 0o2462471162741234772727054414536530023564165
# b1 = 0o3776362545773344220254412013272563345646375
# W1 = 0o30177410335615713542026512603323473205434005561747576441000340673116717446660223313444625136651624625241317244472674410576033351505145102532723042071050116471427334542406460562263224765334125507145737557104465406333501613713727135003611011143450112471232770123366033751722734673337036650302174034661504555667574715231200341006620333553077066
# W2 = 0o21767767521415454605102034111542047036764671756720324646106371712334761330532743112346114006302441445406533657740062602010422272601755373477507607505570626733347000552376671501627563674665230627166705564211645416753645310162172100735325175505371110602207023457024257032454332272025410051011476055743503274466610063274263742714643617465701710
  W1,W2,分别公布给两人,用以生成相应的K等式
K2 = pow(B,b1,p)    # =pow(W2,b,p)
print(K2)

K1 = pow(A,a1,p)   #=pow(W1,a,p)
print(K1)
  到此,a,b即在眼前     下面介绍一下离散对数中的 Pohig-Hellman算法 函数实现: base^e = a discrete_log(a,base,ord,operation) 如上,base为底,求a的对数   ord为base的阶,可以缺省,operation可以是'+'与'*',默认为'*' 通用的求离散对数的方法(Pohlig-Hellman+BSGS) Pohig-Hellman算法是一种求解光滑阶循环群上的离散对数的方法。
  • 要求a≡g^x (mod p)中 g必须是原根 (对于 g 不是原根的情况,需要利用原根将原方程转化成两个关于原根的离散对数问题。
  • 要求阶是光滑的(p-1可拆为多个素数相乘)
光滑的,即形如此 (可将p改为十进制,有利理解) 从此中,便可知此题为何会用 离散对数中的 Pohig-Hellman算法   算法原理: 可先浅了解一下 阶,原根,时间复杂度   即 g^a ≡ 1 (mod p) ,当a为p-1时,g为模p的原根   时间复杂度:(不知其定义如何描述,可自行了解) 时间复杂度越来越大,执行的效率越来越低 若太复杂,计算时间所需太长,会崩,如下见  

回归正题

$$g^x\equiv h(mod\ p)$$ $$1,φ(p)=p-1=p1^{k1}*p2^{k2}...pm^{km}(m为质因数个数)$$   2,对每个素因子pi,将x表示成pi进制,有 $$x = a0+a1pi+a2(pi)^2+a3(pi)^2+...+(a(ki-1))pi^{ki-1} (mod\ {p}_{i}^{ki})$$ (即把x写成pi进制,每个系数ai都小于pi)   3,对于$$g^x\equiv h(mod\ p)$$,两边同时乘以 $$\frac{p-1}{pi^r}$$ 即 $$(a^x)^{\frac{p-1}{{p}_{i}^r}}\equiv b^{\frac{p-1}{{p}_{i}^r}} (mod\ p)$$   4,展开x,得到 $$(a^{{{p}_{i}^0+{p}_{i}^1a1+{p}_{i}^2a2...+{p}_{i}^{{k}_{i-1}{a}_{ki-1}}}})^\frac{p-1}{{p}_{i}^r}\equiv b^\frac{p-1}{{p}_{i}^r}(mod\ p)$$   5,当r=1时,展开,得 $$a^{a0*\frac{p-1}{pi}}*a^{(p-1)a1}*(a^{p-1})^{pa2}*(a^{p-1})^{p^2a3}...(a^{p-1})^{p^{{k}_{i}-2}a{k}_{i-1}}\equiv b^\frac{p-1}{{p}_{i}^r} (mod\ p)$$   6,观察知,第二项及此后的每一项,由欧拉定理$$a^{p-1}\equiv1 (mod\ p)$$ 得,每一项皆为1,故得(r=1) $$a^{a0*\frac{p-1}{pi}}\equiv b^{\frac{p-1}{{p}_{i}^r}} (mod\ p)$$ => $$a0*\frac{p-1}{pi} \equiv \frac{p-1}{pi}(mod\ p-1)$$ 因为ai∈[0,pi-1](前文提到了pi进制,我也不知所以然),故可以在复杂度$$O(pi)$$的时间内暴力求出a0   注:若$$a^j\equiv a^i (mod p)$$,则$$i\equiv j(mod\ p-1)$$   7,得到a0后,令r = r+1,回到步骤5,直到所有ai被求出后,可得到 $$x={p}_{i}^0a0+{p}_{i}^1a1+{p}_{i}^2a2...+{p}_{i}^{{k}_{i-1}}a{k}_{i-1}(mod\ {p}_{i}^{ki})$$   8,在算出m个关于x的式子后,即用中国剩余定理求解 值得一提到是,中国剩余定理所需n的组数需满足=> $$m^e<{n}_{1}*{n}_{2}*{n}_{3}...$$ 所以无需所有p-1的质因子           可结合下面脚本理解(具体这就不加解释,公式打累了(手动狗头))  

# K2 = 54814846335780447316835818815553396107825604069271218449213491151351336059792767162361300914069004913012467841792862632782405340663569408429208004574228303423550868433039264867808382293167572116274903923603187366829575727502616919165542138514088692003615212224589562650802481642791540343802658343564140775050
# p = int(0o100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002320461720107654672567257101774542402073)
# W2 = int(0o21767767521415454605102034111542047036764671756720324646106371712334761330532743112346114006302441445406533657740062602010422272601755373477507607505570626733347000552376671501627563674665230627166705564211645416753645310162172100735325175505371110602207023457024257032454332272025410051011476055743503274466610063274263742714643617465701710)

import hashlib
"""
n = 89884656743115795386465259539451236680898848947115328636715040578866337902750481566354238661203768010560056939935696678829394884407208311246423715319737062188883946712432742638151109800623047059726541476042502884419075341171231440736956555270413618581675255342293149119974022969989259739901207135911877936187
factor(n-1)
# 2 * 659 * 144811523 * 158091863 * 167642023 * 194814973 * 198114301509256817 * 1524198318315919100927 * 302061228405984819868188635839278249994068296319393442016901959084878254985929326557136330675603997640265462782948042782543029960066166632904951616712643712462381886167331227465971149482608610738439655060064241698902750467248492676743
"""
# c = pow(m, secret, n)
# h = g^x mod p
def r(h, g, N, p, qi):
    Zp = Zmod(p)
    h = pow(h, N//qi, p)
    g = pow(g, N//qi, p)
    ri = discrete_log(Zp(h), Zp(g))
    return int(ri)
m = 0o21767767521415454605102034111542047036764671756720324646106371712334761330532743112346114006302441445406533657740062602010422272601755373477507607505570626733347000552376671501627563674665230627166705564211645416753645310162172100735325175505371110602207023457024257032454332272025410051011476055743503274466610063274263742714643617465701710
n = 89884656743115795386465259539451236680898848947115328636715040578866337902750481566354238661203768010560056939935696678829394884407208311246423715319737062188883946712432742638151109800623047059726541476042502884419075341171231440736956555270413618581675255342293149119974022969989259739901207135911877936187
c = 54814846335780447316835818815553396107825604069271218449213491151351336059792767162361300914069004913012467841792862632782405340663569408429208004574228303423550868433039264867808382293167572116274903923603187366829575727502616919165542138514088692003615212224589562650802481642791540343802658343564140775050
tmp_list = [659, 144811523, 158091863, 167642023, 194814973]
r_list = []
for qi in tmp_list:
    tmp = r(c,m,n-1,n,qi)
    print(tmp)
    r_list.append(tmp)
x = crt(r_list, tmp_list)

module = 1
for i in tmp_list:
    module *= i
while True:
    if int(x).bit_length()>128:
        print('fail')
        break
    if int(pow(m, x, n))==c:
        print('x =', x)
#         flag = "flag{"+hashlib.md5(str(x).encode()).hexdigest()+"}"
#         print(flag)
        break
    x += module
回到题目,此处的x即为所求b,同理得a     最后
a = 288439857354393866763185538169340562833
b = 253100920167170926044570003097335817769
p = 89884656743115795386465259539451236680898848947115328636715040578866337902750481566354238661203768010560056939935696678829394884407208311246423715319737062188883946712432742638151109800623047059726541476042502884419075341171231440736956555270413618581675255342293149119974022969989259739901207135911877936187
g = 0o2065141432751712040220440246142105771015421
key = pow(g, a * b, p)
flag = "flag{" + hashlib.md5(str(key).encode()).hexdigest() + "}"
print(flag)
# flag{1515950b17d8b66efc6e47f812448721}
至此,答题结束       闲聊: 2023 DASCTF - 0x401的ezDHKE,题型与此雷同,本以为能解,却棋差一招,对于光滑数的原根理解不够透彻 只随便传了个光滑数,便以为可解,实乃与此题无缘(bushi)
from Crypto.Util.number import *
from random import choice

def myPrime(bits):
    while True:
        n = 2
        while n.bit_length() < bits:
            n *= choice(sieve_base)
        if isPrime(n + 1):
            return n + 1

# g = 2
p = myPrime(1024)
          具体可见如下博客 博客链接参考: 密钥交换协议 (Diffie Hellman),Pohig-Hellman算法: 离散对数 | DH | ElGamal 密码学-06-针对离散对数的攻击 · 陈亮的个人博客 离散对数(La佬) Pohlig-Hellman 算法 离散对数问题——pohlig-hellman算法讲解(有例子)_DrGilbert的博客-CSDN博客   离散对数函数参数说明: sage之离散对数求解_离散对数求解算法_ckm1607011的博客-CSDN博客   算法的时间与空间复杂度(一看就懂)   数学--数论--原根(循环群生成元)_求模19的所有原根过程_风骨散人Chiam的博客-CSDN博客  

 

 

 

 

 

 

 

 

 

 

标签:pow,self,更新,离散,key,print,对数,pi,mod
From: https://www.cnblogs.com/Wbuildings/p/discrete_log.html

相关文章

  • 一点注意事项(实时更新)
    一点注意事项(实时更新)函数没事干不要封装着玩,会T的很惨。不要对STL的速度抱有侥幸且不合理的幻想。如果可以,尽量不用string。请不要对自己的口胡能力过度自信,认真计算复杂度。不要偷懒,过度依赖平板电视等外部库的模板不利于青少年智力发展。如果需要使用指针,请关注时空复杂......
  • GNN学习 GNN Layer(持续更新中)
    GNN学习GNNLayerGNN的通用框架1.对GNN的一个网络层进行信息转换和信息聚合两个操作2.连接GNN的网络层3.图增强,分为图特征增强和图结构增强4.学习目标,有监督学习还是无监督学习,节点/边/图级别1.信息转换和信息聚合GNNLayer=Message+Aggregation不同的实例有不同的信......
  • android页面突然闪一下更新
    Android页面闪烁更新问题解析与解决方案1.简介在Android开发中,我们经常会遇到页面展示闪烁的情况,即页面在更新数据后会短暂地闪烁一下。这种现象通常是由于页面数据刷新的频率过高或者刷新机制不合理所引起的。本文将从原因分析、解决方案和代码示例三个方面来介绍如何解决An......
  • android 热更新手写框架
    Android热更新手写框架实现流程热更新是指在不修改已安装应用程序的情况下,通过下载差异化的资源文件,实现应用程序的更新。在Android开发中,我们可以手动实现一个热更新框架,使得应用程序能够在不重新安装的情况下更新。下面是实现Android热更新框架的步骤:步骤描述1从服......
  • mongodb更新字段的值
    MongoDB更新字段的值作为一名经验丰富的开发者,你需要教会一位刚入行的小白如何在MongoDB中更新字段的值。在本文中,我将向你展示整个更新字段的流程,并提供每一步所需的代码和注释。更新字段的流程下面是更新字段的流程。你可以使用表格来展示这些步骤。步骤描述步骤......
  • 【持续更新】C 和 C++ 区别很大!
    一些容易被忽略的C与C++的重要区别头文件C标准库头文件名在C++中通常去除扩展名,并加上c前缀,如:stdio.h->cstdiostdlib.h->cstdlib其中一个重要的区别是后者保证与C库兼容的各个函数名可以在std命名空间中找到,但并不保证它们不存在于根命名空间中,这可能会引......
  • INFINI Labs 产品更新 | Easysearch 新增分词插件、Gateway 支持邮件发送等功能
    INFINILabs产品又更新啦~,本次更新概要如下:Easysearch新增了分词插件、优化了生命周期管理功能等;Gateway新增smtp过滤器来支持邮件的发送,支持自动跳过因为异常关闭而损坏的磁盘队列文件等;Console新增熔断器监控指标、新增矩形树图(Treemap)、优化了探针Agent指标采集和集......
  • android 线程更新ui
    Android线程更新UI的实现简介在Android开发中,我们常常会遇到需要在后台线程中进行耗时操作,然后在UI线程中更新界面的情况。本文将介绍如何实现在Android中使用线程更新UI,并提供相应的代码示例和解释。实现流程下面是实现"Android线程更新UI"的整个流程:步骤描述步骤1......
  • Struts2中对数字进行格式化,1、将数字用 , 号分隔 2、将小数格式化为百分比 ...
    Struts2中对数字进行格式化,1、将数字用,号分隔2、将小数格式化为百分比2008-12-2422:36一、资源文件的配置(applicationResource_zh_CN.properties)format.number={0,number,###,###.##}format.discount={0,number,###.#######%}二、struts.xml<?xmlve......
  • vuex中的state更新了,但是页面不更新
    问题:我有两个页面,都是用了同一个变量,我在A页面更改了变量,然后我切到B页面,B页面上的变量没有刷新 原因:是因为我这两个页面的路由在配置的时候都是用了keep-alive,所以导致在两个keep-alive之间的页面切换时,页面不会主动刷新,只会展示第一次加载的内容router.config.js 解......