UUCTF CRYPTO 官方WriteUP

前言

第一次受邀给比赛出密码学的题目,本人也不是很会密码学,出的题质量都不是很好,给各位师傅道个歉qwq

爱丽丝梦境的兔子

下载附件看到了一段编码后的文本, 结合题目描述直接梭

兔子是指Rabbit编码,有在线网站可以解

然后就是社会主义核心价值观编码,同样用在线网站解

随后的跳过6排栅栏就是指栏数为6的栅栏密码了,直接在线网站解一下得到flag

flag{W3lc0me_to_tys3C!}

disparity_rsa

from Crypto.Util.number import *
import libnum
from flag import flag

n = getPrime(16) * getPrime(1024)
e = 65537
c = pow(libnum.s2n(flag), e, n)
print(n)
print(c)
"""
5766276392358749678465293140086098467966750231712371312128357014391999737216038752230724284342592823121355823795866483203180931048954335112770774107559486755364212210458976151334722695492171477074797849017986146274077476865962084775522903856595231226401087381140264069846311320790344977681853590320235273290951697
2045715881946911272235143200802867525029545408884378407157206152052553006168468197781701884100551265225998396305370344041310549543210998337911706435156837312343915033047602409702498958543942876869008345155456133353563984395357862622021564371486943574405858053628504628093173853945529577974028398631861979247502108s
"""

观察一下题目代码,发现n的生成过程并不安全

n = getPrime(16) * getPrime(1024)

由于n的一个素因子过小,会造成直接模数分解,使用yafu秒出n的两个素因子

然后就是常规RSA解密了,放一波脚本

from Crypto.Util.number import long_to_bytes
import gmpy2
p = 57191
q = 100824891894856702601201118009583648965164977561371042858637845367138181483380929730739526924561431398670347148954669147299066829552802628259180187574259704417901631558444093499584247442642574479809722666468258052387219612630695122930581802321960294913554359621973108878080665153439264529066699136581547328967
e = 65537
n = p * q
phi = (p - 1) * (q - 1)
d = gmpy2.invert(e,phi)
c = 2045715881946911272235143200802867525029545408884378407157206152052553006168468197781701884100551265225998396305370344041310549543210998337911706435156837312343915033047602409702498958543942876869008345155456133353563984395357862622021564371486943574405858053628504628093173853945529577974028398631861979247502108
print(long_to_bytes(pow(c,d,n)))
#b'flag{great!_Y0u_s0lve_m9_challenge!}'

Easy_base64

from flag import flag
import base64
assert flag[0:4] == "flag"
tmp=base64.b64encode(bytes(flag,"utf-8"))
flag=str(tmp)[2:-1]
for i in range(0,len(flag)-1):
    print(ord(flag[i]) ^ ord(flag[i+1]),end=" ")
#55 21 16 50 105 71 14 27 41 30 34 16 50 111 74 62 5 18 54 52 106 85 31 54 24 111 83 11 38 1 53 17 37 17 35 47 32 52 40 2 9 59 47 54 25 111 77 16 48 26 33 9 55 108 0

观察题目源码,发现是先将flag进行了base64加密,然后将第i个字符转换为ascii后异或第i+1个字符的ascii
这里我们可以使用异或的性质来还原flag

A ^ B ^ B = A

知道思路以后就是纯脚本编写题了,flag经base64编码后第一个字母为"Z",用python写个for循环异或回去即可

import base64

list = [55 ,21 ,16, 50 ,105 ,71, 14, 27 ,41 ,30, 34 ,16, 50, 111 ,74 ,62, 5 ,18 ,54, 52, 106,85 ,31, 54 ,24, 111, 83, 11, 38, 1, 53, 17, 37, 17, 35, 47, 32, 52, 40, 2, 9, 59, 47, 54, 25, 111, 77, 16, 48, 26, 33, 9, 55, 108, 0]
flag = "Z"
for i in range(len(list)):
    flag += chr(ord(flag[i])^list[i])
print(base64.b64decode(flag))
#b'flag{shumu_l0ve_h15_challeng3_ver9_mu3h}'

unsafe_prime

