CTFshow-Crypto(26-29)

machacha發表於2024-06-05

26easyrsa6

分解n/費馬分解

import gmpy2,libnum
from Crypto.Util.number import getPrime

e = 0x10001
p = getPrime(1024)
q = gmpy2.next_prime(p)
n = p * q
print("n =",n)
m = libnum.s2n(flag)
c = pow(m,e,n)
print("c =", c)

# n = 26737417831000820542131903300607349805884383394154602685589253691058592906354935906805134188533804962897170211026684453428204518730064406526279112572388086653330354347467824800159214965211971007509161988095657918569122896402683130342348264873834798355125176339737540844380018932257326719850776549178097196650971801959829891897782953799819540258181186971887122329746532348310216818846497644520553218363336194855498009339838369114649453618101321999347367800581959933596734457081762378746706371599215668686459906553007018812297658015353803626409606707460210905216362646940355737679889912399014237502529373804288304270563
# c = 18343406988553647441155363755415469675162952205929092244387144604220598930987120971635625205531679665588524624774972379282080365368504475385813836796957675346369136362299791881988434459126442243685599469468046961707420163849755187402196540739689823324440860766040276525600017446640429559755587590377841083082073283783044180553080312093936655426279610008234238497453986740658015049273023492032325305925499263982266317509342604959809805578180715819784421086649380350482836529047761222588878122181300629226379468397199620669975860711741390226214613560571952382040172091951384219283820044879575505273602318856695503917257

看到e=0x10001

16進位制轉為10進位制是65537

image-20240604153749146

分解nhttp://www.factordb.com/

image-20240604154302228

我們注意到

p = getPrime(1024)
q = gmpy2.next_prime(p)

p q相差太小 所以 n=p*q ≈p²,費馬分解

p = gmpy2.next_prime(gmpy2.iroot(n,2)[0])
q = n//p
指令碼
import gmpy2,libnum
from Crypto.Util.number import *

\# e = 0x10001
\# p = getPrime(1024)
\# q = gmpy2.next_prime(p)
\# n = p * q
\# print("n =",n)
\# m = libnum.s2n(flag)
\# c = pow(m,e,n)
\# print("c =", c)

n = 26737417831000820542131903300607349805884383394154602685589253691058592906354935906805134188533804962897170211026684453428204518730064406526279112572388086653330354347467824800159214965211971007509161988095657918569122896402683130342348264873834798355125176339737540844380018932257326719850776549178097196650971801959829891897782953799819540258181186971887122329746532348310216818846497644520553218363336194855498009339838369114649453618101321999347367800581959933596734457081762378746706371599215668686459906553007018812297658015353803626409606707460210905216362646940355737679889912399014237502529373804288304270563
c = 18343406988553647441155363755415469675162952205929092244387144604220598930987120971635625205531679665588524624774972379282080365368504475385813836796957675346369136362299791881988434459126442243685599469468046961707420163849755187402196540739689823324440860766040276525600017446640429559755587590377841083082073283783044180553080312093936655426279610008234238497453986740658015049273023492032325305925499263982266317509342604959809805578180715819784421086649380350482836529047761222588878122181300629226379468397199620669975860711741390226214613560571952382040172091951384219283820044879575505273602318856695503917257
p = 163515803000813412334620775647541652549604895368507102613553057136855632963322853570924931001138446030409251690646645635800254129997200577719209532684847732809399187385176309169421205833279943214621695444496660249881675974141488357432373412184140130503562295159152949524373214358417567189638680209172147385163
q = 163515803000813412334620775647541652549604895368507102613553057136855632963322853570924931001138446030409251690646645635800254129997200577719209532684847732809399187385176309169421205833279943214621695444496660249881675974141488357432373412184140130503562295159152949524373214358417567189638680209172147385801
e = 65537
phi = (p-1)*(q-1)
d = gmpy2.invert(e,phi)
m = pow(c,d,n)
print(long_to_bytes(m))
工具(風二西)

image-20240604155218484

27easyrsa7

CopperSmith攻擊 低位資料缺失-知p高位

RSA中coppersmith定理的應用條件_sagemath coppersmith-CSDN部落格

