第一次在crypto中做到tea加密的题目,在此记录一下

TEA简介:

TEA”的全称为“Tiny Encryption Algorithm”,TEA算法也叫微型加密算法

加密流程:

img

加解密代码演示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void Encrypt(long* EntryData, long* Key)
{
//分别加密数组中的前四个字节与后4个字节,4个字节为一组每次加密两组
unsigned long x = EntryData[0];
unsigned long y = EntryData[1];

unsigned long sum = 0;
unsigned long delta = 0x9E3779B9;
//总共加密32轮
for (int i = 0; i < 32; i++)
{
sum += delta;
x += ((y << 4) + Key[0]) ^ (y + sum) ^ ((y >> 5) + Key[1]);
y += ((x << 4) + Key[2]) ^ (x + sum) ^ ((x >> 5) + Key[3]);
}
//最后加密的结果重新写入到数组中
EntryData[0] = x;
EntryData[1] = y;
}

解密思路:

1
2
3
4
5
6
7
8
9
10
11
12
13
x +=xxx

y+=xxx 这两个公式总共是执行了32轮,可以记做为

(x+=xxx)32

(y+=xxx)32
那么解密的时候肯定也是执行32轮,每次递减,且顺序变换过来
(y-=xxx)
(x-=xxx)
其中这里的xxx就是异或的公式,根据其特性我们不需要改公式中的内容.我们可以看做是 a ^ b ^ c 反过来
c ^ b ^ a 是一样的.
既然倒过来了.我们的变量(黄金分割)32轮的和也要依次递减来进行解密

解密代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
void Decrypt(long* EntryData, long* Key)
{
//分别加密数组中的前四个字节与后4个字节,4个字节为一组每次加密两组
unsigned long x = EntryData[0];
unsigned long y = EntryData[1];

unsigned long sum = 0;
unsigned long delta = 0x9E3779B9;
sum = delta << 5; //注意这里,sum = 32轮之后的黄金分割值. 因为我们要反序解密.
//总共加密32轮 那么反序也解密32轮
for (int i = 0; i < 32; i++)
{

// 先将y解开 然后参与运算在解x
y -= ((x << 4) + Key[2]) ^ (x + sum) ^ ((x >> 5) + Key[3]);
x -= ((y << 4) + Key[0]) ^ (y + sum) ^ ((y >> 5) + Key[1]);
sum -= delta;
}
//最后加密的结果重新写入到数组中
EntryData[0] = x;
EntryData[1] = y;
}

例题:

newstarctf 2024 茶里茶气:

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
from Crypto.Util.number import *

flag = "flag{*****}"
assert len( flag ) == 25

a = ""
for i in flag:
a += hex(ord(i))[2:]
l = int(a,16).bit_length()
print("l =" , l )

v0 = int(a,16)>>(l//2)
v1 = int(a,16)-(v0<<(l//2))
p = getPrime(l//2+10)

v2 = 0
derta = 462861781278454071588539315363
v3 = 489552116384728571199414424951
v4 = 469728069391226765421086670817
v5 = 564098252372959621721124077407
v6 = 335640247620454039831329381071
assert v1 < p and v0 < p and derta < p and v3 < p and v4 < p and v5 < p and v6 < p

for i in range(32):
v1 += (v0+v2) ^ ( 8*v0 + v3 ) ^ ( (v0>>7) + v4 ) ; v1 %= p
v0 += (v1+v2) ^ ( 8*v1 + v5 ) ^ ( (v1>>7) + v6 ) ; v0 %= p
v2 += derta ; v2 %= p

print( "p =" , p )
print( "v0 =" , v0 )
print( "v1 =" , v1 )

"""
l = 199
p = 446302455051275584229157195942211
v0 = 190997821330413928409069858571234
v1 = 137340509740671759939138452113480
"""

exp:

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
from Crypto.Util.number import *

p = 446302455051275584229157195942211
v0 = 190997821330413928409069858571234
v1 = 137340509740671759939138452113480
derta = 462861781278454071588539315363
v3 = 489552116384728571199414424951
v4 = 469728069391226765421086670817
v5 = 564098252372959621721124077407
v6 = 335640247620454039831329381071
l = 199

v2 = (derta*32)%p
for i in range(32):
v2 -= derta
v0 = (v0-((v1+v2) ^ ( 8*v1 + v5 ) ^ ( (v1>>7) + v6 )))%p
v1 = (v1-((v0+v2) ^ ( 8*v0 + v3 ) ^ ( (v0>>7) + v4 )))%p
print(bin(v0)[2:])
v0_bin = bin(v0)[2:].zfill(l // 2)
print(v0_bin)
v1_bin = bin(v1)[2:].zfill(l // 2)
combined_bin = v0_bin + v1_bin
combined_hex = hex(int(combined_bin, 2))[2:]

flag = ''.join([chr(int(combined_hex[i:i+2], 16)) for i in range(0, len(combined_hex), 2)])
print(flag)