针对青龙杯2020“you raise me up"的学习
题目如下:
from Crypto.Util.number import *
import random
n = 2 ** 512
m = random.randint(2, n-1) | 1
c = pow(m, bytes_to_long(flag), n)
print 'm = ' + str(m)
print 'c = ' + str(c)
# m = 391190709124527428959489662565274039318305952172936859403855079581402770986890308469084735451207885386318986881041563704825943945069343345307381099559075
# c = 6665851394203214245856789450723658632520816791621796775909766895233000234023642878786025644953797995373211308485605397024123180085924117610802485972584499
这题就是显而易见已知m,n,c,c等于m^flag模n,但是这个n非常非常大,直接爆破显然有些不合理,因此通过查询得知这题是一个离散对数问题,在sympy库里有很多解决离散对数的问题,这里采用discrete_log函数直接解决(注:dsicrete_log(x,y,z)中,x是模数,y是余数,z是底数),从而得到flag{5f95ca93-1594-762d-ed0b-a9139692cb4a}。
m = 391190709124527428959489662565274039318305952172936859403855079581402770986890308469084735451207885386318986881041563704825943945069343345307381099559075
c = 6665851394203214245856789450723658632520816791621796775909766895233000234023642878786025644953797995373211308485605397024123180085924117610802485972584499
n=2**512
import sympy
import binascii
flag=sympy.discrete_log(n,c,m)
print(binascii.unhexlify(hex(flag)[2:]))
但是显然这题不能到这里就结束了,针对其他的离散对数问题,也深入学习了一下
1.BSGS(小步大步算法)
目前存在一个问题:,求解x
我们已知
则P-1就是最小的阶,设已知一个数m,我们不妨把x表示成x=mi-j,且,所以会存在
此时直接爆破i和j即可。
2.pohlig-hellman算法(复杂度高于BSGS)
设存在质数P
目前已知
设其原根为G,则使
则有
也即
故
即求ai,bi。
此时进行素数分解
将X写作进制,使得每一个因数都不大于。
原式化成
展开X
令r=1.则前一项后的所有项均为一(费马小定理),从而可得到a0,以此类推,得到ai的值
从而得到X的值,最后可得m个关于X的式子,运用中国剩余定理可解。