e = 0x10001
p>>128<<128 = 0xd1c520d9798f811e87f4ff406941958bab8fc24b19a32c3ad89b0b73258ed3541e9ca696fd98ce15255264c39ae8c6e8db5ee89993fa44459410d30a0a8af700ae3aee8a9a1d6094f8c757d3b79a8d1147e85be34fb260a970a52826c0a92b46cefb5dfaf2b5a31edf867f8d34d2222900000000000000000000000000000000
n = 0x79e0bf9b916e59286163a1006f8cefd4c1b080387a6ddb98a3f3984569a4ebb48b22ac36dff7c98e4ebb90ffdd9c07f53a20946f57634fb01f4489fcfc8e402865e152820f3e2989d4f0b5ef1fb366f212e238881ea1da017f754d7840fc38236edba144674464b661d36cdaf52d1e5e7c3c21770c5461a7c1bc2db712a61d992ebc407738fc095cd8b6b64e7e532187b11bf78a8d3ddf52da6f6a67c7e88bef5563cac1e5ce115f3282d5ff9db02278859f63049d1b934d918f46353fea1651d96b2ddd874ec8f1e4b9d487d8849896d1c21fb64029f0d6f47e560555b009b96bfd558228929a6cdf3fb6d47a956829fb1e638fcc1bdfad4ec2c3590dea1ed3
c = 0x1b2b4f9afed5fb5f9876757e959c183c2381ca73514b1918d2f123e386bebe9832835350f17ac439ac570c9b2738f924ef49afea02922981fad702012d69ea3a3c7d1fc8efc80e541ca2622d7741090b9ccd590906ac273ffcc66a7b8c0d48b7d62d6cd6dd4cd75747c55aac28f8be3249eb255d8750482ebf492692121ab4b27b275a0f69b15baef20bf812f3cbf581786128b51694331be76f80d6fb1314d8b280eaa16c767821b9c2ba05dfde5451feef22ac3cb3dfbc88bc1501765506f0c05045184292a75c475486b680f726f44ef8ddfe3c48f75bb03c8d44198ac70e6b7c885f53000654db22c8cee8eb4f65eaeea2da13887aaf53d8c254d2945691

新題型

>> 和 <<都是位運算,對二進位制數進行移位操作

>> 1 右移一位 相當於 /2

這裡 “p>>128<<128" p右移128位再左移128位 之後 p末尾很多0,p低位資料缺失

p,q二進位制位數相同時 β一般只能取 0.4

利用 sagemath 去恢復p

下載使用

【SageMath】SageMath在Windows系統下的安裝_sagemath下載-CSDN部落格

SageMath的新手保姆使用教程-CSDN部落格

安裝第三方庫

在sagemath中安裝第三方庫_pip install sage-CSDN部落格

#sage#
p = 0xd1c520d9798f811e87f4ff406941958bab8fc24b19a32c3ad89b0b73258ed3541e9ca696fd98ce15255264c39ae8c6e8db5ee89993fa44459410d30a0a8af700ae3aee8a9a1d6094f8c757d3b79a8d1147e85be34fb260a970a52826c0a92b46cefb5dfaf2b5a31edf867f8d34d2222900000000000000000000000000000000
n = 0x79e0bf9b916e59286163a1006f8cefd4c1b080387a6ddb98a3f3984569a4ebb48b22ac36dff7c98e4ebb90ffdd9c07f53a20946f57634fb01f4489fcfc8e402865e152820f3e2989d4f0b5ef1fb366f212e238881ea1da017f754d7840fc38236edba144674464b661d36cdaf52d1e5e7c3c21770c5461a7c1bc2db712a61d992ebc407738fc095cd8b6b64e7e532187b11bf78a8d3ddf52da6f6a67c7e88bef5563cac1e5ce115f3282d5ff9db02278859f63049d1b934d918f46353fea1651d96b2ddd874ec8f1e4b9d487d8849896d1c21fb64029f0d6f47e560555b009b96bfd558228929a6cdf3fb6d47a956829fb1e638fcc1bdfad4ec2c3590dea1ed3

