2023 红明谷杯 --- Crypto It Takes Two! wp

题目

from sage.all import *
from Crypto.Util.number import *
from os import urandom
from secret import flag

n = 16
bound = 2^15

A = [ZZ.random_element(-bound, bound) for _ in range(n*n)]
A = Matrix(ZZ, n, n, A)
        
B = [ZZ.random_element(-bound, bound) for _ in range(n*n)]
B = Matrix(ZZ, n, n, B)

res = []
for i in range(5):
    bound = 2^15
    S = [ZZ.random_element(-bound, bound) for _ in range(n*n)]
    S = Matrix(ZZ, n, n, S)
    
    tmp = []
    for i in range(0, 60):
        S = S*A+B
        bound = 2^(int(S[0, 0]).bit_length())
        if i % 3 == 2:
            tmp.append(Matrix(ZZ,n,n,[ZZ.random_element(-bound, bound) for _ in range(n*n)]))
            continue
        tmp.append(S)
    res.append(tmp)
    
e = A.LLL().determinant()

p = getPrime(512)
q = getPrime(512)
n = p * q
m = bytes_to_long(urandom(int(n).bit_length() // 8 - len(flag) - 1) + flag)
c = pow(m, e, n)
h1 = pow(p+q, e, n)
h2 = pow(p-q, e, n)

f = open('双人成行.txt', 'w')
f.writelines(str(res)+'\n')
f.writelines(str(n)+'\n')
f.writelines(str(c)+'\n')
f.writelines(str(h1)+'\n')
f.writelines(str(h2)+'\n')
f.close()

过程分析

A和B是固定的,五轮大循环,每一轮循环会生成随机矩阵S,然后进行60次循环 S = S ∗ A + B S = S*A+B S=SA+B,每三次循环中,第2次会生成一个新的n*n随机矩阵,否则使用更新后的S矩阵。这部分和LCG类似,我们可以通过两组LCG数据来计算出A,模3为2的矩阵不能取,所以我们取 S 0 , S 1 , S 3 , S 4 S_0,S_1,S_3,S_4 S0,S1,S3,S4,计算A,进而获得e。
S 1 = S 0 ∗ A + B S_1 = S_0*A+B S1=S0A+B
S 4 = S 3 ∗ A + B S_4 = S_3*A+B S4=S3A+B
两式相减
S 4 − S 1 = ( S 3 − S 0 ) ∗ A S_4-S_1 = (S_3-S_0)*A S4S1=(S3S0)A
⇒ A = ( S 4 − S 1 ) ∗ ( S 3 − S 0 ) − 1 \Rightarrow A = (S_4-S_1)*(S_3-S_0)^{-1} A=(S4S1)(S3S0)1
此时得到e是奇数
另外一部分是二项式展开
h 1 ≡ ( p + q ) e   m o d   n ≡ p e + q e   m o d   n h_1 \equiv (p+q)^e \space mod \space n \equiv p^e+q^e \space mod \space n h1(p+q)e mod npe+qe mod n
h 2 ≡ ( p − q ) e   m o d   n ≡ p e − q e   m o d   n h_2 \equiv (p-q)^e \space mod \space n \equiv p^e -q^e \space mod \space n h2(pq)e mod npeqe mod n
两式相加
h 1 + h 2 ≡ 2 ∗ p e   m o d   n h_1+h_2 \equiv 2*p^e \space mod \space n h1+h22pe mod n
发现h1+h2与n存在最大公约数p,进而求得
p = g c d ( h 1 + h 2 , n ) p = gcd(h_1+h_2,n) p=gcd(h1+h2,n)
经过计算e和phi不互素,且gcd(e,phi)=21,直接对解出的m开21次方未得到flag,显然经过padding后的m,其 m 21 = c m^{21}=c m21=c大于n,于是我们转换到有限域下对c开方,然后CRT组合一下得到flag.

PS:出题人我真是谢谢你嗷,所有矩阵append到一个列表里面,找矩阵还得小半天!!!

解题代码

from Crypto.Util.number import *
import gmpy2

s0 = 
s1 = 
s3 = 
s4 = 

s0=matrix(s0)
s1=matrix(s1)
s3=matrix(s3)
s4=matrix(s4)
A=((s3-s0)^-1)*(s4-s1)
e = A.LLL().determinant()
n = 126930298936285661712486297662920895162569606037310367763354747221281175771655642407136326621695910623038808779778530112406355314071209370688157872928010633181351390724545013677593062556323119308457918805555312069055604237211117650220178416298165021603211366843640334616217695418858036626587483782452105122653
c = 113627841667808982839757084973426219545127121566516056267404541633803040730885409234473068650543791446730694746311695177758797711077000091232969424826171863685060090359260225102836081852105845748467870581394884564134418376982186965340367386781824886506478939204791426457255483148486730526127180397268053506840
h1 = 87021607670080656750728189202811647321664825322085967432146885995538140004901574830625347954724344331514731852873721100175299656618161173874818773415684739773055620673258848991693719847569489515642296650035465632567910004553054397894647697286044465567405142149926303968235362573821060105908856127568162452912
h2 = 70528801000055618659638315463133504198238507722722570127215098017082205934290867816695737682738831717228470799826957490782948760796844881508632060312080331264474968266753069687287034453036854258618280625776346633340081217397502423530180647548747144401922660710323623212890923488339464759360304751017490144695
p = gmpy2.gcd(h1+h2,n)
q = n//p
phi = (p-1)*(q-1)
t = gmpy2.gcd(gmpy2.mpz(e),int(phi))
d = gmpy2.invert(e//t,int(phi))
m = pow(c,d,n)

R.<x> = Zmod(p)[]
f = x^t-m
f = f.monic()
results1 = f.roots()

R.<x> = Zmod(q)[]
f = x^t-m
f = f.monic()
results2 = f.roots()

for i in results1:
    for j in results2:
        param1 = [int(i[0]),int(j[0])]
        param2 = [p,q]
        M = CRT_list(param1,param2)
        flag = long_to_bytes(int(M))
        if b'flag' in flag:
            print(flag)
            break

flag:

flag{5a6814eb-8848-11ed-aee3-d812656dd8d8}

【我认为真正的爱情应该是一种小型共产主义,我是奉献但不是付出,能够不把奉献看成付出,不计较得失,便不会总是处于一种患得患失的心态,你我之间的爱情应当如此。】

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值