这道题一开始甚至上错了附件,但是题目并不难,所以最后解出还是很高的(

from Crypto.Util.number import *
from flag import flag
import libnum
p=getPrime(1024)
n=p**3
e=65537
c=pow(libnum.s2n(flag),e,n)
print(n)
print(c)
#1781066779141074297846071955037887396311182371062305797790413639302252321886055189043670187843106208315282055227397316083218930657040969292641990094428330517286511511741846106485971830443788363541411679523274683568732340113625424593194464460018629545968907529693143364870519531630721083893407011154181539445417439610805148961135948617691115328261432541033785402520757881586489819563221498111411690769065511011083021336493731421274742041131952523427183184133413677315203810963447656037908287875212013900845740870561508870574734100843624059414134156975073835607712519402938132401964708681236647568922173471703538744207491065165405594141287750705055447493380970194312139898574699147098202027540057477562090764694370368571887563631557761911842054442637038169316686266784299889397326811768646649462480349219937292894824766045607723468654723947999531346474969019631500665628522355198334827965770037487344994396753505248472283247731
#1402371150275079475353867962992356093684205278224746766691813462864343871795075217989508355749642716635931824907174189358797217546624305634264458802157933311315419673854405865092102322247505412453586251582022669511221048298234732642016439123525455296325766292112758881774720932499142635136210314142144509741404827421282969081272484330382868174392651681290127032351489627054643864671335712011990584326951285867375878235135547391155357814807654366986019707719726796289990920154227959213228064918435259919697047405788311280560319520593639968900649500117511665741073545430999580686455996145426173603547052710181735901020361145546892741579951501409108067297139928103329203429485237575169217432586580425019729120741661192297552519858305628835738911159460615968385837687234565509200392302553443089729906970894661310333276852803980265040679214814192141779678148895736682538612828771031493541256243879854624644771924477873876038496224

观察代码,发现n= p 3 p^3 p3,那么我们就可以求出 n 3 \sqrt[3]{n} 3n 来得到p,然后进行常规的RSA解密,下面放出脚本

import gmpy2
from Crypto.Util.number import *
n = 1781066779141074297846071955037887396311182371062305797790413639302252321886055189043670187843106208315282055227397316083218930657040969292641990094428330517286511511741846106485971830443788363541411679523274683568732340113625424593194464460018629545968907529693143364870519531630721083893407011154181539445417439610805148961135948617691115328261432541033785402520757881586489819563221498111411690769065511011083021336493731421274742041131952523427183184133413677315203810963447656037908287875212013900845740870561508870574734100843624059414134156975073835607712519402938132401964708681236647568922173471703538744207491065165405594141287750705055447493380970194312139898574699147098202027540057477562090764694370368571887563631557761911842054442637038169316686266784299889397326811768646649462480349219937292894824766045607723468654723947999531346474969019631500665628522355198334827965770037487344994396753505248472283247731
c = 1402371150275079475353867962992356093684205278224746766691813462864343871795075217989508355749642716635931824907174189358797217546624305634264458802157933311315419673854405865092102322247505412453586251582022669511221048298234732642016439123525455296325766292112758881774720932499142635136210314142144509741404827421282969081272484330382868174392651681290127032351489627054643864671335712011990584326951285867375878235135547391155357814807654366986019707719726796289990920154227959213228064918435259919697047405788311280560319520593639968900649500117511665741073545430999580686455996145426173603547052710181735901020361145546892741579951501409108067297139928103329203429485237575169217432586580425019729120741661192297552519858305628835738911159460615968385837687234565509200392302553443089729906970894661310333276852803980265040679214814192141779678148895736682538612828771031493541256243879854624644771924477873876038496224
e = 65537
p = gmpy2.iroot(n,3)[0]
phi = p-1
d = gmpy2.invert(e,phi)
m = pow(c,d,p)
print(long_to_bytes(m))
#b'flag{Shumu_th1nk_saf3_pr1me_ar3_importanT!}'

Impossible_RSA

这道题相对来说难度大很多,但是也并非题目名称中的impossible

import libnum
from Crypto.Util.number import getPrime
from flag import flag, e

p = getPrime(1024)
q = getPrime(1024)
n = p * q
assert e <= 500000
c = pow(libnum.s2n(flag), e, n)
leak1 = c % q
leak2 = c % p
leak3 = p + q
print("n =", n)
print("leak1 =", leak1)
print("leak2 =", leak2)
print("leak3 =", leak3)

"""
n = 21256406304024147327122699985764737895162788854942201173538004689536569610046157311527715126074775927977409773971656249943602454790380966869525211733301201659688694473703188427037879868522859419364680904585572399937639393418586498509580133474303442722716959873727260844993296681950092753897902540593927952622713860163782763263944291810729056735965535138964485886748344167499818148134252327820007439830749462775149754781930983094046362696040641091039506998835624218220892441813224657845627120344960554424765109502415773475619490661527184126374299883610442465428985757004551740482644952396990065188807827114495184096249
leak1 = 8842431959638543756327530752221031675897458993985909403335303147413741167900365489182674478419510549838159493192002672500346433589707076289344572454304647803237654059883974235710442126617587691632375039292283285577033977676131772115877520248352227419433136507412485140428972344000541898060766721412300525883
leak2 = 127414092867622693231378230621806169422569654246682818498761930473755998913688181327473434110121174292309611256339271412324673262030535400937563769685033472683498585742711576446343086462569783541192470920638935990937187809422965809986860709074542257475025562691683977493260026623616012846939417988284096473040
leak3 = 293130152177150437492580785085598394773458388719469800871702200331766258900690595210759869625006484354799804558552583572062231998451041105464048317708732987121458633718573774164071597186461239762511364549980544029915308083867329707804739776241438307060614946195675715671343671137725809499387682363101164970886
"""

我们观察题目,发现n=p*q且leak3=p+q,那么我们就可以列一个二元一次方程组从而求出p和q了
这里我们使用sage求p和q,那样非常easy

#sage
n = 21256406304024147327122699985764737895162788854942201173538004689536569610046157311527715126074775927977409773971656249943602454790380966869525211733301201659688694473703188427037879868522859419364680904585572399937639393418586498509580133474303442722716959873727260844993296681950092753897902540593927952622713860163782763263944291810729056735965535138964485886748344167499818148134252327820007439830749462775149754781930983094046362696040641091039506998835624218220892441813224657845627120344960554424765109502415773475619490661527184126374299883610442465428985757004551740482644952396990065188807827114495184096249
leak3 = 293130152177150437492580785085598394773458388719469800871702200331766258900690595210759869625006484354799804558552583572062231998451041105464048317708732987121458633718573774164071597186461239762511364549980544029915308083867329707804739776241438307060614946195675715671343671137725809499387682363101164970886
var('p q')
eq = [p*q-n,p+q-leak3]
result = solve(eq,p,q)[0]
print(result)

成功求出p和q

接着我们发现题目并没有给c,继续观察代码,发现如下代码

leak1 = c % q
leak2 = c % p

妥妥的中国剩余定理,sage同样可以很简单的求出c,python的话手撸一个CRT也不难,这里就用sage演示

#sage
p = 161562249983202700035527081166558786031731223261198195999535987465827171883730733359944156020947215855022510635343983292897557354440470230745496731228302894376018866016596714241754815953745113727125200716224341010140868299262202025976056483744622119807303134689795661748036502596285135565503272596613700276343
q = 131567902193947737457053703919039608741727165458271604872166212865939087016959861850815713604059268499777293923208600279164674644010570874718551586480430092745439767701977059922316781232716126035386163833756203019774439784605127681828683292496816187253311811505880053923307168541440673933884409766487464694543
leak1 = 8842431959638543756327530752221031675897458993985909403335303147413741167900365489182674478419510549838159493192002672500346433589707076289344572454304647803237654059883974235710442126617587691632375039292283285577033977676131772115877520248352227419433136507412485140428972344000541898060766721412300525883
leak2 = 127414092867622693231378230621806169422569654246682818498761930473755998913688181327473434110121174292309611256339271412324673262030535400937563769685033472683498585742711576446343086462569783541192470920638935990937187809422965809986860709074542257475025562691683977493260026623616012846939417988284096473040
c_list = [leak2,leak1]
p_q_list = [p,q]
c = CRT_list(c_list,p_q_list)
print(c)


接着发现e也没给,但是给了e的取值范围为: e ≤ 500000 e\leq500000 e500000,所以我们可以尝试爆破一下
下面给出完整代码

#sage
import gmpy2
import libnum
n = 21256406304024147327122699985764737895162788854942201173538004689536569610046157311527715126074775927977409773971656249943602454790380966869525211733301201659688694473703188427037879868522859419364680904585572399937639393418586498509580133474303442722716959873727260844993296681950092753897902540593927952622713860163782763263944291810729056735965535138964485886748344167499818148134252327820007439830749462775149754781930983094046362696040641091039506998835624218220892441813224657845627120344960554424765109502415773475619490661527184126374299883610442465428985757004551740482644952396990065188807827114495184096249
leak1 = 8842431959638543756327530752221031675897458993985909403335303147413741167900365489182674478419510549838159493192002672500346433589707076289344572454304647803237654059883974235710442126617587691632375039292283285577033977676131772115877520248352227419433136507412485140428972344000541898060766721412300525883
leak2 = 127414092867622693231378230621806169422569654246682818498761930473755998913688181327473434110121174292309611256339271412324673262030535400937563769685033472683498585742711576446343086462569783541192470920638935990937187809422965809986860709074542257475025562691683977493260026623616012846939417988284096473040
leak3 = 293130152177150437492580785085598394773458388719469800871702200331766258900690595210759869625006484354799804558552583572062231998451041105464048317708732987121458633718573774164071597186461239762511364549980544029915308083867329707804739776241438307060614946195675715671343671137725809499387682363101164970886
p = 161562249983202700035527081166558786031731223261198195999535987465827171883730733359944156020947215855022510635343983292897557354440470230745496731228302894376018866016596714241754815953745113727125200716224341010140868299262202025976056483744622119807303134689795661748036502596285135565503272596613700276343
q = 131567902193947737457053703919039608741727165458271604872166212865939087016959861850815713604059268499777293923208600279164674644010570874718551586480430092745439767701977059922316781232716126035386163833756203019774439784605127681828683292496816187253311811505880053923307168541440673933884409766487464694543
phi = n - leak3 + 1
c_list = [leak2,leak1]
p_q_list = [p,q]
c = CRT_list(c_list,p_q_list)
print(c)
for e in range(1,5000001):
    try:
        d = gmpy2.invert(e,phi)
        m = pow(c,d,n)
        flag = libnum.n2s(int(m))
        if b'flag' in flag:
            print(flag)
            break
        else:
            continue
    except:
        continue
#b'flag{c59d5fc3-610c-41ca-baef-b26f9a88648d}'

简单的数学

from Crypto.Util.number import *
import libnum
from flag import flag
e = 65537
p = getPrime(1024)
q = getPrime(1024)
n = p*q
k = getRandomNBitInteger(20)
c=pow(libnum.s2n(flag)*p+k*n,e,n)
print(n)
print(k)
print(c)
'''
25014963863951112347974440214066273048882503259160338255496299775995961351901571648895465031685356024238885233929337483853960374743565692563404769039019561050421788096283392820458449077490390195564801845037357811298274797645813808259301937466827199149702646030007667049110326436048932024335483846993690455310182909643176845321021209137548742937430940258997221937352498631551209822079559591857076641561863821325180714184637516327495056825200929458796589533188382551310078527193764723189551017851538326522660734366263229681834096022505151628784267513086843047784002223603418978827233728149657480292961095596638702578233
930971
21332979626247382647148222928588089621511790656630926013612529289276199934646065751526142377438330548167579869346422391777913473113228287023801928140946948279096562923728186040013041739656216576467903409087827269164764659636977412246373447194249307513950780025367450729199178539765363446611686879821064068711525543800807969264271445173422813211738947698740537888866771159352960700295474589207758542367193701819811125602611901272496121027126921035697692984486226677539547135753720071134145590716156803665486826826046693205511230289946748601632769198172373201803516681379607412290191420859001274915183415061321376410345
'''

这是一道看似很难实则很简单的问题,我们展开密文c即可得到: c = ( m ⋅ p + k ⋅ n ) e c=(m \cdot p+k \cdot n)^e c=(mp+kn)e m o d mod mod n n n
我们使用多项式定理展开,得到:
第一项为 ( m ⋅ p ) e (m \cdot p)^e (mp)e,最后一项为 ( k ⋅ n ) e (k \cdot n)^e (kn)e
而它们每一项在 m o d mod mod n n n之后结果均为0
等价于c = ( m ⋅ p ) e (m \cdot p)^e (mp)e m o d mod mod ( p ⋅ q ) (p \cdot q) (pq)
根据模运算规律可得: c p = m e ⋅ p ( e − 1 ) \frac{c}{p} = m^e \cdot p^(e - 1) pc=mep(e1) m o d mod mod q q q
所以c和n的最大公约数就是p,求出p后解密RSA即可

from Crypto.Util.number import *
import gmpy2
n = 25014963863951112347974440214066273048882503259160338255496299775995961351901571648895465031685356024238885233929337483853960374743565692563404769039019561050421788096283392820458449077490390195564801845037357811298274797645813808259301937466827199149702646030007667049110326436048932024335483846993690455310182909643176845321021209137548742937430940258997221937352498631551209822079559591857076641561863821325180714184637516327495056825200929458796589533188382551310078527193764723189551017851538326522660734366263229681834096022505151628784267513086843047784002223603418978827233728149657480292961095596638702578233
k = 930971
e = 65537
c = 21332979626247382647148222928588089621511790656630926013612529289276199934646065751526142377438330548167579869346422391777913473113228287023801928140946948279096562923728186040013041739656216576467903409087827269164764659636977412246373447194249307513950780025367450729199178539765363446611686879821064068711525543800807969264271445173422813211738947698740537888866771159352960700295474589207758542367193701819811125602611901272496121027126921035697692984486226677539547135753720071134145590716156803665486826826046693205511230289946748601632769198172373201803516681379607412290191420859001274915183415061321376410345
p = gmpy2.gcd(n,c)
q = n // p
phi = (p - 1) * (q - 1)
d = gmpy2.invert(e,phi)
m = pow(c,d,n) // p
print(long_to_bytes(m))
#b'flag{The_s3cret_0f_shumu_1s_th1s!}'

每日emo

【我爱山间的清风与广场上的风筝,午夜的马路和清晨的粥铺,已经走远再也不会回头的你。】
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值