pbits = 1024
kbits = 128
#pbits 和 kbits: 分別表示 p 和一箇中間步驟中的某些數值的位數。
PR.<x> = PolynomialRing(Zmod(n))
#Zmod(n):指定模,定義界限為n的環;Z表示整數;指定模是劃定這個環的界限,就是有效的數字只有從0到n,其他的都透過與n取模來保證在0~n這個範圍內;Zmod代表這是一個整數域中的n模環
#ZZ:整數環;QQ:有理數環;RR:實數環;CC:複數環
#R:只是一個指標,指向用polynomialring指定的那個環(可以使用任意字元)
#PolynomialRing:這個就是說建立多項式環
#.<X>:指定一個變數的意思(可以用任意字元)
f = x + p
#定義了一個多項式 f(x) = x + p。
roots = f.small_roots(X=2^kbits, beta=0.4)
#small_roots 方法試圖找到多項式的根,這些根在 [0, X) 範圍內,並且滿足一定的“小”條件(由 beta 引數控制)。具體來說,X 是我們想要查詢的根的最大值(這裡是 2^kbits),而 beta 是一個浮點數,用於控制演算法的複雜性。通常,beta 的值越大,演算法會更快,但可能找到的根越少。
if roots:
	p = p+int(roots[0])
	print("p = "+str(p))
#如果 small_roots 方法找到了根(即 roots 非空),那麼程式碼將 p 更新為 p 加上找到的第一個根,並列印出新的 p 值。

image-20240604212225496

from Crypto.Util.number import *
from gmpy2 import *

e = 0x10001
n = 0x79e0bf9b916e59286163a1006f8cefd4c1b080387a6ddb98a3f3984569a4ebb48b22ac36dff7c98e4ebb90ffdd9c07f53a20946f57634fb01f4489fcfc8e402865e152820f3e2989d4f0b5ef1fb366f212e238881ea1da017f754d7840fc38236edba144674464b661d36cdaf52d1e5e7c3c21770c5461a7c1bc2db712a61d992ebc407738fc095cd8b6b64e7e532187b11bf78a8d3ddf52da6f6a67c7e88bef5563cac1e5ce115f3282d5ff9db02278859f63049d1b934d918f46353fea1651d96b2ddd874ec8f1e4b9d487d8849896d1c21fb64029f0d6f47e560555b009b96bfd558228929a6cdf3fb6d47a956829fb1e638fcc1bdfad4ec2c3590dea1ed3
p = 147305526294483975294006704928271118039370615054437206404408410848858740256154476278591035455064149531353089038270283281541411458250950936656537283482331598521457077465891874559349872035197398406708610440618635013091489698011474611145014167945729411970665381793142591665313979405475889978830728651549052207969
q = n // p
c = 0x1b2b4f9afed5fb5f9876757e959c183c2381ca73514b1918d2f123e386bebe9832835350f17ac439ac570c9b2738f924ef49afea02922981fad702012d69ea3a3c7d1fc8efc80e541ca2622d7741090b9ccd590906ac273ffcc66a7b8c0d48b7d62d6cd6dd4cd75747c55aac28f8be3249eb255d8750482ebf492692121ab4b27b275a0f69b15baef20bf812f3cbf581786128b51694331be76f80d6fb1314d8b280eaa16c767821b9c2ba05dfde5451feef22ac3cb3dfbc88bc1501765506f0c05045184292a75c475486b680f726f44ef8ddfe3c48f75bb03c8d44198ac70e6b7c885f53000654db22c8cee8eb4f65eaeea2da13887aaf53d8c254d2945691

phi_n = (p - 1) * (q - 1)

d = invert(e, phi_n)
m = pow(c, d, n)
print(long_to_bytes(m))

28easyrsa8

公鑰解析

下載附件是兩個檔案

image-20240604163602251

將public.key檔案內容進行公鑰解析得到e和n

SSL線上工具-公鑰解析 (hiencode.com)

image-20240604164251074

分解n

n=10306247299477991196335954707897189353577589618180446614762218980226685668311143526740800444344046158260556585833057716406703213966249956775927205061731821632025483608182881492214855240841820024816859031176291364212054293818204399157346955465232586109199762630150640804366966946066155685218609638749171632685073
e=65537
p=97
q=106249972159566919549855203174197828387397831115262336234662051342543151219702510584956705611794290291345944183845955839244363030579896461607496959399297130227066841321473005074379950936513608503266587950271044991876848389878395867601515004796212227929894460104645781488319246866661398816686697306692491058609

