n = 0xa3bce3926fc27e291e730abe80e936c24d28e55a42995e296b3914b3f5b68dbdcdfa91582193fcf90b8b82905aead974b6465c5f9f8ff759c66c7dd78fcd7086011915110dce9927acb28d985f97d24027139372ccd3fd1b012787b8cd28908350fa0dbba59e2661f6740e6d133777dc37690b60b87eb9c748e869b4382c8f719869bac442be8ec8cb9700222a13f40921a691d32c420077cfabccd2844b78f8dc5f48b8e210c1523a0efa12b2ab1b15406a022f5cc4d2a261d810748104b1f8bda2c2b5d82ef78c6c7a81a3b89e14b935eceff152371db9215641974731238cc778a023e462c0e205f71caa0d1c82d1f8ebaca91b13cab25e698407978d0157 e = 0x3 c = 0x10652cdfaa8b1ec60efcf3bf9cc73f918e0476a9265f6ed80d816b1826abcd23a13d45419a652ba6b33e9cd6766b31ed4aefb576f1048ef00bcbc6ebf05f89c6cbbf315d1dc6b0ef2b5a5bfde6ea0978f01b4865 res = 0
for i inrange(200000000): if gmpy2.iroot(c + n * i, 3)[1] == 1: try: res = int(gmpy2.iroot(c + n * i, 3)[0]) print(libnum.n2s(res).decode()) except: continue
实际上这题中的 k = 0 因此直接将 c 开三次根后甚至能直接出答案,某种程度上还是留了一点后门?大整数运算需要有 Python 专门的库,自带的开根号精度不够,算出来一半的注意一下这个问题。
1
flag{tH1s_I5_wH4t_y0u_ne3D!}
Wiener RSA
背景
1989年,Michael J.Wiener发表了Cryptanalysis of Short RSA Secret Exponents文章,提出了一种针对解密指数 d 较低时对于RSA的攻击方法,该方法基于连分数(Continued Fraction)
defwiener_hack(e, n): frac = ContinuedFractions.rational_to_contfrac(e, n) convergents = ContinuedFractions.convergents_from_contfrac(frac) for (k, d) in convergents: if k != 0and (e * d - 1) % k == 0: phi = (e * d - 1) // k s = n - phi + 1 discr = s * s - 4 * n if (discr >= 0): t = Arithmetic.is_perfect_square(discr) if t != -1and (s + t) % 2 == 0: return d returnFalse
from Crypto.PublicKey import RSA import ContinuedFractions, Arithmetic from Crypto.Util.number import long_to_bytes
defwiener_hack(e, n): frac = ContinuedFractions.rational_to_contfrac(e, n) convergents = ContinuedFractions.convergents_from_contfrac(frac) for (k, d) in convergents: if k != 0and (e * d - 1) % k == 0: phi = (e * d - 1) // k s = n - phi + 1 discr = s * s - 4 * n if (discr >= 0): t = Arithmetic.is_perfect_square(discr) if t != -1and (s + t) % 2 == 0: return d returnFalse
defmain(): n = 122799981867653458656229479905780591709320336906548267308725133504023620666473594694619400061072384153052380482145474476277325274539534268692096140372698856686913649268243189214226426197241972179248244727576974065032906277783259533091580447468486634337837769772374096283015491595913791337168075781487175577011 e = 1634708036918022876029212484705339394117588871584112517454367841949655368912434655817734472520220293452874702665398224936229255345466873974072201646615281356263861423534178234100275738689728153879282329006386554426368727168149082061185380447183592559043261489606693247823120095812869743632614890148511762833 c = 8828249396920089665604321590729449082283412247637210954851574255858554979363879535153347766207783540409667667635411461588213929794181755191561235289121055575970985299405308351883604156440682299260079619595877340179217897011307148868696271453299235902611126697623645746302557312636041900678521266759516645215 d = wiener_hack(e, n) m = pow(c,d,n) print (long_to_bytes(m))
if __name__=="__main__": main()
将上述代码放入rsa-wiener-attack 文件夹下运行即可得到 flag,最好准备 Linux 环境。
1
flag{W1eNer_atTAcK_Is_vErY_eASy!}
Fermat RSA
一些数学推导,推导完了实际就是解个一元二次方程求 p 和 q,代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
import gmpy2 from Crypto.Util.number import * from sympy import *
e = 65537 c = 23895834623261377800351031954483648973943748863301467305810451110352777886300454729029165813465351332857815718013916942502578356053087425580006364436079752652396602575187901157819298680796270368515668161455494688724537106030940049090557292366949959348885616425446560414414860161844976376461908126987441253405 n = 64871829903104213643680764097850414283536373814646568873418061349075599660706209112510457467832178810869133929276049796748237853589936969078985797862477657422954022334398157187517648415739493949218289040505843638468023658049134338372905051146096638506369570551073678125496909258166096784242028555600270176773 leak = 16108617090416270985577150372010761876856874015361846998037080476963691088702658913666115496812645234594684431959245528754650234787455851230467008931520826 p, q = symbols("p q") eq = [p*q-n,p+q-leak] result = list(nonlinsolve(eq, [p, q])) p,q =int(result[1][0]),int(result[1][1]) phi =(p-1)*(q-1) d = gmpy2.invert(e,phi) m = pow(c,d,n) flag = long_to_bytes(m) print(flag)