DES

[ACTF新生赛2020]crypto-des

encryptedkey.txt

1
2
3
4
5
6
7
72143238992041641000000.000000,
77135357178006504000000000000000.000000,
1125868345616435400000000.000000,
67378029765916820000000.000000,
75553486092184703000000000000.000000,
4397611913739958700000.000000,
76209378028621039000000000000000.000000

hint.txt

1
To solve the key, Maybe you know some interesting data format about C language?

附件1考的是数据在内存中的存储,我们用struct库中的pack函数打包数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
from libnum import*
import struct
import binascii

s = [72143238992041641000000.000000,77135357178006504000000000000000.000000,1125868345616435400000000.000000,67378029765916820000000.000000,75553486092184703000000000000.000000,4397611913739958700000.000000,76209378028621039000000000000000.000000]
a = ''
b = ''
for i in s:
i = float(i)
a += struct.pack('<f',i).hex() #小端
print(a)

for j in s:
i = float(i)
b += struct.pack('>f',i).hex() #小端
print(b)

a = 0x496e74657265737472696e67204964656120746f20656e6372797074
b = 0x74707972747079727470797274707972747079727470797274707972
print(n2s(a))
print(n2s(b))

我们得到压缩包密码为

1
Interestring Idea to encrypt

得到一个加密文件,密钥都给出来了,直接base64解码后,decrypt()解密就行了。

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
import pyDes
import base64
from Crypto.Util.number import*
deskey = "********"
DES = pyDes.des(deskey)
DES.setMode('ECB')
DES.Kn = [
[1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0],
[1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0],
[0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0],
[1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1],
[0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1],
[0, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0],
[0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0],
[0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0],
[1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0],
[0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0],
[0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1],
[0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0],
[1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0],
[1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1],
[1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1],
[1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1]
]
# cipher_list = base64.b64encode(DES.encrypt(flag))

k = b'vrkgBqeK7+h7mPyWujP8r5FqH5yyVlqv0CXudqoNHVAVdNO8ML4lM4zgez7weQXo'
data = base64.b64decode(k)
# print(data)
flag = DES.decrypt(data)
print(flag)

AES

加密模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
ECB模式(电子密码本模式:Electronic codebook)
  ECB是最简单的块密码加密模式,加密前根据加密块大小(如AES为128位)分成若干块,之后将每块使用相同的密钥单独加密,解密同理。

CBC模式(密码分组链接:Cipher-block chaining)
  CBC模式对于每个待加密的密码块在加密前会先与前一个密码块的密文异或然后再用加密器加密。第一个明文块与一个叫初始化向量的数据块异或
  CBC加密:https://www.cnblogs.com/phoenixy/p/15793339.html

CTR模式(计数器模式)
  CTR模式是一种通过将逐次累加的计数器进行加密来生成密钥流的流密码。自增的算子用密钥加密之后的输出和明文异或的结果得到密文,相当于一次一密。
  这种加密方式简单快速,安全可靠,而且可以并行加密,但是在计算器不能维持很长的情况下,密钥只能使用一次。

CFB模式(密文反馈:Cipher feedback)
  与ECB和CBC模式只能够加密块数据不同,CFB能够将块密文(Block Cipher)转换为流密文(Stream Cipher)

OFB模式(输出反馈:Output feedback)
  OFB是先用块加密器生成密钥流(Keystream),然后再将密钥流与明文流异或得到密文流,解密是先用块加密器生成密钥流,再将密钥流与密文流异或得到明文,由于异或操作的对称性所以加密和解密的流程是完全一样的。

AES在python中的加密限制:

1.在python中进行AES加密解密时,所传入的密文,明文,密钥,iv偏移量,都是需要bytes类型的数据。python在构建aes对象时也只能接受bytes类型数据

2.当密钥,iv偏移量,待解密的明文,字节长度不够16字节或者16字节的背书时需要进行补全

3.CBC模式需要重新生成AES对象,为了防止这类错误,我们写代码无论什么模式都要重新生成AES对象

  • python中bytes类型数据与中文的转换。Tips:utf8一个中文三个字节,gbk一个中文两个字节。

  • key = "中文数据"   #中文数据
    key_b = key.encode()  #转换成字节型数据
    print(key_b)
    print(key_b.decode()) #字节型数据转换成中文数据
    
    
    1
    2
    3
    4
    5
    6
    7



    #### [ACTF新生赛2020]crypto-aes

    我们来看题目

from Cryptodome.Cipher import AES
import os
import gmpy2
from flag import FLAG
from Cryptodome.Util.number import *

def main():
key = os.urandom(2) * 16 # 生成一个随机的密钥,长度为32字节(256位) 前16位和后16位相同
iv = os.urandom(16) # 生成一个随机的初始化向量,长度为16字节(128位)
print(bytes_to_long(key) ^ bytes_to_long(iv)) # 将密钥和初始化向量转换为长整数,并执行异或操作,然后打印结果
aes = AES.new(key, AES.MODE_CBC, iv) # 使用密钥、模式(CBC)和初始化向量创建一个新的AES加密对象
enc_flag = aes.encrypt(FLAG) # 使用AES加密对象对FLAG进行加密,并将加密后的结果存储在enc_flag变量中
print(enc_flag) # 打印加密后的FLAG

if name == “main“:
main() # 如果当前模块是主模块,则调用main函数

1
2
3
4
5
6
7
8
9
10
11

代码最后输出了两个值,应该key和iv(偏移量)xor的结果,应该enc_flag也就是key和iv利用aes的CBC模式加密后的结果

这边可以观察到,它的key是随机生成了16字节的值,然后*2变成32字节的。其实也就是说key的高位128位和低位128位是相同的

iv是16字节的,也就是128位,那么去计算key和iv的异或时,其实key仅有低位参与了异或运算,高位相当于没变。这里也就有了解题思路,

在原题的加密文件aes.py中key和iv仅异或了低16字节,key的高16字节是不变的,所有由aes.py中key是生成来看解题思路,获取了key的高16字节,便获取了key的256位。(因为aes.py中是*2)

通过key的低位与xor的低位进行异或得到的结果就是aes.py中的iv

from Cryptodome.Cipher import AES
import os
from gmpy2 import*
from Cryptodome.Util.number import*

xor = 91144196586662942563895769614300232343026691029427747065707381728622849079757
enc_flag = b’\x8c-\xcd\xde\xa7\xe9\x7f.b\x8aKs\xf1\xba\xc75\xc4d\x13\x07\xac\xa4&\xd6\x91\xfe\xf3\x14\x10|\xf8p’
out = long_to_bytes(xor) #将异或的数值转换为字节型数据
key = out[:16]*2 #取了之前加密key和iv的异或的前16字节,相当于取了高位的128位。

iv = bytes_to_long(key[16:])^bytes_to_long(out[16:]) #此时取了key的后16位与xor的后16位进行xor来还原iv
iv = long_to_bytes(iv)
aes = AES.new(key,AES.MODE_CBC,iv)
flag = aes.decrypt(enc_flag)
print(flag)

1

//验证 key = out[:16]*2
from Cryptodome.Cipher import AES
import os
from gmpy2 import *
from Cryptodome.Util.number import *

xor = 91144196586662942563895769614300232343026691029427747065707381728622849079757
out = long_to_bytes(xor) # 将异或的数值转换为字节型数据
key = out[:16] * 2
print(bin(bytes_to_long(key)))
print((bin(bytes_to_long(out[:16]))))
print(“0b11001001100000011100100110000001110010011000000111001001100000011100100110000001110010011000000111001001100000011100100110000001”)