密文c就是flag.enc

使用RSA演算法加密字串:從基礎到實現 - Python-CSDN部落格

指令碼

import gmpy2
from Crypto.Cipher import PKCS1_OAEP
\# PKCS1 OAEP 是一種基於 RSA 和 OAEP 填充的非對稱密碼
\#用於RSA的OAEP填充解密。
from Crypto.PublicKey import RSA
\#用於RSA公鑰和私鑰的生成和操作。

n=10306247299477991196335954707897189353577589618180446614762218980226685668311143526740800444344046158260556585833057716406703213966249956775927205061731821632025483608182881492214855240841820024816859031176291364212054293818204399157346955465232586109199762630150640804366966946066155685218609638749171632685073
e=65537
p=97
q=106249972159566919549855203174197828387397831115262336234662051342543151219702510584956705611794290291345944183845955839244363030579896461607496959399297130227066841321473005074379950936513608503266587950271044991876848389878395867601515004796212227929894460104645781488319246866661398816686697306692491058609

phi_n = (p - 1) * (q - 1)
d = int(gmpy2.invert(e, phi_n))

\#rsakey = RSA.importKey(open(r"C:\Users\86157\Desktop\easyrsa8\public.key", 'r').read())
\#從檔案中匯入公鑰,但是已經有了私鑰的所有引數,所以不需要從檔案中匯入公鑰。
privatekey = RSA.construct((n, e, d, p, q))
\#構造私鑰
rsa = PKCS1_OAEP.new(privatekey)
\#使用私鑰和PKCS1_OAEP填充來初始化解密器。
m = rsa.decrypt(open(r"C:\Users\86157\Desktop\easyrsa8\flag.enc", 'rb').read())
\#讀取加密的檔案,並使用之前初始化的解密器來解密。
print(m)

29funnyrsa1

兩個e c q不同,p相同(e與phi不互素)+CRT

e1 = 14606334023791426
p1 = 121009772735460235364940622989433807619211926015494087453674747614331295040063679722422298286549493698150690694965106103822315378461970129912436074962111424616439032849788953648286506433464358834178903821069564798378666159882090757625817745990230736982709059859613843100974349380542982235135982530318438330859
q1 = 130968576816900149996914427770826228884925960001279609559095138835900329492765336419489982304805369724685145941218640504262821549441728192761733409684831633194346504685627189375724517070780334885673563409259345291959439026700006694655545512308390416859315892447092639503318475587220630455745460309886030186593
c1 = 11402389955595766056824801105373550411371729054679429421548608725777586555536302409478824585455648944737304660137306241012321255955693234304201530700362069004620531537922710568821152217381257446478619320278993539785699090234418603086426252498046106436360959622415398647198014716351359752734123844386459925553497427680448633869522591650121047156082228109421246662020164222925272078687550896012363926358633323439494967417041681357707006545728719651494384317497942177993032739778398001952201667284323691607312819796036779374423837576479275454953999865750584684592993292347483309178232523897058253412878901324740104919248

e2 = 13813369129257838
p2 = 121009772735460235364940622989433807619211926015494087453674747614331295040063679722422298286549493698150690694965106103822315378461970129912436074962111424616439032849788953648286506433464358834178903821069564798378666159882090757625817745990230736982709059859613843100974349380542982235135982530318438330859
q2 = 94582257784130735233174402362819395926641026753071039760251190444144495369829487705195913337502962816079184062352678128843179586054535283861793827497892600954650126991213176547276006780610945133603745974181504975165082485845571788686928859549252522952174376071500707863379238688200493621993937563296490615649
c2 = 7984888899827615209197324489527982755561403577403539988687419233579203660429542197972867526015619223510964699107198708420785278262082902359114040327940253582108364104049849773108799812000586446829979564395322118616382603675257162995702363051699403525169767736410365076696890117813211614468971386159587698853722658492385717150691206731593509168262529568464496911821756352254486299361607604338523750318977620039669792468240086472218586697386948479265417452517073901655900118259488507311321060895347770921790483894095085039802955700146474474606794444308825840221205073230671387989412399673375520605000270180367035526919

