DES
属于对称密码算法中的分组加密算法
密钥:**8个字节共64位的工作密钥,但只有56位参与运算,其余8位为校验位(8,16,24,32,40,48,56,64)不参与运算,且最后生成的密钥为48位
明文:8个字节共64位的需要被加密的数据。
密文:8个字节共64位的需要被解密的数据。
明文加密过程:
IP置换:按照一定的规律,将原来的64位2进制位重新排序
E盒扩展:将32位输入扩展为48位输出(左右两边各扩一列,左边列数等于第一列减一,右边列数等于第四列j加一,注意:第一个数和最后一个数扩出来的有点变化)
异或:将E盒扩展的数与当前轮数的密钥进行异或
S盒压缩:将异或后的48位分成8行*6列,把每一行取出来,将一行的第一个数和最后一个数组成一个二进制,化成10进制后就是得到的行数,中间的四个数组成一个二进制,化成10进制后就是得到的列数
共8个表,哪一行化出来的行数和列数就在哪张表查,将最终得到的10进制化作二进制就是压缩后的结果
例如:第一行的111111,在第一张表的第3行第15列,为13,二进制为1103
P置换:跟P置换差不多
密钥ki生成过程:
先将64位密钥除去8位校验位后进行pc-1置换,得到56位密钥,将56位密钥排成8*7的表,取出前四行为C,后四行为D,将每四行按顺序排成一行进行循环左移,每一轮完成后再重新排成8*7的表,经过以下的pc-2盒的置换得到每一轮的密钥
[ACTF新生赛2020]crypto-des
encryptedkey.txt
1 | 72143238992041641000000.000000, |
hint.txt
1 | To solve the key, Maybe you know some interesting data format about C language? |
附件1考的是数据在内存中的存储,我们用struct库中的pack函数打包数据
1 | from libnum import* |
我们得到压缩包密码为
1 | Interestring Idea to encrypt |
得到一个加密文件,密钥都给出来了,直接base64解码后,decrypt()解密就行了。
1 | import pyDes |
AES
加密模式
1 | ECB模式(电子密码本模式:Electronic codebook) |
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 |
|
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”)