CRYPTO
9个CTF密码学的题,链接在这,请自取
链接:https://pan.baidu.com/s/1em_JledhAaO0_1E7Y-AWhQ?pwd=osyg
提取码:osyg
--来自百度网盘超级会员V3的分享
script
让我们一起写MD5脚本吧。
通过题目及其附件可知,此题考查MD5加密
明文:flag{P7?Y0OG?0XPC?ZPK}
密文:9e86????007f??9a38???449a?0ea7cf
Python 3内置的 hashlib 模块包括了 md5 和 sha1 算法,暴力猜明文缺失字符,编写python脚本如下所示:
import hashlib
# flag{P7?Y0OG?0XPC?ZPK}
s1 = "flag{P7"
s2 = "Y0OG"
s3 = "0XPC"
s4 = "ZPK}"
dict = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
for i in range(36):
for j in range(36):
for k in range(36):
src = s1 + dict[i] + s2 + dict[j] + s3 + dict[k] + s4
src_bytes = src.encode('utf-8') # 将字符串转换为字节串
pre = hashlib.md5()
pre.update(src_bytes)
md5 = pre.hexdigest() # 直接获取hexdigest,无需转换为字符串
if '9e86' in md5 and '9a38' in md5 and '0ea7cf' in md5:
print(md5, ' ', src)
运行脚本,得出flag
flag{P70Y0OG00XPC0ZPK}
dp
dp=d%(p-1)
打开题目附件发现给了e 、c、 n 和dp,典型dp泄露问题,如下所示
n = 8604206664806745342168308407736664243779255857304203559954887795876314292548808824569221326135442951396570846730905060035093483091560994483766999321792528742385522688674491325318243227665651447454225684489922429130701999583472403938977116046240939097443373997461261268576566757297338922187501639574851029992578820698058472586961747714012538193674494758948475663291020567990855344532515152207300039545667460492842519422816159286385691631813719409268620014517296396144435387913805962148004421071107300134917
e = 65537
dp = 5322568719169737161435373804079374052963099217986542304765220927456862340459918748565303396239095461305158145873483711181078415768561073654821282898895792014510875476759654876641542774715410624823541347
c = 7713010941776018394460937838688101138886389440124967436362634520453525787263803153048839218904596792025221739398376160611187175949223252314089684537538587279344619934441104448127018949686378560731689286639199775823979889880011530090416478590812561931551073004551522758033697758211066364688996430692968155580514545636400072748535651733331992209003506999556029761752106288763442020289094502293759308446402753316908997325117590363436976980346946963276901401118341392396023155471904168993033594607832278309287
首先dp是dp=d%(p-1),可以知道的是,如下所示:
c≡m^e mod n
m≡c^d mod n
ϕ(n)=(p−1)∗(q−1)
d∗e≡1 mod ϕ(n)
dp≡d mod (p−1)
由上式可以得到dp∗e≡d∗e mod (p−1)
因此可以得到d∗e=k∗(p−1)+dp∗ed∗e≡1 mod ϕ(n)
将式1带入式2可以得到k∗(p−1)+dp∗e≡1 mod (p−1)∗(q−1)。
故此可以得到k2∗(p−1)∗(q−1)+1=k1∗(p−1)+dp∗e
变换一下(p−1)∗[k2∗(q−1)−k1]+1=dp∗e
因为dp<p−1,
可以得到e>k2∗(q−1)−k1。
假设x=k2∗(q−1)−k1,
可以得到x的范围为(0,e),
因此有x∗(p−1)+1=dp∗e。
那么可以遍历x∈(0,e),求出p-1,
求的方法也很简单,遍历65537种可能,其中肯定有一个p可以被n整除那么求出p和q,
即可利用ϕ(n)=(p−1)∗(q−1)d∗e≡1 mod ϕ(n),
推出d≡1∗e−1 mod ϕ(n)。
注:这里的-1为逆元,不是倒数的那个-1。
综上所述,可以编写exp脚本,如下所示:
# -*- coding: utf-8 -*-
import gmpy2
n = 8604206664806745342168308407736664243779255857304203559954887795876314292548808824569221326135442951396570846730905060035093483091560994483766999321792528742385522688674491325318243227665651447454225684489922429130701999583472403938977116046240939097443373997461261268576566757297338922187501639574851029992578820698058472586961747714012538193674494758948475663291020567990855344532515152207300039545667460492842519422816159286385691631813719409268620014517296396144435387913805962148004421071107300134917
e = 65537
dp = 5322568719169737161435373804079374052963099217986542304765220927456862340459918748565303396239095461305158145873483711181078415768561073654821282898895792014510875476759654876641542774715410624823541347
c = 7713010941776018394460937838688101138886389440124967436362634520453525787263803153048839218904596792025221739398376160611187175949223252314089684537538587279344619934441104448127018949686378560731689286639199775823979889880011530090416478590812561931551073004551522758033697758211066364688996430692968155580514545636400072748535651733331992209003506999556029761752106288763442020289094502293759308446402753316908997325117590363436976980346946963276901401118341392396023155471904168993033594607832278309287
for i in range(1, 65538):
if (dp * e - 1) % i == 0:
if n % (((dp * e - 1) // i) + 1) == 0:
q = n // (((dp * e - 1) // i) + 1)
p = (((dp * e - 1) // i) + 1)
phi = (p - 1) * (q - 1)
d = gmpy2.invert(e, phi)
m = pow(c, d, n)
# 将mpz对象转换为Python int对象,然后转换为字节串
m_int = int(m)
m_bytes = m_int.to_bytes((m_int.bit_length() + 7) // 8, byteorder='big')
print(m_bytes.decode('utf-8', errors='ignore')) # 使用'ignore'错误处理策略来应对可能的非UTF-8编码数据
运行脚本,拿到flag,如下图所示:
flag{4a1db444-0b02-496e-900e-3014cd566d0e}
coppersmith
你有听说过coppersmith定理么?
Coppersmith 相关攻击与Don Coppersmith紧密相关,他提出了一种针对于模多项式(单变量,二元变量,甚至多元变量)找所有小整数根的多项式时间的方法。
这里我们以单变量为主进行介绍,假设 模数为 N ,N 具有一个因子 b≥Nβ,0<β≤1b≥Nβ,0<β≤1, 多项式 F 的次数为 δδ。
那么该方法可以在O(cδ5log9(N))O(cδ5log9(N)) 的复杂度内找到该多项式所有的根x0x0,在这个问题中,目标是找到在模 N 意义下多项式所有的根,这一问题被认为是复杂的,与该多项式具有相同根 x0x0更小系数,定义域为整数域的多项式 g,由于在整数域上找多项式的根是简单的(Berlekamp–Zassenhaus),从而我们就得到了原多项式在模意义下的整数根。
本题已知p的大部分位数,可以采取coppersmith定理对其进行攻击。
打开题目附件,输出三个密文,如下图所示:
from secret import flag
from Crypto.Util.number import *
m = bytes_to_long(flag)
p = getPrime(512)
q = getPrime(512)
N = p * q
e = 7
c = pow(m, e, N)
high_p = (p >> 100) << 100
print(c, N, high_p, sep='\n')
# 77910349061944763568299396394184337520861899083817490010678766043320388729842050532499742515132299125221386423487817013007167101659632771120727305169401713711755701139645391311421914142639007159020652755880068954988225402131362184667436752944331368809243280933094976267099141065017878199319211904257432652753
# 99887986204824691113457754897953425406993412586030259044004283966194202433452866024995465248688896193125819761385921365388030307691682145106269184432165936577174730773115650122496935533603059557681592007428920955897003476296682566264772005134125852663260971355535474414913501328212769545952135420770881499467
# 12672576027810761975840956553905924324108169270520824932988309977042643967090398117355253953195633095326913407044418517938976916071656473263683948565757952
RSA Coppersmith Attack情景为已知p的高位,但低100位未知,可以通过coppersmith attack分解出p和q。
sage代码如下:
SageMathCell:https://sagecell.sagemath.org/
# SageMath
c = 77910349061944763568299396394184337520861899083817490010678766043320388729842050532499742515132299125221386423487817013007167101659632771120727305169401713711755701139645391311421914142639007159020652755880068954988225402131362184667436752944331368809243280933094976267099141065017878199319211904257432652753
N = 99887986204824691113457754897953425406993412586030259044004283966194202433452866024995465248688896193125819761385921365388030307691682145106269184432165936577174730773115650122496935533603059557681592007428920955897003476296682566264772005134125852663260971355535474414913501328212769545952135420770881499467
high_p = 12672576027810761975840956553905924324108169270520824932988309977042643967090398117355253953195633095326913407044418517938976916071656473263683948565757952
pbits = 512
kbits = 100
PR.<x> = PolynomialRing(Zmod(N)) # x: low 100 bits of p
f = high_p + x
x0 = f.small_roots(X=2^kbits, beta=0.4)[0]
print ("x: %s" % x0)
p = high_p + x0
print ("p: ", p)
q = N // int(p)
print ("q: ", q)
得出输出结果,如下图所示:
综上所述,得到p和q后,可以算出d,再解密即可拿到flag。
对其编写exp脚本,如下所示:
from Cryptodome.Util.number import *
p = 12672576027810761975840956553905924324108169270520824932988309977042643967090398117355253953195633095326913407044418517938977305083732740090760858841266427
q = 7882216369080307573684148336656348276125777637863593106760322365174229732530885238209013585945585289415095195664039487452042451160318978844874180224833521
N = p * q
e = 7
c = 77910349061944763568299396394184337520861899083817490010678766043320388729842050532499742515132299125221386423487817013007167101659632771120727305169401713711755701139645391311421914142639007159020652755880068954988225402131362184667436752944331368809243280933094976267099141065017878199319211904257432652753
d = inverse(e, (p-1)*(q-1))
m = pow(c, d, N)
print(long_to_bytes(m))
运行结果,得到flag,如下图所示:
根据flag形式,flag值为
flag{4e5c8922-3b95-9190-1ed6-1198ce4d8064}
LCG
我们在敌方的随机数生成器中提取到了部分信息,你能否从中解出关键信息呢?
打开题目附件,看到四行密文,如下所示:
from secret import flag
from Crypto.Util.number import *
seed = bytes_to_long(flag)
bits = seed.bit_length()
while True:
p = getPrime(bits+1)
if p > seed:
break
print(p)
a = getRandomRange(1, p)
b = getRandomRange(1, p)
for _ in range(3):
seed = (a*seed + b) % p
print(seed)
# 128987642185762631932220495481391630226043626316907538452726762212389321270926330459165141807985514151
# 106251204638652955228263443087141132193772679785945812348606411450231736217554078867269536273823941317
# 108567696415488189015128528616460098558795853372868300042216845912719954168424158333151674140021074736
# 67151728692480947558775166912293436958127879133219560190637295597591667555742533671408274392843074079
目前我们在编程中经常会使用随机数,但是其中会不会存在什么问题呢?要知道CPU计算中的各种状态都是确定的,在其中的随机数不是凭空产生的,所以这种随机数真的随机吗?
目前生成随机数的方式主要分为以下几种:
硬件随机数生成器、利用现有硬件,从非预期方式产生随机数(比如利用音频的产生、硬盘寻址时间等)、伪随机数、量子技术。
虽然选择很多,但是目前还是主要采用伪随机数的方式来应对实际开发中需要的场景。
用于产生这些看起来随机但实际是由确定性算法生成数字的机制被称为”伪随机数发生器”,简称为PRNG。PRNG的中心是确定的,如果攻击者知道其内部的完整状态,则可以对未来的值和过去的值进行预测。如果PRNG被用于加密密钥、生成证书等场景,就会出现安全问题。
线性同余生成器(LCG),线性同余方法线性同余方法(LCG)是个产生伪随机数的方法。它是根据递归公式:N_NaN\equiv (A\times N_{j}+B){\pmod {M}},其中A,B,M是产生器设定的常数。LCG的周期最大为 M,但大部分情况都会少于M。
要令LCG达到最大周期,应符合以下条件:
B,M互质,M的所有质因数都能整除A-1,若M是4的倍数,A-1也是,A,B,N[0]都比M小,A,B是正整数。
线性同余生成器是一种常见的伪随机数生成器(PRNG)。通过递归执行获得近似真随机序列。
伪随机数从一个初始种子开始,通过线性同余方程递归计算得到序列。需要注意的的是PRNG(Pseudo-randomized numbers generator)生产的并不是真正意义上的随机序列,因其可根据一定的参数计算出来,称之为计算确定的。
本题使用flag作为LCG(线性同余生成器)的种子,并给出了前3个输出,攻击者可以直接从这前3个输出中获取到到种子的值。
综上所述,对其进行exp脚本编写,如下所示:
from Cryptodome.Util.number import *
def solve1(p, a, b, n1):
return (n1 - b) * inverse(a, p) % p
def solve2(p, a, n1, n2):
b = (n2 - n1 * a) % p
print("b: ", b)
return solve1(p, a, b, n1)
def solve3(p, n1, n2, n3):
a = (n3 - n2) * inverse(n2 - n1, p) % p
print("a: ", a)
return solve2(p, a, n1, n2)
p = 128987642185762631932220495481391630226043626316907538452726762212389321270926330459165141807985514151
n1 = 106251204638652955228263443087141132193772679785945812348606411450231736217554078867269536273823941317
n2 = 108567696415488189015128528616460098558795853372868300042216845912719954168424158333151674140021074736
n3 = 67151728692480947558775166912293436958127879133219560190637295597591667555742533671408274392843074079
seed = solve3(p, n1, n2, n3)
print(long_to_bytes(seed))
运行脚本,结果如下图所示:
根据flag形式,flag值为
flag{9c0ccf89-a555-79dd-e40b-61ca741c9674}
lfsr
flag形式为flag{},线性移位反馈寄存器,你能从它的输出中发现什么秘密么?
LFSR示意图如下:
每一次输出,都会取最右边寄存器中的值进行输出。输出之后,所有寄存器会向右边移一位,这个时候最左边的寄存器就会空出来。为了让最左边的寄存器有值,会在输出之前,通过一些操作计算出一个反馈值,填到最左边的寄存器中。
可以看见,这个反馈值,实际上是当前所有n个寄存器的一个线性变换:
其中,ai即为本题中需要求出的mask的每一位。如果我们能够求出所有的n个ai,那么我们就可以得到mask,进而得到flag。
而本题
本题中,前100个输出bit即为这个LFSR的初始状态,所以第101个输出,即为前100个输出的一个线性变换。同样的,第102个输出,即为第1个一直到第101个这100个输出的一个线性变换;第103个输出,即为第2个到第102个输出的一个线性变换……
这样,可以写出:
未知量只有100个a i,因此只要有100组这样的表达式,我们就可以利用解方程组的方式求出这100个a i。
写成矩阵形式,即:
注意,这里的运算都是在GF(2)上的,使用SageMath可以很轻松地解决这个问题。
也就是说,我们只需要利用前200个输出bit,就可以求出mask。
打开题目附件,只看到二进制的内容,如下图所示:
exp编写,代码如下所示:
SageMathCell: https://sagecell.sagemath.org/
#前200个输出bit
out = "01001100111011110111110110101001110010100101000011111101101111010111100111110100100101110111001101110110011000010100100111011010001101100000111110111100000101000010010000110010110110110110011111101011"
N = 100
F = GF(2)
Sn = [vector(F, N) for j in range(N+1)]
for j in range(N + 1):
Sn[j] = list((map(int, out[j:j+N])))
X = matrix(F, Sn[:N])
Y = matrix(F, N, 1, Sn[-1])
A = X.solve_right(Y)
mask = ''
for i in A.transpose()[0]:
mask = str(i) + mask
print(int(mask, 2))
输出结果,如下图所示:
根据flag形式,flag值为
flag{856137228707110492246853478448}
next
奇怪的模数生成方式,你能否从中分解出N呢?
RSA公开密钥密码体制是一种使用不同的加密密钥与解密密钥,“由已知加密密钥推导出解密密钥在计算上是不可行的”密码体制。
在公开密钥密码体制中,加密密钥(即公开密钥)PK是公开信息,而解密密钥(即秘密密钥)SK是需要保密的。加密算法E和解密算法D也都是公开的。虽然解密密钥SK是由公开密钥PK决定的,但却不能根据PK计算出SK。
正是基于这种理论,1978年出现了著名的RSA算法,它通常是先生成一对RSA密钥,其中之一是保密密钥,由用户保存;另一个为公开密钥,可对外公开,甚至可在网络服务器中注册。为提高保密强度,RSA密钥至少为500位长,一般推荐使用1024位。这就使加密的计算量很大。为减少计算量,在传送信息时,常采用传统加密方法与公开密钥加密方法相结合的方式,即信息采用改进的DES或IDEA对话密钥加密,然后使用RSA密钥加密对话密钥和信息摘要。对方收到信息后,用不同的密钥解密并可核对信息摘要。
本题在生成RSA模数的过程中,使用的两个素数十分接近,因此非常容易被分解。
打开题目附件,可以看到C、N的密文,如下所示:
from secret import flag
from Crypto.Util.number import *
p = getPrime(512)
q = p + 2
while True:
if isPrime(q):
break
q += 2
N = p * q
e = 0x10001
m = bytes_to_long(flag)
c = pow(m, e, N)
print(c)
print(N)
# 148424465798304945167250248254436660371772148039137809407743400737194128537141868847451364265636630340866508741642501886466340194647554617583629924131714531271539011128061022480521390215365303820954694837540067178184270211155380856554625937689079346774001636736492546883595465564744950751854489444787660248226
# 177920246731961984692844675027794269351974655978633360958792135066811113973204490061355452695689806058893015396266267360582784890984276521557441293993864861033228213124084744486810727223671447408512757938978007969098885482833084907318019060009833379873711469730284507118386587060518773729384368339738258068433
RSA中p和q很接近
分离p和q
方法一:直接利用N值从https://www.alpertron.com.ar/ECM.HTM在线网站上分解。
N=177920246731961984692844675027794269351974655978633360958792135066811113973204490061355452695689806058893015396266267360582784890984276521557441293993864861033228213124084744486810727223671447408512757938978007969098885482833084907318019060009833379873711469730284507118386587060518773729384368339738258068433
分解得出
p = 13338674849173061115293654793180407094989029053925404248071219621296728291036306985378067182889271608069125757071973826272388440545180205478075524105332271
q = 13338674849173061115293654793180407094989029053925404248071219621296728291036306985378067182889271608069125757071973826272388440545180205478075524105332223
方法二:拿yafu直接分解,编写exp脚本进行分离p和q,如下所示:
RSA-p和q挨得很近(费马分解):https://blog.csdn.net/hacker_zrq/article/details/121444869
【密码学】RSA破解方法汇总(PYTHON实现):https://blog.csdn.net/Mr_Fmnwon/article/details/134962639
import gmpy2
N=177920246731961984692844675027794269351974655978633360958792135066811113973204490061355452695689806058893015396266267360582784890984276521557441293993864861033228213124084744486810727223671447408512757938978007969098885482833084907318019060009833379873711469730284507118386587060518773729384368339738258068433
temp = gmpy2.iroot(N, 2)[0]
p = gmpy2.next_prime(temp)
q = N // p
print("p=")
print(p)
print("q=")
print(q)
成功分离出p和q
综上所述得出pq的值,编写exp脚本进行解密,如下所示:
from Cryptodome.Util.number import *
p = 13338674849173061115293654793180407094989029053925404248071219621296728291036306985378067182889271608069125757071973826272388440545180205478075524105332271
q = 13338674849173061115293654793180407094989029053925404248071219621296728291036306985378067182889271608069125757071973826272388440545180205478075524105332223
e = 0x10001
c = 148424465798304945167250248254436660371772148039137809407743400737194128537141868847451364265636630340866508741642501886466340194647554617583629924131714531271539011128061022480521390215365303820954694837540067178184270211155380856554625937689079346774001636736492546883595465564744950751854489444787660248226
m = pow(c, inverse(e, (p-1)*(q-1)), p*q)
print(long_to_bytes(m))
解密,即可得到flag,如下图所示:
根据flag形式,flag值为
flag{3e364d7b-261d-3715-5d4d-4ddda6eb49f9}
rwx
读写与执行。
打开附件,看到为python脚本,如下所示
from flag import flag
from Crypto.Util.number import long_to_bytes,bytes_to_long
from os import urandom
import hashlib
def know(m):
r=[]
w=[]
x=[]
e=[]
for i in m:
r.append(bin(ord(i))[-1])
w.append(bin(ord(i))[-2])
x.append(bin(ord(i))[-3])
e.append(ord(i)>>3)
return r,w,e,x
def inf(r,w,x,files):
re=[]
for i in range(len(files)):
re.append(long_to_bytes(int(bin(bytes_to_long(files[i]))[2:]+r[i]+w[i]+x[i],2)))
return re
r,w,e,x=know(flag)
files=[]
f=open("output","wb")
for i in range(len(flag)):
files.append(urandom(8))
for i in files:
f.write(i.encode("hex")+"\n")
files=inf(r,w,x,files)
for i in files:
f.write(hashlib.sha256(i).hexdigest()+"\n")
for i in e:
f.write(hashlib.sha256(str(i)+urandom(2)).hexdigest()+"\n")
print r
print w
print x
print e
输出的hash值如下图所示:
Hash的时候分段hash了,存在逻辑问题,可以分段爆破,最终复原明文。
综上所述,编写python2的exp脚本,脚本如下所示:
f=open("output","rb").readlines()
print len(f)/3
random1=[]
for i in range(43):
random1.append(f[i].strip().decode("hex"))
targethash=[]
for i in range(43,86):
targethash.append(f[i].strip())
lasthash=[]
for i in range(86,129):
lasthash.append(f[i].strip())
import hashlib
def b1s(hash):
for i1 in range(0xff):
for i2 in range(0xff):
for xx in range(32):
if hashlib.sha256(str(xx)+chr(i1)+chr(i2)).hexdigest()==hash:
return xx
def brutehash(lasthash):
e=[]
for i in lasthash:
print i
e.append(b1s(i))
return e
import hashlib
from Crypto.Util.number import long_to_bytes,bytes_to_long
x=[]
w=[]
r=[]
for i in range(43):
for i1 in ["0","1"]:
for i2 in ["0","1"]:
for i3 in ["0","1"]:
if hashlib.sha256(long_to_bytes(int(bin(bytes_to_long(random1[i]))[2:]+i1+i2+i3,2))).hexdigest()==targethash[i]:
r.append(i1)
w.append(i2)
x.append(i3)
e=brutehash(lasthash)
print r
print w
print x
print e
for i in range(43):
print chr(int(bin(e[i])[2:]+x[i]+w[i]+r[i],2)),
运行结果,拿到flag,如下图所示:
flag{ 8 u u u u u _ d d _ 3 y y y u i _ l i k e _ t h e _ i n t e r n e t _ g 0 }
flag{8uuuuu_dd_3yyyui_like_the_internet_g0}
rsarsa
flag形式为flag{},使用RSA算法对密文进行解码,c、p、q、e是RSA算法的参数。
打开题目附件给出rsa密码给了相关的值。
Math is cool! Use the RSA algorithm to decode the secret message, c, p, q, and e are parameters for the RSA algorithm.
p = 9648423029010515676590551740010426534945737639235739800643989352039852507298491399561035009163427050370107570733633350911691280297777160200625281665378483
q = 11874843837980297032092405848653656852760910154543380907650040190704283358909208578251063047732443992230647903887510065547947313543299303261986053486569407
e = 65537
c = 83208298995174604174773590298203639360540024871256126892889661345742403314929861939100492666605647316646576486526217457006376842280869728581726746401583705899941768214138742259689334840735633553053887641847651173776251820293087212885670180367406807406765923638973161375817392737747832762751690104423869019034
Use RSA to find the secret message
根据题目里面附件的值可以写出如下脚本
# -*- coding:utf-8 -*-
import gmpy2
from numpy.compat import long
p = 9648423029010515676590551740010426534945737639235739800643989352039852507298491399561035009163427050370107570733633350911691280297777160200625281665378483
q = 11874843837980297032092405848653656852760910154543380907650040190704283358909208578251063047732443992230647903887510065547947313543299303261986053486569407
e = 65537
c = 83208298995174604174773590298203639360540024871256126892889661345742403314929861939100492666605647316646576486526217457006376842280869728581726746401583705899941768214138742259689334840735633553053887641847651173776251820293087212885670180367406807406765923638973161375817392737747832762751690104423869019034
phi = (p - 1) * (q - 1)
# 计算得到私钥(n, d)
d = long(gmpy2.invert(e, phi)) # 如果你已经安装了gmpy2库,并希望更快地计算大整数的模逆元,请使用此行
n = p * q
# 计算并输出c^d mod n
plaintext = pow(c, d, n)
print(plaintext)
最终运行脚本得出flag。
flag形式为flag{},则
flag{5577446633554466577768879988}
rsa2
很简单的,使用私钥解密即可。
将三个文件放置在linux系统的任意目录中。
查看提供的文件,发现存在公钥与私钥,直接使用私钥解密。打开终端在linux中输入以下命令即可完成解密。
openssl pkeyutl -decrypt -in enc.txt -inkey private.pem
flag{0e3923e0-bd39-423c-bef3-a62ac973f816}