对称密码——AES

一、算法(Rijndael)

AES 属于分组加密算法
明文长度固定为128位(16字节)
密钥长度可以是128(循环10次)、192(循环12次)、256位(循环14次)

二、加密

输入明文和密钥的字节顺序:

12345678910111213141516

规定字节的排列方式:

15913
261014
371115
481216

总加密过程:

注意:第十轮(最终轮)循环运算中没有列混合

分步加密:

1.初始变换:

明文矩阵和子密钥矩阵进行异或

2.字节代换

字节代换是非线性变换,独立地对状态的每个字节进行。代换表(S-Box)是可逆的。
相当于明文在s盒中进行行列的映射。

S盒

eg:

19

a0

9ae9d4e0b81e
3df4c6f827bfb441
e3e28d4811985d52
be2b2a08aef1e530

说明:19代表第一行第九列,在S盒中对应0*d4;3d代表第三行第d列,在S盒中对应0*27······以此类推。

  3.行移位

eg:

d4e0b81ed4e0b81e
27bfb441bfb44127
11985d525d521198
aef1e53030aef1e5

4.列混合

将输⼊的4*4的矩阵左乘⼀个规定的4*4正矩阵

eg:

02030101d404
01020301*bf=66
010102035d81
0301010230e5

5.轮密钥加

6.轮密钥的生成

w[0]

w[1]

w[2]w[3]w[4]w[5]w[6]w[7]
2b28ab09
7eaef7cf
15d2154f
16a6883c

1.密钥扩展(i不是4的倍数)

w[i]=w[i-4]\oplus w[i-1]

w[5]=w[1]\oplus w[4], w[6]=w[2]\oplus w[5], w[7]=w[3]\oplus w[6]

2.密钥扩展(i是4的倍数)

w[i]=w[i-4]\oplus T(w[i-1])

w[4]=w[0]\oplus T(w[3])

T函数由3部分组成:字循环,字节代换和轮常量异或。

a.字循环:将w[3]中的4个字节循环左移1个字节。即,将输入字[k1,k2,k3,k4]变换成
[k2,k3,k4,k1].

09cf
cf4f
4f3c
3c09

b.字节代换:对字循环的结果使用s盒进行字节代换

cf8a
4f84
3ceb
0901

c.轮常量异或:将前两步的结果同轮常量Rcon[j]进行异或,其中j表示轮数。

轮常量异或表
01020408102040801b36
00000000000000000000
00000000000000000000
00000000000000000000

得到T(w[3]),最后再和W[0]异或

 最终通过计算生成10轮密钥

7.python脚本实现

在Python中,可以使用pycryptodome库来实现AES加密。pycryptodomePyCrypto的一个分支,提供了更全面的加密算法支持。

安装pycryptodome

首先,需要安装pycryptodome库。

案例一:使用CBC模式和PKCS#7填充
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
from Crypto.Random import get_random_bytes
import base64

# 生成随机的密钥(必须是16、24或32字节)
key = get_random_bytes(16)

# 生成随机的初始化向量(IV),AES块大小为16字节
iv = get_random_bytes(AES.block_size)

# 明文数据
plain_text = "Hello, AES Encryption!".encode('utf-8')

# 使用PKCS#7填充明文数据到AES块大小的倍数
padded_data = pad(plain_text, AES.block_size)

# 创建AES加密器,使用CBC模式和之前生成的密钥及IV
cipher = AES.new(key, AES.MODE_CBC, iv)

# 加密填充后的数据
encrypted_data = cipher.encrypt(padded_data)

# 将IV和密文拼接,然后Base64编码以便于存储或传输
cipher_text_str = base64.b64encode(iv + encrypted_data).decode('utf-8')

print("加密后的数据:", cipher_text_str)

# 解密过程
# 创建相同的AES解密器
decrypt_cipher = AES.new(key, AES.MODE_CBC, iv)

# 解密数据
decrypted_padded_data = decrypt_cipher.decrypt(encrypted_data)

# 去除填充
decrypted_text = unpad(decrypted_padded_data, AES.block_size)

print("解密后的数据:", decrypted_text.decode('utf-8'))

输出结果:

加密后的数据: UYQTIYCyXTclVckVAmQH3VjWjfZLhblZGNTkNe2CSIrxBwcbXRutES9I+Elid4Hj
解密后的数据: Hello, AES Encryption!

