1.XR4
1 | import base64 |
类似RC4的流密码,解密思路是用密钥XR4
解密密文MjM184anvdA=
还原出随机数种子,用来重置随机数生成器,再恢复矩阵,最后生成随机数流逐位异或就能得到答案,exp
1 | import base64 |
flag{c570ee41-8b09-11ef-ac4a-a4b1c1c5a2d2}
2.essential
1 | from Crypto.Util.number import * |
套层皮的RSA,crypto01计算的是
crypto02计算的是
crypto03计算的是
crypto05计算的是
这里给出了
,注意到a就512位,且
1 | def find_a(n): |
有了p,q之后就是很基础的RSA解明文了,注意到e与phi不互素,但是gcd很小,先试着用e//2算,实在不行再尝试有限域开根,所幸这里直接就算出来了,exp
1 | p = 102397419546952293033860597727650152144175130286102358700580521651161981691864932442389800376284315897109792547767071136122457986326994452907466660551539601 |
flag{75811c6d95770d56092817b75f15df05}
3.EZ-calculate
1 | from Crypto.Util.number import * |
part1
RSA,题目给出的是
这里我们的思路是枚举k的取值,计算出pow(e,k,n)之后用p2来除它,得到P,那么由二项式定理
上下相加,容易得到
同样的方法我们也能枚举出q,再用位数和正负号作为制约就能爆破出p,q的值,脚本如下
1 | problem1 = 24819077530766367166035941051823834496451802693325219476153953490742162231345380863781267094224914358021972805811737102184859249919313532073566493054398702269142565372985584818560322911207851760003915310535736092154713396343146403645986926080307669092998175883480679019195392639696872929250699367519967334248 |
然后这里e是65536,不和phi互素,gcd是4,就考虑有限域开根然后用crt算可能的解了,脚本如下
1 | from Crypto.Util.number import * |
不过跑出来b’CRYPTO_ALGORIT’就是第一个,有可能开根也能做呢
part2
背包加密,不过该给的都给了,按照加密过程反过来写很快就能搞出来
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54from Crypto.Util.number import long_to_bytes
import math
# 已知参数
R = [10, 29, 83, 227, 506, 1372, 3042, 6163]
A = 1253412688290469788410859162653
B = 16036
M = [10294, 12213, 10071, 4359, 1310, 4376, 7622, 14783]
S_list = [13523, 32682, 38977, 44663, 43353, 31372, 17899, 17899, 44663, 16589, 40304, 25521, 31372]
def backpack_decrypt(S_list, A, B, M):
# 1. 验证A与B互质
assert math.gcd(A, B) == 1, "A and B must be coprime"
# 2. 计算A的模逆元
inv_A = pow(A, -1, B)
# 3. 恢复超递增序列R
R_recovered = [(m * inv_A) % B for m in M]
print("恢复的R:", R_recovered) # 应等于原始R
# 4. 解密每个S值
bits = []
for S in S_list:
# 将S转换为超递增背包问题
S_prime = (S * inv_A) % B
# 贪心算法解背包
group = []
remaining = S_prime
for r in reversed(R_recovered):
if remaining >= r:
group.append(1)
remaining -= r
else:
group.append(0)
bits.extend(group[::-1]) # 反转后加入
# 5. 转换二进制为字节
bytes_data = b''
for i in range(0, len(bits), 8):
byte_bits = bits[i:i+8]
if len(byte_bits) < 8:
byte_bits += [0]*(8 - len(byte_bits))
byte = int(''.join(map(str, byte_bits)), 2)
bytes_data += bytes([byte])
# 6. 去除填充的零
return bytes_data.rstrip(b'\x00')
# 执行解密
flag2 = backpack_decrypt(S_list, A, B, M)
print("解密结果:", flag2.decode())
# HMS_WELL_DONE最后对两个flag拼接之后取md5,
flag{64f67374264b7621650b1de4dbc5f924}
4.merge_ECC
1 | #t.sage |
考察的是有关ECC的两种特殊攻击方法
part1
攻击的思路是Pohlig-Hellman攻击,要求是曲线的阶有小因数,这里E.order计算出来是512位,丢yafu分解之后发现有7个因子,其中5个比较小,且全部乘起来之后是比
要大的,因此我们就可以取小的5个因子来进行攻击,脚本如下 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65from sage.all import *
from Crypto.Util.number import *
n = 8186762541745429544201163537921168767557829030115874801599552603320381728161178278432652391299286759969365150578265902315058515370390070500719061057476940
print(n.bit_length())
# 2*2*5*11*499*683*124696170958113532210068667*875618937758378886905025632349007870524674918888468835522805095350653442872611049093102429356717528012933133846029979343
# 椭圆曲线参数
p = 8186762541745429544201163537921168767557829030115874801599552603320381728161132002130533050721684554609459754424458805702284922582219134865036743485620797
a = 1495420997701481377470828570661032998514190598989197201754979317255564287604311958150666812378959018880028977121896929545639701195491870774156958755735447
b = 5991466901412408757938889677965118882508317970919705053385317474407117921506012065861844241307270755999163280442524251782766457119443496954015171881396147
E = EllipticCurve(GF(p), [a, b])
# 生成元和密文点
P = E(
6053058761132539206566092359337778642106843252217768817197593657660613775577674830119685211727923302909194735842939382758409841779476679807381619373546323,
7059796954840479182074296506322819844555365317950589431690683736872390418673951275875742138479119268529134101923865062199776716582160225918885119415223226
)
cipher0 = E(
4408587937721811766304285221308758024881057826193901720202053016482471785595442728924925855745045433966244594468163087104593409425316538804577603801023861,
5036207336371623412617556622231677184152618465739959524167001889273208946091746905245078901669335908442289383798546066844566618503786766455892065155724816
)
cipher1 = E(
2656427748146837510897512086140712942840881743356863380855689945832188909581954790770797146584513962618190767634822273749569907212145053676352384889228875,
4010263650619965046904980178893999473955022015118149348183137418914551275841596653682626506158128955577872592363930977349664669161585732323838763793957500
)
cipher2 = E(
1836350123050832793309451054411760401335561429787905037706697802971381859410503854213212757333551949694177845513529651742217132039482986693213175074097638,
1647556471109115097539227566131273446643532340029032358996281388864842086424490493200350147689138143951529796293632149050896423880108194903604646084656434
)
# 已知阶的分解(排除最后两个大因子)
primes = [4, 5, 11, 499, 683] # 2^2, 5, 11, 499, 683
def pohlig_hellman(P, Q, primes):
dlogs = []
for fac in primes:
t = P.order() // fac
PP = t * P
QQ = t * Q
dlog = PP.discrete_log(QQ) # 自动选择最佳算法
dlogs.append(dlog)
print(f"Factor: {fac}, Discrete Log: {dlog}")
return crt(dlogs, primes)
# 计算三个离散对数
print("计算n0:")
n0 = pohlig_hellman(P, cipher0, primes)
print("\n计算n1:")
n1 = pohlig_hellman(P, cipher1, primes)
print("\n计算n2:")
n2 = pohlig_hellman(P, cipher2, primes)
# 验证结果
assert cipher0 == n0 * P
assert cipher1 == n1 * P
assert cipher2 == n2 * P
# 拼接结果
part1 = hex(n0)[2:] + hex(n1)[2:] + hex(n2)[2:]
print("\n解密结果:", part1)
# f61bd9f152e65acpart2
smart攻击,这里曲线计算出来阶和模数相同,脚本如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43from sage.all import *
from Crypto.Util.number import *
from gmpy2 import *
p = 839252355769732556552066312852886325703283133710701931092148932185749211043
a = 166868889451291853349533652847942310373752202024350091562181659031084638450
b = 168504858955716283284333002385667234985259576554000582655928538041193311381
E = EllipticCurve(GF(p), [a, b])
r = E.order()
# 839252355769732556552066312852886325703283133710701931092148932185749211043
print(r)
P = E(547842233959736088159936218561804098153493246314301816190854370687622130932 , 259351987899983557442340376413545600148150183183773375317113786808135411950 )
Q = E(52509027983019069214323702207915994504051708473855890224511139305828303028 , 520507172059483331872189759719244369795616990414416040196069632909579234481 )
def SmartAttack(P,Q,p):
E = P.curve()
Eqp = EllipticCurve(Qp(p, 2), [ ZZ(t) + randint(0,p)*p for t in E.a_invariants() ])
P_Qps = Eqp.lift_x(ZZ(P.xy()[0]), all=True)
for P_Qp in P_Qps:
if GF(p)(P_Qp.xy()[1]) == P.xy()[1]:
break
Q_Qps = Eqp.lift_x(ZZ(Q.xy()[0]), all=True)
for Q_Qp in Q_Qps:
if GF(p)(Q_Qp.xy()[1]) == Q.xy()[1]:
break
p_times_P = p*P_Qp
p_times_Q = p*Q_Qp
x_P,y_P = p_times_P.xy()
x_Q,y_Q = p_times_Q.xy()
phi_P = -(x_P/y_P)
phi_Q = -(x_Q/y_Q)
k = phi_Q/phi_P
return ZZ(k)
r = SmartAttack(P, Q, p)
print(r)
# 7895892011flag{f61bd9f152e65ac-7895892011}
*5.logos
2023赣政杯原题,这里是别的师傅写的博客2023赣政杯 —- Crypto_赣政杯2023-CSDN博客
还在被sagemath各种环境问题折磨,就暂时不细写了