AES(高级加密标准)是一种广泛使用的对称加密算法,用于保护数据的安全。AES支持128、192和256位的密钥长度,并提供了多种操作模式,以适应不同的安全需求和应用场景,本文将重点介绍ECB、CBC、GCM,并顺带介绍下目前应用较广得CMAC计算。
注:本文不介绍AES算法原理,感兴趣得可参考如下文章:
ECB (电子密码本)模式
AES ECB(Electronic Codebook)模式是AES(高级加密标准)算法的一种基础操作模式。在ECB模式中,明文被分成固定大小的块(对于AES,这个块大小是128位),然后每个块独立地被加密。这种模式的特点是简单和高效,但它并不提供数据的混淆,因为相同的明文块总是产生相同的密文块。
工作原理:
-
数据分块:
- 待加密的明文被分割成128位的块。如果最后一个块不足128位,通常使用特定的填充方案(如PKCS#7)来补全至128位。
-
独立加密:
- 每个128位的明文块独立地通过AES算法进行加密。加密过程涉及多轮的重复操作,包括字节替换(SubBytes)、行移位(ShiftRows)、列混淆(MixColumns)和轮密钥加(AddRoundKey)。
-
密文输出:
- 每个加密块的输出就是对应的密文块。这些块可以顺序输出,形成最终的密文。
特点:
- 简单性:ECB模式的实现非常简单,因为它不需要保存任何状态信息,每个块的加密都是独立的。
- 并行处理:由于每个块的加密是独立的,ECB模式可以并行处理多个数据块,这在多核处理器系统中可以显著提高性能。
- 无混淆:ECB模式的主要缺点是它不提供数据混淆。如果明文中有重复的模式,加密后的密文中也会有明显的模式,这可能会被攻击者利用来破解密码。
安全性:
- ECB模式的安全性相对较低,因为它容易受到模式分析攻击。如果攻击者能够识别出密文中的某些模式,他们可能推断出明文的一些信息。
应用场景:
- 由于无混淆的特点,所以不太安全,目前已不推荐使用。
python实现:
如未安装pycryptodome,需要安装pycryptodome
库,可以通过pip进行安装:
pip install pycryptodome
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
from Crypto.Random import get_random_bytes
# AES密钥长度可以是16(AES-128), 24(AES-192), 或 32(AES-256)字节
key = get_random_bytes(16) # 这里我们使用AES-128,所以密钥长度为16字节
# 创建一个新的AES cipher对象
cipher = AES.new(key, AES.MODE_ECB)
# 原始数据
plaintext = b"This is a secret message!"
# 由于AES是块密码,它只能处理固定长度的块(对于AES,这个长度是16字节)。
# 因此,我们需要对原始数据进行填充,使其长度达到块的倍数。
# pycryptodome提供了pad函数,可以自动进行填充。
padded_plaintext = pad(plaintext, AES.block_size)
# 加密数据
ciphertext = cipher.encrypt(padded_plaintext)
# 为了解密数据,我们需要再次创建一个新的AES cipher对象
decrypt_cipher = AES.new(key, AES.MODE_ECB)
# 解密数据
decrypted_padded_text = decrypt_cipher.decrypt(ciphertext)
# 删除填充
decrypted_text = unpad(decrypted_padded_text, AES.block_size)
print(f"原始数据: {plaintext}")
print(f"加密后数据: {ciphertext}")
print(f"解密后数据: {decrypted_text}")
# 输出如下
'''
原始数据: b'This is a secret message!'
加密后数据: b"rR\xc6\xd2c\x897\x00t\x8baCc\x9c\xea\xb5\xeb\xe1\x80\xc2\x86\x1f\xc4\xe4['\xaf\x9b\x03!\x07\xeb"
解密后数据: b'This is a secret message!'
'''
CBC(密码块链接)模式
AES CBC(Cipher Block Chaining)模式是AES算法中一种广泛使用的加密模式,它通过引入数据依赖性来增强安全性。在CBC模式中,每个数据块在被加密之前,会与前一个密文块进行异或操作。这种依赖性使得即使相同的明文块也会产生不同的密文块,从而隐藏了数据中的模式。
工作原理:
-
初始化向量(IV):
- CBC模式开始于一个随机生成的初始化向量(IV),它是一个128位的值,通常在密钥相同的情况下每次加密都会改变。
- IV不需要保密,但它应该被传输给解密方,并且在加密过程中不应重复使用。
-
数据分块:
- 明文被分割成128位的块。如果最后一个块不足128位,需要使用特定的填充方案(如PKCS#7)来补全至128位。
-
块间依赖:
- 第一个明文块与IV进行异或操作后,再用AES密钥进行加密,得到第一个密文块。
- 随后的每个明文块先与前一个密文块进行异或操作,然后再加密,以此类推。
-
密文输出:
- 每个经过异或和加密的块成为密文块,这些密文块顺序输出,形成最终的密文。
特点:
- 安全性:CBC模式通过引入块间依赖性,使得相同的明文块产生不同的密文块,这增加了攻击者破解密码的难度。
- 错误传播:在CBC模式中,如果一个密文块被篡改,只有该块及其后续块的解密结果会受到影响,而不会像ECB模式那样影响所有块。
解密过程:
- 解密过程与加密过程相反。每个密文块先进行解密,然后与前一个密文块(或IV)进行异或操作,以恢复原始的明文块。
应用场景:
- CBC模式因其较高的安全性,适用于多种需要加密保护的场景,包括文件加解密、网络通信加解密,例如27服务安全算法、升级文件加解密、报文传输加解密等。
注意事项:
- 必须确保每次加密都使用一个新的IV,以防止模式分析攻击。
- 在某些情况下,如果IV的保密性得不到保证,可能会降低CBC模式的安全性。
python实现:
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
from Crypto.Random import get_random_bytes
def aes_cbc_encrypt(key, plaintext):
# AES key must be either 16, 24, or 32 bytes long
if len(key) not in [16, 24, 32]:
raise ValueError("Invalid AES key size")
cipher = AES.new(key, AES.MODE_CBC)
ciphertext = cipher.encrypt(pad(plaintext, AES.block_size))
# 返回加密后的数据和初始化向量
return cipher.iv, ciphertext
def aes_cbc_decrypt(key, iv, ciphertext):
# AES key must be either 16, 24, or 32 bytes long
if len(key) not in [16, 24, 32]:
raise ValueError("Invalid AES key size")
cipher = AES.new(key, AES.MODE_CBC, iv)
plaintext = unpad(cipher.decrypt(ciphertext), AES.block_size)
return plaintext
# 示例
key = get_random_bytes(16) # 生成一个随机的16字节的AES密钥
plaintext = b"This is a secret message" # 需要加密的明文
# 加密
iv, ciphertext = aes_cbc_encrypt(key, plaintext)
print("Encrypted:", ciphertext)
# 解密
decrypted_text = aes_cbc_decrypt(key, iv, ciphertext)
print("Decrypted:", decrypted_text)
# 输出如下
'''
Encrypted: b'b\xed\tQ\x08jU\xf5\xd69\x85e\xa5!\xf3i\x17\x80\x84 :\xb1\x1b\xfe(r\x91E>!\xe3\x06'
Decrypted: b'This is a secret message'
'''
GCM(伽罗瓦/计数器)模式
AES GCM(Galois/Counter Mode)模式是一种流行的加密算法,结合了计数器模式(CTR)的并行性和密码块链接模式(CBC)的安全性。GCM模式不仅提供加密,还提供消息认证,使其成为一种认证加密(AE)模式。这种模式特别适用于处理高速网络通信中的安全问题。
工作原理:
-
密钥和IV:
- GCM模式使用一个128位、192位或256位的AES密钥,并要求一个随机生成的初始化向量(IV),通常长度为96位或128位。
-
加密过程:
- GCM模式首先生成一个密钥流,这个密钥流是通过AES密钥加密一个由计数器和IV组成的固定长度的块来得到的。
- 计数器块通常由一个递增的数字组成,用于加密每个数据块。
- 每个数据块与密钥流进行异或操作后产生密文块。
-
认证过程:
- GCM模式同时计算一个认证标签(Tag),这个标签是通过对附加的认证数据(如序列号、时间戳等)和加密后的密文块进行加密得到的。
- 认证标签与密文一起传输,接收方可以使用相同的密钥和IV重新计算认证标签,并与接收到的标签进行比较,以验证数据的完整性和认证性。
-
解密过程:
- 解密过程与加密过程类似,通过重新计算密钥流和认证标签来恢复原始数据,并验证数据的完整性和认证性。
特点:
- 并行性:GCM模式允许加密和认证过程并行执行,这使得它非常适合高速网络通信。
- 安全性:GCM模式提供了强大的安全性,包括对抗重放攻击和篡改攻击的能力。
- 灵活性:GCM模式可以处理任意长度的数据,并且不需要填充到固定块大小。
应用场景:
- GCM模式广泛应用于各种安全协议和标准中,包括无线网络安全(Wi-Fi)、IPsec VPN、TLS/SSL等。
注意事项:
- 密钥和IV的保密性对GCM模式的安全性至关重要。如果密钥或IV被泄露或重复使用,可能会降低安全性。
python实现:
from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
from Crypto.Util.Padding import pad, unpad
# 密钥长度必须是 16(AES128), 24(AES192), 或 32(AES256)字节
key = get_random_bytes(16)
# 初始化向量(IV)长度必须是 12 字节
iv = get_random_bytes(12)
# 创建一个 AES-GCM cipher 对象
cipher = AES.new(key, AES.MODE_GCM, iv)
# 要加密的数据
plaintext = b"This is a secret message."
# 加密数据
ciphertext, tag = cipher.encrypt_and_digest(pad(plaintext, AES.block_size))
# 现在,假设我们有一个接收者,他/她也有相同的密钥和 IV,并希望解密消息
# 创建一个新的 AES-GCM cipher 对象,用于解密
decipher = AES.new(key, AES.MODE_GCM, iv)
# 尝试解密数据
try:
decryptedtext = unpad(decipher.decrypt(ciphertext), AES.block_size)
# 验证消息的完整性
decipher.verify(tag)
print("Decrypted text: ", decryptedtext)
except (ValueError, TypeError):
print("Decryption failed. The message may have been tampered with.")
CMAC 介绍
AES CMAC(Cipher-based Message Authentication Code)模式是一种基于AES加密算法的消息认证码生成方法。CMAC提供了一种机制,用于验证消息的完整性和认证性,确保消息在传输过程中未被篡改,并且确实来自声称的发送者。CMAC结合了加密的安全性和消息认证码的效率。
工作原理:
-
密钥:
- CMAC使用一个AES密钥,长度可以是128位、192位或256位。
-
消息分块:
- 待认证的消息被分割成128位的块。如果消息长度不是128位的整数倍,需要进行填充。
-
CMAC计算:
- CMAC的计算涉及两个关键步骤:扩展和XOR操作。
- 首先,使用AES密钥对一个全零块进行加密,得到一个128位的值,称为K1。
- 然后,对消息的第一个128位块(或填充后的块)进行加密,得到另一个128位的值,称为K2。
- 接下来,将K2与消息块进行XOR操作,如果消息块大于128位,则继续处理下一个块。
- 这个过程重复进行,直到所有的消息块都被处理完毕。
-
最终CMAC输出:
- 最后,将所有XOR操作的结果进行累加,得到最终的CMAC值。这个值作为消息认证码,可以附在消息后面一起发送。
特点:
- 安全性:CMAC提供了消息认证,确保消息的完整性和来源的可靠性。
- 效率:CMAC的计算过程相对简单,不需要复杂的链式操作,适合于硬件和软件实现。
- 灵活性:CMAC适用于不同长度的消息,并且可以与AES的不同密钥长度配合使用。
应用场景:
- CMAC主要用于需要消息认证的场景,例如SecOC、安全启动等。
注意事项:
- 密钥的保密性对CMAC的安全性至关重要。如果密钥被泄露,CMAC提供的保护将失效。
python实现:
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
from Crypto.Hash import CMAC
# AES 密钥,长度必须是 16(AES-128), 24(AES-192)或 32(AES-256)字节
key = b'sixteen byte key'
# 要加密的消息
message = b'This is a secret message.'
# 创建一个 AES CMAC 对象
cmac = CMAC.new(key, ciphermod=AES)
# 更新 CMAC 对象,添加要验证的消息
cmac.update(message)
# 生成 CMAC 摘要
cmac_digest = cmac.digest()
print(f"CMAC Digest: {cmac_digest.hex()}")
# 如果你要验证消息的完整性,你可以重新计算消息的 CMAC,并与原始 CMAC 进行比较
# 例如,假设你收到了一条消息和一个 CMAC,你可以这样验证它们:
# 重新创建 AES CMAC 对象
new_cmac = CMAC.new(key, ciphermod=AES)
# 更新 CMAC 对象,添加接收到的消息
new_cmac.update(message)
# 生成新的 CMAC 摘要
new_cmac_digest = new_cmac.digest()
# 比较两个 CMAC 摘要是否相同
if cmac_digest == new_cmac_digest:
print("Message is authentic and intact.")
else:
print("Message is not authentic or has been tampered with.")
# 输出如下
'''
CMAC Digest: 1f358736c85072cb02b11a8f3b9cbc1e
Message is authentic and intact.
'''
附 AES加密工具
支持ECB、CBC、CMAC、GCM计算,
下载链接:AES.rar