补充:
MMI = lambda A, n,s=1,t=0,N=0: (n < 2 and t%N or MMI(n, A%n, t, s-A//n*t, N or n),-1)[n<1] #逆元计算
·“A”是输入的整数。 n’是模数。 ·“s’是一个累加器,默认为1。 ·“t”是另一个累加器,默认为0. ·“N’也是一个累加器,默认为0.
原理及相关推导
由于打出来稍显困难,决定将就一下。
01
题目
from Crypto.Util.number import * flag = b'Spirit{***********************}' plaintext = bytes_to_long(flag) length = plaintext.bit_length() a = getPrime(length) b = getPrime(length) n = getPrime(length) seed = 33477128523140105764301644224721378964069 print("seed = ",seed) for i in range(10): seed = (a*seed+b)%n #进行了十次循环 ciphertext = seed^plaintext #一次异或 print("a = ",a) print("b = ",b) print("n = ",n) print("c = ",ciphertext) # seed = 33477128523140105764301644224721378964069 # a = 216636540518719887613942270143367229109002078444183475587474655399326769391 # b = 186914533399403414430047931765983818420963789311681346652500920904075344361 # n = 155908129777160236018105193822448288416284495517789603884888599242193844951 # c = 209481865531297761516458182436122824479565806914713408748457524641378381493
exp:
按题目中过程进行
from Crypto.Util.number import * seed = 33477128523140105764301644224721378964069 a = 216636540518719887613942270143367229109002078444183475587474655399326769391 b = 186914533399403414430047931765983818420963789311681346652500920904075344361 n = 155908129777160236018105193822448288416284495517789603884888599242193844951 c = 209481865531297761516458182436122824479565806914713408748457524641378381493 for i in range(10): seed = (a * seed + b) % n print(seed) m = seed ^ c print(m) print(long_to_bytes(m)) # 66922225691609264283867072422037270235122544465805107339080357133935022024 # 147424144810829416246263598495658483373775464141840154829404726417260880253 # b'Spirit{0ops!___you_know__LCG!!}'
02(已知后项求前项)
题目:
from Crypto.Util.number import * flag = b'Spirit{*****************************}' plaintext = bytes_to_long(flag) length = plaintext.bit_length() a = getPrime(length) b = getPrime(length) n = getPrime(length) seed = plaintext for i in range(10): seed = (a*seed+b)%n ciphertext = seed print("a = ",a) print("b = ",b) print("n = ",n) print("c = ",ciphertext) # a = 59398519837969938359106832224056187683937568250770488082448642852427682484407513407602969 # b = 32787000674666987602016858366912565306237308217749461581158833948068732710645816477126137 # n = 43520375935212094874930431059580037292338304730539718469760580887565958566208139467751467 # c = 8594514452808046357337682911504074858048299513743867887936794439125949418153561841842276
只需要将题中过程逆向推回去,应用公式1
import gmpy2 from Crypto.Util.number import * a = 59398519837969938359106832224056187683937568250770488082448642852427682484407513407602969 b = 32787000674666987602016858366912565306237308217749461581158833948068732710645816477126137 n = 43520375935212094874930431059580037292338304730539718469760580887565958566208139467751467 c = 8594514452808046357337682911504074858048299513743867887936794439125949418153561841842276 t = gmpy2.invert(a, n) seed = c for i in range(10): seed = t * (seed - b) % n print(long_to_bytes(seed)) #b'Spirit{Orzzz__number_the0ry_master!!}'
03(求增量b)
from Crypto.Util.number import * flag = b'Spirit{*********************}' plaintext = bytes_to_long(flag) length = plaintext.bit_length() a = getPrime(length) seed = getPrime(length) n = getPrime(length) b = plaintext output = [] for i in range(10): seed = (a*seed+b)%n output.append(seed) ciphertext = seed print("a = ",a) print("n = ",n) print("output1 = ",output[6]) print("output2 = ",output[7]) # a = 3227817955364471534349157142678648291258297398767210469734127072571531 # n = 2731559135349690299261470294200742325021575620377673492747570362484359 # output1 = 56589787378668192618096432693925935599152815634076528548991768641673 # output2 = 2551791066380515596393984193995180671839531603273409907026871637002460
exp:
from Crypto.Util.number import * a = 3227817955364471534349157142678648291258297398767210469734127072571531 n = 2731559135349690299261470294200742325021575620377673492747570362484359 output1 = 56589787378668192618096432693925935599152815634076528548991768641673 output2 = 2551791066380515596393984193995180671839531603273409907026871637002460 b = (output2 - a * output1) % n print(long_to_bytes(b)) #b'Spirit{Y0u_@r3_g00d_at__math}'
04(未知a,b求seed)
from Crypto.Util.number import * flag = b'Spirit{********************************}' plaintext = bytes_to_long(flag) length = plaintext.bit_length() a = getPrime(length) b = getPrime(length) n = getPrime(length) seed = plaintext output = [] for i in range(10): seed = (a*seed+b)%n output.append(seed) print("n = ",n) print("output = ",output) # n = 714326667532888136341930300469812503108568533171958701229258381897431946521867367344505142446819 # output = [683884150135567569054700309393082274015273418755015984639210872641629102776137288905334345358223, 285126221039239401347664578761309935673889193236512702131697050766454881029340147180552409870425, 276893085775448203669487661735680485319995668779836512706851431217470824660349740546793492847822, 670041467944152108349892479463033808393249475608933110640580388877206700116661070302382578388629, 122640993538161410588195475312610802051543155060328971488277224112081166784263153107636108815824, 695403107966797625391061914491496301998976621394944936827202540832952594905520247784142392337171, 108297989103402878258100342544600235524390749601427490182149765480916965811652000881230504838949, 3348901603647903020607356217291999644800579775392251732059562193080862524671584235203807354488, 632094372828241320671255647451901056399237760301503199444470380543753167478243100611604222284853, 54758061879225024125896909645034267106973514243188358677311238070832154883782028437203621709276]
exp:
import gmpy2 from Crypto.Util.number import * n = 714326667532888136341930300469812503108568533171958701229258381897431946521867367344505142446819 output = [683884150135567569054700309393082274015273418755015984639210872641629102776137288905334345358223, 285126221039239401347664578761309935673889193236512702131697050766454881029340147180552409870425, 276893085775448203669487661735680485319995668779836512706851431217470824660349740546793492847822, 670041467944152108349892479463033808393249475608933110640580388877206700116661070302382578388629, 122640993538161410588195475312610802051543155060328971488277224112081166784263153107636108815824, 695403107966797625391061914491496301998976621394944936827202540832952594905520247784142392337171, 108297989103402878258100342544600235524390749601427490182149765480916965811652000881230504838949, 3348901603647903020607356217291999644800579775392251732059562193080862524671584235203807354488, 632094372828241320671255647451901056399237760301503199444470380543753167478243100611604222284853, 54758061879225024125896909645034267106973514243188358677311238070832154883782028437203621709276] #公式二求a t = gmpy2.invert((output[2] - output[1]), n) a = t * (output[3] - output[2]) % n #公式三求b b = (output[2] - a * output[1]) % n #公式一求初始值 aa = gmpy2.invert(a, n) seed = aa * (output[0] - b) % n#注意这里的应为第一个但是实际上output收录的第一个就是第二个故应写为output[0] print(seed) print(long_to_bytes(seed)) #b'Spirit{Gr3at__J0b!_You_can_be___better!}'
05(未知a,b,n求seed)
from Crypto.Util.number import * flag = b'Spirit{****************************************}' plaintext = bytes_to_long(flag) length = plaintext.bit_length() a = getPrime(length) b = getPrime(length) n = getPrime(length) seed = plaintext output = [] for i in range(10): seed = (a*seed+b)%n output.append(seed) print("output = ",output) # output = [9997297986272510947766344959498975323136012075787120721424325775003840341552673589487134830298427997676238039214108, 4943092972488023184271739094993470430272327679424224016751930100362045115374960494124801675393555642497051610643836, 6774612894247319645272578624765063875876643849415903973872536662648051668240882405640569448229188596797636795502471, 9334780454901460926052785252362305555845335155501888087843525321238695716687151256717815518958670595053951084051571, 2615136943375677027346821049033296095071476608523371102901038444464314877549948107134114941301290458464611872942706, 11755491858586722647182265446253701221615594136571038555321378377363341368427070357031882725576677912630050307145062, 7752070270905673490804344757589080653234375679657568428025599872155387643476306575613147681330227562712490805492345, 8402957532602451691327737154745340793606649602871190615837661809359377788072256203797817090151599031273142680590748, 2802440081918604590502596146113670094262600952020687184659605307695151120589816943051322503094363578916773414004662, 5627226318035765837286789021891141596394835871645925685252241680021740265826179768429792645576780380635014113687982]
exp:
只有seed的值了,明显只能使用公式4
这个题我只选取了其中的某个数直接求,发现中间的模逆运算无法将进行,
以下是我搜到的脚本:
from Crypto.Util.number import * import gmpy2 output = [9997297986272510947766344959498975323136012075787120721424325775003840341552673589487134830298427997676238039214108, 4943092972488023184271739094993470430272327679424224016751930100362045115374960494124801675393555642497051610643836, 6774612894247319645272578624765063875876643849415903973872536662648051668240882405640569448229188596797636795502471, 9334780454901460926052785252362305555845335155501888087843525321238695716687151256717815518958670595053951084051571, 2615136943375677027346821049033296095071476608523371102901038444464314877549948107134114941301290458464611872942706, 11755491858586722647182265446253701221615594136571038555321378377363341368427070357031882725576677912630050307145062, 7752070270905673490804344757589080653234375679657568428025599872155387643476306575613147681330227562712490805492345, 8402957532602451691327737154745340793606649602871190615837661809359377788072256203797817090151599031273142680590748, 2802440081918604590502596146113670094262600952020687184659605307695151120589816943051322503094363578916773414004662, 5627226318035765837286789021891141596394835871645925685252241680021740265826179768429792645576780380635014113687982] t = [] for i in range(1,len(output)): t.append(output[i]-output[i-1])#tn T = [] for i in range(1,len(t)-1): T.append(t[i+1]*t[i-1] - t[i]**2)#Tn m = [] for i in range(len(T)-1): mm = gmpy2.gcd(T[i],T[i+1])#这里是公式四进行的 if isPrime(mm): m.append(int(mm)) else: for i in range(1,100):#该处相当于除以最大公约数 if isPrime(mm // i): mm = mm // i m.append(int(mm)) break print(m) for i in m: if isPrime(i): a = gmpy2.invert(t[0],i) * t[1] % i b = output[1] - a*output[0] % i a_ = gmpy2.invert(a,i) seed = a_ * (output[0]-b) % i flag = long_to_bytes(seed) if b'Spirit' in flag: print(flag)
官方wp:
from Crypto.Util.number import * def gcd(a,b): if(b==0): return a else: return gcd(b,a%b) s = [9997297986272510947766344959498975323136012075787120721424325775003840341552673589487134830298427997676238039214108, 4943092972488023184271739094993470430272327679424224016751930100362045115374960494124801675393555642497051610643836, 6774612894247319645272578624765063875876643849415903973872536662648051668240882405640569448229188596797636795502471, 9334780454901460926052785252362305555845335155501888087843525321238695716687151256717815518958670595053951084051571, 2615136943375677027346821049033296095071476608523371102901038444464314877549948107134114941301290458464611872942706, 11755491858586722647182265446253701221615594136571038555321378377363341368427070357031882725576677912630050307145062, 7752070270905673490804344757589080653234375679657568428025599872155387643476306575613147681330227562712490805492345, 8402957532602451691327737154745340793606649602871190615837661809359377788072256203797817090151599031273142680590748, 2802440081918604590502596146113670094262600952020687184659605307695151120589816943051322503094363578916773414004662, 5627226318035765837286789021891141596394835871645925685252241680021740265826179768429792645576780380635014113687982] t = [] for i in range(9): t.append(s[i]-s[i-1]) all_n = [] for i in range(7): all_n.append(gcd((t[i+1]*t[i-1]-t[i]*t[i]), (t[i+2]*t[i]-t[i+1]*t[i+1]))) MMI = lambda A, n,s=1,t=0,N=0: (n < 2 and t%N or MMI(n, A%n, t, s-A//n*t, N or n),-1)[n<1] #逆元计算 for n in all_n: n=abs(n) if n==1: continue a=(s[2]-s[1])*MMI((s[1]-s[0]),n)%n ani=MMI(a,n) b=(s[1]-a*s[0])%n seed = (ani*(s[0]-b))%n plaintext=seed print(long_to_bytes(plaintext))