給定兩個密文(c1 c2)的情況下,通常需要找到兩者之間存在的關係,“合併”密文求解才能得到正確的明文。

先計算phi1和phi2,然後分別計算e和phi的gcd,發現都等於14,所以這裡問題考察e和phi不互素(d的逆元求不出來)情況下的求解。

由於m^e mod n =c,m一樣,e不同,c才不同。改變了e,對應的密文c也需要改變

image-20240604184938552

我們把 m^14看成一個整體 M 則 M^x ≡ c mod n 那麼 M的加密指數E 就是x,解密指數D就變成了 invert(x,phi) 從而我們就可以根據 c^D = M mod n 求解出來M 即(m^x ),對M開x次方根即可得到m

但根據第一段已知條件就能把m求出來嗎?顯然是不可能的。兩段已知條件中p1和p2是相等的,但是q1和q2不相等,所以p1*q1!=p2*q2,也就是說兩段條件下m所在的有限域不同,第一段條件直接開根解出來的明文m不一定滿足第二段的域

不可以直接利用其中一段已知 e、p、q、c求出來m

正確思路:

已知存在如下數學公等式:

1  gcd(e,phi)=b

2  e = a * b

3  e*d ≡ 1 mod phi

4  m^e ≡ c mod n

5  a*b*d ≡ 1 mod phi 由2和3得到,這裡可以推出a*b*d mod phi = 1

6  m^(a*b) ≡ c mod n 由2和4得到,這裡可以變換成c ≡ m^(a*b) mod n

存在性質:

image-20240604190739805

由以上可以推出c^(b*d) ≡ m^(abbd) mod n

因為a*b*d=1

所以c^(bd) ≡ m^b mod n

所以我們先要求出b*d,然後就能算出m^b。求bd我們可以根據5式子,所以要算出a。由題目分析我們知道b=14,所以a=e/b。程式碼如下:

p = p1
phi1 = (p - 1) * (q1 - 1)
phi2 = (p - 1) * (q2 - 1)
b = gmpy2.gcd(e1, phi1)
a1 = e1 // b
a2 = e2 // b
bd1 = gmpy2.invert(a1, phi1)
bd2 = gmpy2.invert(a2, phi2)

由以上我們分別求出了bd,然後就可以分別算出mb。到了這一步還是無法算出m的(因為兩段已知條件中p1和p2是相等的,但是q1和q2不相等,所以p1*q1!=p2*q2,也就是說兩段條件下m所在的有限域不同,第一段條件直接開根解出來的明文m不一定滿足第二段的域)

有同餘式組:

c1 ≡ m^b1 mod n1  變換得到  c1 ≡ m^b1 mod (p1 * q1) 
c2 ≡ m^b2 mod n2    同理 c2 ≡ m^b2 mod (p2 * q2)

根據同餘性質:
$$
a ≡ b mod (mn) 則 a ≡ b mod m,a ≡ b mod n
$$
所以得到下列式子:

c1 ≡ m^b1 mod p1

c1 ≡ m^b1 mod q1

c2 ≡ m^b2 mod p2

c2 ≡ m^b2 mod q2

因為p1和p2相等,則c1 ≡ m^b1 mod p,c2 ≡ m^b2 mod p

根據如下性質:

image-20240604192104907

我們可以得到c3 ≡(m^b1 * m^b2 )mod p

程式碼如下:

mb1 = pow(c1, bd1, n1)
mb2 = pow(c2, bd2, n2)
c3 = mb1 * mb2 % p
c2 = mb2 % q2
c1 = mb1 % q1

根據中國剩餘定理

image-20240604192436147

簡單來說,就是求一個整數滿足一組同餘式組。

所以這裡把c1,c2,c3 "連線" 起來,求一個特解c,即c滿足如下:

c3 = c % p

c2 = c % q2

c1 = c % q1

所以求特解c的程式碼如下:

res = solve_crt([c1, c2, c3], [q1, q2, p]) 
libnum庫 solve_crt 專門求解中國剩餘定理特解
第一個列表是各個同餘方程右側的常數(即餘數)
第二個列表是各個同餘方程右側的模數(即除數)
函式返回一個整數解,該解滿足給定的同餘方程組