3、案例二:使用ECB模式和自定义填充

注意:ECB模式不推荐使用于加密长数据或敏感数据,因为它不使用IV且相同的明文块会产生相同的密文块。

from Crypto.Cipher import AES
import base64
from Crypto.Random import get_random_bytes
 
# 生成随机的密钥(必须是16、24或32字节)
key = get_random_bytes(16)
 
# 明文数据
plain_text = "ECB模式进行AES加密".encode('utf-8')
 
 
# 自定义填充函数(这里使用简单的'X'字符填充)
def custom_pad(s, block_size=AES.block_size):
    pad_len = block_size - len(s) % block_size
    return s + b'h' * pad_len
 
 
# 加密
cipher = AES.new(key, AES.MODE_ECB)
padded_data = custom_pad(plain_text)
encrypted_data = cipher.encrypt(padded_data)
 
# Base64编码
cipher_text_str = base64.b64encode(encrypted_data).decode('utf-8')
 
print("加密后输出:", cipher_text_str)
 
# 解密(同样需要自定义填充)
decrypted_data = cipher.decrypt(encrypted_data)
# 去除填充(注意:这里需要知道填充的规则)
decrypted_text = decrypted_data.rstrip(b'h').decode('utf-8')
 
print("解密后输出:", decrypted_text)

输出结果:

加密后输出: ZYUTsU3bZdWF7pq4pFA1J/mbR4DRLMHUMcoOYhODcNM=
解密后输出: ECB模式进行AES加密

3、案例三:使用GCM模式

GCM(Galois/Counter Mode)是一种结合了CTR模式和GHASH(Galois Hash)的认证加密模式,它提供了数据的机密性和完整性保护。

from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
from Crypto.Util.Padding import pad
import base64
 
# 生成随机的密钥(对于AES-GCM,推荐使用128位(16字节)或256位(32字节)的密钥)
key = get_random_bytes(32)  # 生成一个32字节(256位)的密钥
 
# 生成随机的nonce(GCM中的IV被称为nonce,不需要保密,但必须确保唯一)
nonce = get_random_bytes(16)  # 生成一个16字节的nonce
 
# 明文数据
plain_text = "AES-GCM加密!".encode('utf-8')
 
# AES-GCM不需要传统的填充,但我们可以使用pad函数以确保与可能的其他加密模式兼容(尽管在这里是多余的)
# 注意:对于GCM,实际上应该直接加密原始明文,不需要填充
# 这里为了展示pad函数的使用(虽然在这个上下文中是多余的),我们还是使用它
padded_data = pad(plain_text, AES.block_size)  # 但GCM模式下这步是多余的
 
# 由于GCM模式下不需要填充,我们直接加密原始明文
# 创建AES-GCM加密器
cipher = AES.new(key, AES.MODE_GCM, nonce=nonce)
 
# 加密数据并获取密文和认证标签
ciphertext, tag = cipher.encrypt_and_digest(plain_text)  # 加密明文并获取密文和GCM认证标签
 
# 通常,你会将nonce、密文和标签一起发送给接收者(或存储它们以供以后使用)
# 这里,为了简化,我们将它们Base64编码并打印出来
cipher_text_with_nonce_and_tag = base64.b64encode(nonce + ciphertext + tag).decode('utf-8')
print("加密后输出:", cipher_text_with_nonce_and_tag)
 
# 解密过程
# 接收方需要拥有相同的密钥和nonce来解密和验证密文
decrypt_cipher = AES.new(key, AES.MODE_GCM, nonce=nonce)
 
# 解密数据并验证认证标签
try:
    decrypted_text = decrypt_cipher.decrypt_and_verify(ciphertext, tag)
    print("解密后输出:", decrypted_text.decode('utf-8'))
except ValueError:
    # 如果认证标签不匹配,decrypt_and_verify将抛出一个ValueError
    print("身份验证失败!.")
 
# 注意:在实际应用中,nonce(IV)和密钥都应该安全地存储和传输
# 密钥应该保密,而nonce(IV)应该对每个加密操作都是唯一的,但不需要保密
# 认证标签(tag)是验证密文完整性和真实性的关键部分,必须随密文一起发送或存储

输出结果:

加密后输出:FwPwETBk5pxUyKPQ8iOQReBHUS2inee//aaKDlumHoj32olJRqMLTWaaWImJwQ==
解密后输出: AES-GCM加密!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值