大步小步算法

Baby-step giant-step

称之为大步小步算法,一种解决离散对数问题的方法,其主要思路是中间相遇攻击。

y=g^{x}

我们可以把这个 x转化为x = i*m+j, 而这个m的值就是⌈√n⌉, 并且ij的值要在m的范围内,所以m的值决定着该算法计算出结果所需要的时间。

所以该式可变为:
y = g^{x} = g^{i*m + j} \\=> y*g^{-m*i} = g^j

接下来就可以枚举j,计算g^j的结果并存储下来,接着枚举i计算y*g^(-m*j)的值,找到g^jy*g^(-m*j)相等的时候,这时的ij就是我们要找的值。之后带入x = i*m + j,这时i*m+j的值就是x的值。

例:

已知:g = 17
p = 509
y = g^x%p = 438
计算x的值

对于这个式子我们就可以先枚举j先算出结果并存入列表中。

jg^j % p
117
13238
25278
44356
59438

然后我们在对i进行枚举

iyg^(-m*i) % p
1199
2238
25185
44368
59445

这里可以找到i=2, j=13时,他们求出来得值是一样的,所以可以算出 x=i*m+13, m在这里是23, 所以可以算出m的值为59

算法代码:

from gmpy2 import *
​
g = 17
p = 509
y = 438
m = iroot(p, 2)[0] + 1
​
def BSGS(g, y, p):
    m = iroot(p, 2)[0] + 1
    s = {pow(g, j, p): j for j in range(m)}
    gs = pow(g, -m, p)
    for i in range(m):
        if y in s:
            return m*i + s[y]
        y = y * gs % p
    return None
print(BSGS(g, y, p))

再举个用在CTF中的例子:

from libnum import *
from gmpy2 import *
​
flag = "flag{big_and_small}"
a =  s2n(flag)
print(a)
m = a >> 16 << 16
p = generate_prime(1024)
g = 5
y = pow(g,a,p)
print(f"m = {m}")
print("g =", g)
print("p =", p)
print("y =", y)
​
#m = 2284117282071477104642039231536944446836572160
#g = 5
#p = 117061102100923822494374971271356428838245797897131713833497324490347029897509453234867144323074426358251468387009784964409490629474760505325012358657612358218630936761844853452752207513376553400570437173183245325363865380385444332069521612219917516076129636378470207520184345636826950827640031147884327602403
#y = 36330338308028857799449375552374448525921689801126735837219113818543840068942804412602004817464522788143367479566994608891201675854663902669408381421532026724950780811697860458785100785315287105361742435587380380417609918284799177467034247188834721615753928207192485082356827804549590792117891230279436213258

这道题也要用到BSGS(大步小步算法)。已知m的值是a向右向左移位16位得到的数,要求的数是m缺少的16位数, 所以可以把目标设为只求缺少的数,这样我们要求的数字最大就是(2^16),而不是去整体计算a这个大值。

接下来可以写出算法代码:

from libnum import *
from gmpy2 import *
​
m = 2284117282071477104642039231536944446836572160
g = 5
p = 104902226273988324576427043280139630983677434981789024088951356016939994526304119354435543071985576434554541580765980475339863817923069063092822047759376193281443519615446894334112711636144801809678018855363243259870518701678872861580764859373668820885488992214504069164524801155987240703746883303678741931657
y = 52132387535704137390458836331516728932227502073670482441552732370459557430160087735998314933737812855984248770511516860301143061293647971484306910330283327130899876785232553721318312581135200914802966676159312701878015611579070659605675344114334474279389271370807188711609485615280774712598619602033548583710
def BSGS(g, y, p, bound):
    x = iroot(bound, 2)[0] + 1
    s = {pow(g, j, p): j for j in range(x)}
    sg = pow(g, -m, p)
    for i in range(m):
        if y in s:
            return i*x + s[y]
        y = y * sg % p
    return None
​
a = BSGS(g, y*invert(pow(g,m,p), p)%p, p, 2**32) + m
print(n2s(int(a)))
​
#b'flag{big_and_small}'

在这个代码中。

y*invert(pow(g, m, p), p) % p :表示的是

y*g^{-m} \\\because y=g^{a}\\a = m + a\_low\\\therefore y = g^{a}=g^{m+a\_low}\\\therefore y * g^{-m} = g^{a\_low}

这样我们就只需要求a_low的值即可。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值