於是我們重新得到了c ≡ m^e mod n的形式:

res ≡ m^14 mod q1*q2

e依舊是14,n=q1*q2

m^14 = c mod q1*q2 這裡依舊不能直接開方求(此時 14 與 phi_n 不互素,求不出d )

gcd(e,phi_n)=2

因此 把 (m^2)^7 = c mod q1*q2 這裡把 m^2看成整體,求D = invert(7,(q1-1)*(q2-1)) 之後rsa 根據 c^D = M mod n

得到 m^2 開二次根得到明文m

image-20240604192904902

程式碼如下:

n = q1 * q2
f = (q1 - 1) * (q2 - 1)
m = res % n
d2 = gmpy2.invert(7, f)
m = pow(m, d2, n)
msg = gmpy2.iroot(m, 2)[0]
print(long_to_bytes(msg))

完整程式碼:

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

e1 = 14606334023791426
p1 = 121009772735460235364940622989433807619211926015494087453674747614331295040063679722422298286549493698150690694965106103822315378461970129912436074962111424616439032849788953648286506433464358834178903821069564798378666159882090757625817745990230736982709059859613843100974349380542982235135982530318438330859
q1 = 130968576816900149996914427770826228884925960001279609559095138835900329492765336419489982304805369724685145941218640504262821549441728192761733409684831633194346504685627189375724517070780334885673563409259345291959439026700006694655545512308390416859315892447092639503318475587220630455745460309886030186593
c1 = 11402389955595766056824801105373550411371729054679429421548608725777586555536302409478824585455648944737304660137306241012321255955693234304201530700362069004620531537922710568821152217381257446478619320278993539785699090234418603086426252498046106436360959622415398647198014716351359752734123844386459925553497427680448633869522591650121047156082228109421246662020164222925272078687550896012363926358633323439494967417041681357707006545728719651494384317497942177993032739778398001952201667284323691607312819796036779374423837576479275454953999865750584684592993292347483309178232523897058253412878901324740104919248
n1 = p1 * q1

e2 = 13813369129257838
p2 = 121009772735460235364940622989433807619211926015494087453674747614331295040063679722422298286549493698150690694965106103822315378461970129912436074962111424616439032849788953648286506433464358834178903821069564798378666159882090757625817745990230736982709059859613843100974349380542982235135982530318438330859
q2 = 94582257784130735233174402362819395926641026753071039760251190444144495369829487705195913337502962816079184062352678128843179586054535283861793827497892600954650126991213176547276006780610945133603745974181504975165082485845571788686928859549252522952174376071500707863379238688200493621993937563296490615649
c2 = 7984888899827615209197324489527982755561403577403539988687419233579203660429542197972867526015619223510964699107198708420785278262082902359114040327940253582108364104049849773108799812000586446829979564395322118616382603675257162995702363051699403525169767736410365076696890117813211614468971386159587698853722658492385717150691206731593509168262529568464496911821756352254486299361607604338523750318977620039669792468240086472218586697386948479265417452517073901655900118259488507311321060895347770921790483894095085039802955700146474474606794444308825840221205073230671387989412399673375520605000270180367035526919
n2 = p2 * q2

p = p1
phi1 = (p - 1) * (q1 - 1)
phi2 = (p - 1) * (q2 - 1)
b = gmpy2.gcd(e1, phi1)
a1 = e1 // b
a2 = e2 // b
bd1 = gmpy2.invert(a1, phi1)
bd2 = gmpy2.invert(a2, phi2)

mb1 = pow(c1, bd1, n1)
mb2 = pow(c2, bd2, n2)
c3 = mb1 * mb2 % p
c2 = mb2 % q2
c1 = mb1 % q1

res = solve_crt([c1, c2, c3], [q1, q2, p])   #crt中國同餘定理,求出特解作為
print(res)

n = q1 * q2
f = (q1 - 1) * (q2 - 1)
M = res % n
D = gmpy2.invert(7, f)
msg = pow(M, D, n)
m = gmpy2.iroot(msg, 2)[0]
print(long_to_bytes(m))
#flag{gcd_e&\xcf\x86_isn't_1}
#中間的\xcf\x86為utf-8編碼,轉換得到字元:φ
#flag{gcd_e&φ_isn't_1}