week2

1.滴啤

from Crypto.Util.number import *
import gmpy2
from flag import flag
def gen_prime(number):
    p = getPrime(number//2)
    q = getPrime(number//2)
    return p,q

m = bytes_to_long(flag.encode())
p,q = gen_prime(1024)
print(p*q)
e = 65537
d = gmpy2.invert(e,(p-1)*(q-1))
print(d%(p-1))
print(pow(m,e,p*q))
# 93172788492926438327710592564562854206438712390394636149385608321800134934361353794206624031396988124455847768883785503795521389178814791213054124361007887496351504099772757164211666778414800698976335767027868761735533195880182982358937211282541379697714874313863354097646233575265223978310932841461535936931
# 307467153394842898333761625034462907680907310539113349710634557900919735848784017007186630645110812431448648273172817619775466967145608769260573615221635
# 52777705692327501332528487168340175436832109866218597778822262268417075157567880409483079452903528883040715097136293765188858187142103081639134055997552543213589467751037524482578093572244313928030341356359989531451789166815462417484822009937089058352982739611755717666799278271494933382716633553199739292089

滴啤就是dp的意思,考察的是dp泄露,先来推理

from Crypto.Util.number import *
import gmpy2
for i in range(1,e):
    if (dp*e-1)%i == 0:
        if (n%((dp*e-1)//i+1)) == 0:
            p = (dp*e-1)//i+1
            q = n // p#注意都是整除
            phi_n = (p-1)*(q-1)
            d = gmpy2.invert(e,phi_n)
            m = pow(c,d,n)
print(long_to_bytes(m))

 b'flag{cd5ff82d-989c-4fbf-9543-3f98ab567546}'

2.不止一个pi

题目

from flag import flag
from Crypto.Util.number import *
import gmpy2
p = getPrime(1024)
q = getPrime(1024)
n = p**3*q**2
print("q = ",q)
print("p = ",p)
m = bytes_to_long(flag.encode())
c = pow(m,65537,n)
print("c = ",c)

# q =  115478867870347527660680329271012852043845868401928361076102779938370270670897498759391844282137149013845956612257534640259997979275610235395706473965973203544920469416283181677660262509481282536465796731401967694683575843183509430017972506752901270887444490905891490955975762524187534052478173966117471143713
# p =  171790960371317244087615913047696670778115765201883835525456016207966048658582417842936925149582378305610304505530997833147251832289276125084339614808085356814202236463900384335878760177630501950384919794386619363394169016560485152083893183420911295712446925318391793822371390439655160077212739260871923935217
# c =  4459183928324369762397671605317600157512712503694330767938490496225669985050002776253470841193156951087663107866714426230222002399666306287642591077990897883174134404896800482234781531592939043551832049756571987010173667074168282355520711905659013076509353523088583347373358980842707686611157050425584598825151399870268083867269912139634929397957514376826145870752116583185351576051776627208882377413433140577461314504762388617595282085102271510792305560608934353515552201553674287954987323321512852114353266359364282603487098916608302944694600227628787791876600901537888110093703612414836676571562487005330299996908873589228072982641114844761980143047920770114535924959765518365614709272297666231481655857243004072049094078525569460293381479558148506346966064906164209362147313371962567040047084516510135054571080612077333228195608109065475260832580192321853906138811139036658485688320161530131239854003996457871663456850196483520239675981391047452381998620386899101820782421605287708727667663038905378115235163773867508258208867367314108701855709002634592329976912239956212490788262396106230191754680813790425433763427315230330459349320412354189010684525105318610102936715203529222491642807382215023468936755584632849348996666528981269240867612068382243822300418856599418223875522408986596925018975565057696218423036459144392625166761522424721268971676010427096379610266649911939139451989246194525553533699831110568146220347603627745407449761792135898110139743498767543521297525802809254842518002190381508964357001211353997061417710783337

看到n=p**3*q**2,知道应该是考欧拉函数的扩展


from Crypto.Util.number import *
import gmpy2

q = 115478867870347527660680329271012852043845868401928361076102779938370270670897498759391844282137149013845956612257534640259997979275610235395706473965973203544920469416283181677660262509481282536465796731401967694683575843183509430017972506752901270887444490905891490955975762524187534052478173966117471143713
p = 171790960371317244087615913047696670778115765201883835525456016207966048658582417842936925149582378305610304505530997833147251832289276125084339614808085356814202236463900384335878760177630501950384919794386619363394169016560485152083893183420911295712446925318391793822371390439655160077212739260871923935217
c = 4459183928324369762397671605317600157512712503694330767938490496225669985050002776253470841193156951087663107866714426230222002399666306287642591077990897883174134404896800482234781531592939043551832049756571987010173667074168282355520711905659013076509353523088583347373358980842707686611157050425584598825151399870268083867269912139634929397957514376826145870752116583185351576051776627208882377413433140577461314504762388617595282085102271510792305560608934353515552201553674287954987323321512852114353266359364282603487098916608302944694600227628787791876600901537888110093703612414836676571562487005330299996908873589228072982641114844761980143047920770114535924959765518365614709272297666231481655857243004072049094078525569460293381479558148506346966064906164209362147313371962567040047084516510135054571080612077333228195608109065475260832580192321853906138811139036658485688320161530131239854003996457871663456850196483520239675981391047452381998620386899101820782421605287708727667663038905378115235163773867508258208867367314108701855709002634592329976912239956212490788262396106230191754680813790425433763427315230330459349320412354189010684525105318610102936715203529222491642807382215023468936755584632849348996666528981269240867612068382243822300418856599418223875522408986596925018975565057696218423036459144392625166761522424721268971676010427096379610266649911939139451989246194525553533699831110568146220347603627745407449761792135898110139743498767543521297525802809254842518002190381508964357001211353997061417710783337

e = 65537
phi = (p**3 - p**2) * (q**2 - q)
n = p**3 * q**2

d = gmpy2.invert(e, phi)
m = pow(c, d, n)
print(long_to_bytes(m))


b'flag{bu_zhi_yige_p1dsaf}'

3.halfcandecode

题目

from Crypto.Util.number import *
import gmpy2
from flag import flag
import os
from hashlib import md5

def gen_prime(number):
    p = getPrime(number // 2)
    q = gmpy2.next_prime(p)
    return p * q

def md5_hash(m):
    return md5(m.encode()).hexdigest()
e = 65537
n = gen_prime(1024)
m1 = bytes_to_long(flag[:len(flag) // 2].encode() + os.urandom(8))
c1 = pow(m1, e, n)
m2 = flag[len(flag) // 2:]
with open("out.txt","w") as f:
    f.write(str(n) + '\n')
    f.write(str(c1) + '\n')
    for t in m2:
        f.write(str(md5_hash(t))+'\n')

将flag分成两部分,对前一半部分进行随机填充后转换为整数m1,然后使用RSA加密得到密文c1。

将flag的后一半部分作为m2,对每个字符进行MD5哈希,并将哈希值写入文件"out.txt"中

这段代码的目的是生成一个RSA加密的挑战,其中一部分是RSA加密的密文,另一部分是经过MD5哈希的flag的剩余部分。我们可以在"out.txt"文件中找到n、c1和每个字符的MD5哈希值,可以使用RSA私钥解密c1以获取原始消息m1,并尝试破解MD5哈希值以还原flag的剩余部分。

我们知道这里应该采取费马解法,所以我们可以把n放到yafu中去,可以获取得到两个因子

P155 = 10631151190024160908870967192522097752991652918777416177941351782447314225123009693276679810786266997133099934443701772661928189884235742113123409596993841
P155 = 10631151190024160908870967192522097752991652918777416177941351782447314225123009693276679810786266997133099934443701772661928189884235742113123409596993409

  知道(p,q)后,我们就可以破解RSA了。接下来我们只需要用MD5在线工具破解下半段密文即可。

 前半部分

#p与q相近,可以费马分解。也可以直接开方求根附近的素数,即为p, q。
from Crypto.Util.number import *
from gmpy2 import next_prime,iroot
e = 0x10001
n = 113021375625152132650190712599981988437204747209058903684387817901743950240396649608148052382567758817980625681440722581705541952712770770893410244646286485083142929097056891857721084849003860977390188797648441292666187101736281034814846427200984062294497391471725496839508139522313741138689378936638290593969
c = 43054766235531111372528859352567995977948625157340673795619075138183683929001986100833866227688081563803862977936680822407924897357491201356413493645515962458854570731176193055259779564051991277092941379392700065150286936607784073707448630150405898083000157174927733260198355690620639487049523345380364948649
t = iroot(n,2)[0]
q = next_prime(t)
p = n//q
assert(n==p*q)
d = inverse(e,(p-1)*(q-1))
print(long_to_bytes(pow(c,d,n)))

4.Rotate Xor

题目

from secret import flag
from os import urandom
from pwn import xor
from Cryptodome.Util.number import *
k1 = getPrime(64)
k2 = getPrime(64)
ROUND = 12
ciphertext = xor(flag, long_to_bytes(k1))
def round_rotate_left(num, step):
    return ((num) << step | num >> (64-step)) & 0xffffffffffffffff
def encrypt_key(key):
    
    for _ in range(ROUND):
        key = round_rotate_left(key, 3) ^ k2
    
    return key
print('ciphertext =', ciphertext)
print('enc_k1 =', encrypt_key(k1))
print('k2 =', k2)

# ciphertext = b'\x8dSyy\xd2\xce\xe2\xd2\x98\x0fth\x9a\xc6\x8e\xbc\xde`zl\xc0\x85\xe0\xe4\xdfQlc'
# enc_k1 = 7318833940520128665
# k2 = 9982833494309156947

c=flag^k1,解密flag=c^k1,先从k1入手,定义了一个名为 round_rotate_left 的函数,用于对密钥进行循环左移操作,

在 encrypt_key 函数中,使用循环和异或操作对密钥进行了 ROUND 轮的处理,每轮都进行了循环左移和异或操作。

解密的话,就是逆向,先定义一个循环右移函数,再写一个decrypt_key函数,加密中是先左移再异或k2,解密就是先异或k2再进行循环右移还原k1,最后就是flag=xor^k1

from pwn import xor
from Crypto.Util.number import *
ROUND = 12
def round_rotate_right(num, step):#定义了一个函数,用于将一个数字向右循环移动若干位
return ((num >> step) | (num << (64 - step))) & 0xffffffffffffffff
def decrypt_key(enc_key):
for _ in range(ROUND):
enc_key = round_rotate_right(enc_key ^ k2, 3)
return enc_key
ciphertext = b'\x8dSyy\xd2\xce\xe2\xd2\x98\x0fth\x9a\xc6\x8e\xbc\xde`zl\xc0\x85\xe0\xe4\xdfQlc'
enc_k1 = 7318833940520128665  #加密密钥的初始值
k2 = 9982833494309156947   #另外一个密钥
dec_k1 = decrypt_key(enc_k1)#解密加密密钥enc_k1,得到解密后的密钥dec_k1
plaintext = xor(ciphertext, long_to_bytes(dec_k1))#将解密后的密钥dec_k1与密文进行异或操作,得到明文
print(plaintext)
b'flag{z3_s0lv3r_15_bri11i4nt}'

 5.partial decrypt

题目

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

m = bytes_to_long(flag)
e = 65537
p = getPrime(512)
q = getPrime(512)

n = p*q 

c = pow(m,e,n)

dp = inverse(e, (p-1))
dq = inverse(e, (q-1))
m1 = pow(c,dp, p)
m2 = pow(c,dq, q)
q_inv = inverse(q, p)
h = (q_inv*(m1-m2)) % p#根据CRT计算得到h,用于还原出原始消息m
print('m2 =', m2)
print('h =', h)
print('q =', q)

# m2 = 4816725107096625408335954912986735584642230604517017890897348901815741632668751378729851753037917164989698483856004115922538576470127778342121497852554884
# h = 4180720137090447835816240697100630525624574275
# q = 7325294399829061614283539157853382831627804571792179477843187097003503398904074108324900986946175657737035770512213530293277111992799331251231223710406931

我们要知道这里的h是什么

     dp=1+k_{1}(p-1),dq=1+k_{2}(q-1),m1=m (mod p),m2=m (mod q)因为h=(q_inv*(m1-m2))。所以h=(q_inv*(k_{3}p-k_{4}q))(mod p)=-k_{4}(modp),但是k4大小我们未知,其的正负都有可能。但是看到题目只解一半,也就说m > q,即k4 < 0, 所以h就是我们要求取的系数。

from Crypto.Util.number import long_to_bytes
m2 = 4816725107096625408335954912986735584642230604517017890897348901815741632668751378729851753037917164989698483856004115922538576470127778342121497852554884
h = 4180720137090447835816240697100630525624574275
q = 7325294399829061614283539157853382831627804571792179477843187097003503398904074108324900986946175657737035770512213530293277111992799331251231223710406931

m = m2 + h*q
print(long_to_bytes(m))
#flag{rsa_with_crt#b12a3a020c9cc5f1a6df4618256f7c88c83fdd95aab1a2b2656d760475bd0bf1}

6. broadcast

题目

from secret import flag
from Cryptodome.Util.number import *

menu = '''
Welcome to RSA Broadcasting system

please select your option:

1. brocast the flag
2. exit
'''
e = 17
def broadcast_the_flag():
    p = getPrime(256)
    q = getPrime(256)
    n=p*q
    m = bytes_to_long(flag)
    c = pow(m,e,n)
    print('n =', n)
    print('c =', c)
    print('e =', e)
while True:
    print(menu)
    opt = input('> ')
    try:
        opt = int(opt)
        if opt == 1:
            broadcast_the_flag()
        elif opt == 2:
            break
        else:
            print('invalid option')
    except:
        print('oh no, something wrong!')
        

低加密指数攻击

import gmpy2
from Crypto.Util.number import *
from pwn import *#pwn用于交互式连接
def CRT(cList, nList):#用CTR解密一组密文,clist包含密文的列表,nList是包含模数的列表
M = 1
for i in nList:
M = M * i       #计算所有模数的累乘
x = 0     #对每个模数进行循环处理
for i in range(len(nList)):
Mi = M // nList[i]   #除去当前模数的其他模数的乘积
Mi_inverse = gmpy2.invert(Mi, nList[i]) #计算 (M_i) 模 (n_i) 的乘法逆元 Mi_inverse
x += cList[i] * Mi * Mi_inverse
x = x % M #对x取模,是为了确保得到的解在正确的模数范围内
return x  #明文

context.log_level= "debug" #设置日志级别为调试模式
p = remote("IP", 端口号)  #使用 remote 函数连接到指定的IP地址和端口号
n_list = []
c_list = []
for _ in range(17):
p.recvuntil(b'> ')
p.sendline(str(1))
n = int(p.recvline().decode().strip('\n').split('=')[1])
c = int(p.recvline().decode().strip('\n').split('=')[1])
n_list.append(n)
c_list.append(c)#通过循环接收17个RSA加密的密文和对应的模数,将它们分别存储在 n_list 和 c_list 中
m = CRT(c_list, n_list)
print(m)
print(long_to_bytes(gmpy2.iroot(m, 17)[0]))
#flag{d0_n0t_sh0ut_loud1y_1n_th3_d4rk_f0r3st}

  • 21
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值