活到老学到老之AES加密

AES简介

AES(Advanced Encryption Standard,高级加密标准)是一种对称加密算法,广泛应用于数据加密与传输安全。AES 是美国国家标准与技术研究院(NIST)在 2001 年正式发布的标准,取代了之前的 DES(Data Encryption Standard)。

特性描述
加密方式对称加密(加密和解密使用同一个密钥)
加密算法分组加密(block cipher)
分组长度固定为 128 位(16 字节)
密钥长度128 位、192 位 或 256 位
加密轮数根据密钥长度不同,分别为 10/12/14 轮
安全性目前仍被认为是高度安全的
应用HTTPS、VPN、文件加密、磁盘加密、数据库加密等

AES原理

AES 把明文(plaintext)数据按块(block)加密,每块为 128 位(16 字节),然后执行若干轮如下操作:

  1. 字节替代(SubBytes):使用一个称为 S-Box 的替代表,对每个字节进行替换。
  2. 行移位(ShiftRows):对每行字节进行循环移位操作。
  3. 列混淆(MixColumns):在每一列内做数学变换,增加混淆。
  4. 轮密钥加(AddRoundKey):将每轮生成的密钥与当前状态进行异或操作。

每轮都会进行这些操作,最后一轮略去列混淆。

密钥扩展
AES 并不直接使用初始密钥进行每一轮加密,而是先把初始密钥扩展成多个轮密钥(Round Keys),每轮用一个。这个过程称为密钥扩展(Key Expansion)。

加密模式(Mode of Operation)
AES 本身只能加密固定长度的块(16 字节),为了解决加密多块数据的问题,引入了多种加密模式,例如:

模式描述
ECB每块独立加密,不安全,易遭重放攻击
CBC每块与前一块加密结果异或
CFB反馈方式,适合流式加密
OFB输出反馈模式,适合流式加密
CTR将计数器加密后与明文异或,支持并行
GCM加密同时提供认证(AEAD)

优点

  1. 安全性高(目前无有效破解方法)
  2. 运行速度快,适合硬件和软件实现
  3. 被广泛采用(FIPS、TLS、IPSec、Disk Encryption 等)

PKCS7

PKCS7 是一种 填充(padding)算法,常用于对称加密算法(如 AES)中,以确保明文数据的长度满足加密算法对块大小(block size)的要求。就是说PKCS7 是为了让数据长度变成块大小的整数倍而填充的一种标准方式。

PKCS7 填充规则

  1. 计算需要补多少个字节(N)使数据长度变成块大小的整数倍。
  2. 然后在数据末尾添加 N 个字节,每个字节的值都是 N。

例如:假设块大小是 16 字节,原始数据是:

"HELLO WORLD"  # 11 字节

差 5 字节才够一个完整块,所以填充:

"HELLO WORLD\x05\x05\x05\x05\x05"

每个填充字节是 \x05,表示填充了 5 个字节。
解密时,根据最后一个字节的值(比如 5),将最后的 5 个字节去掉,还原原始数据。

PKCS7 常用于AES-CBC 模式、AES-ECB 模式、其他基于块的加密算法。

业务中的加密规则

加密方法

  1. AES(设备xxx|||设备xxxx|||设备xx|||设备xxx),例如:AES(co45zjXXXXXta5ss|||bxxxxxf6da6xxxxxdbc5|||xxxxxX1100xxxxx|||1246684457)
  2. 加密KEY:设备xxx(前16字节)
  3. 对齐方法:PKCS7
  4. 加密模式:CBC
  5. 初始化向量:xxx

代码实现

安装pycryptodome库

pip install pycryptodome
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
import base64
import time


def aes_crypt(xxx, xxxx, xx, random_num, xxx):
    plaintext = f"{xxx}|||{xxxx}|||{xx}|||{random_num}"
    plaintext_bytes = plaintext.encode('utf-8')

    padded_data = pad(plaintext_bytes, AES.block_size)

    key = xxx[:16].encode('utf-8')
    iv = xxx

    cipher = AES.new(key, AES.MODE_CBC, iv)
    ciphertext = cipher.encrypt(padded_data)

    encoded = base64.b64encode(ciphertext).decode('utf-8')

    return encoded

if __name__ == '__main__':
    xxx = "6xxxxxA7B1E7xxxx"
    xxxx = "gxxxxx63416S7xxxxx44A9BFE6xxxx"
    xx = "Cxxxxx12006xxxx"
    random = str(int(time.time()))
    xxx = "rApXXXXXfkGg55RXXXXXoL9238XXXXXH"

    encrypt_data = aes_crypt(xxx, xxxx, xx, random, xxx)

    print(encrypt_data)
    print(random)
plaintext_bytes = plaintext.encode('utf-8')
  • 将字符串 plaintext 转换成字节数据(bytes 类型)才能进行加密。
  • 加密算法只能处理字节(bytes),不能加密字符串。
  • 转换后就变成这样:
b'6xxxxxA7B1E7xxxx|||gxxxxx63416S7xxxxx44A9BFE6xxxx|||Cxxxxx12006xxxx|||1652731469'
padded_data = pad(plaintext_bytes, AES.block_size)
  • 对字节数据进行 PKCS7 填充(padding),确保数据长度是 AES 所需的16 字节的倍数。
  • AES 是分组加密算法,一次只能加密 16 字节。如果不够,需要补齐。
  • pad() 是来自 Crypto.Util.Padding 的函数。
  • 例如:原始字节长度:73,加密需要的长度:80(下一个 16 的倍数),就会补 7 个字节,每个字节的值是 07(十六进制)
key = xxx[:16].encode('utf-8')
  • 将原始密钥(key)取前 16 个字符,然后转为 UTF-8 编码的字节串,作为 AES 加密的密钥。
  • AES 加密要求密钥长度必须是 16、24 或 32 字节(分别对应 AES-128、AES-192、AES-256)。
  • 如果原来的 key 比较长,这里只取了前 16 个字符。
  • encode(‘utf-8’) 是将字符串转为 bytes 类型,因为 AES 库要求输入是 bytes。
iv = xxx
  • 设置初始化向量(IV),这里只示意说一下,业务中的初始化向量就不说了,用于 CBC 模式。
  • iv 是 CBC 模式下用来打乱加密结果的一个初始向量,长度必须是 16 字节。
cipher = AES.new(key, AES.MODE_CBC, iv)
  • 使用 AES 创建一个 加密器对象,选择的加密模式是 CBC 模式。
  • AES.new(…) 创建一个 AES 加密器。
  • AES.MODE_CBC 是密码块链接模式,适用于加密多块数据,安全性好于 ECB。
ciphertext = cipher.encrypt(padded_data)
  • 将原始明文数据(必须是 16 的倍数长度)加密成密文。
  • padded_data 是明文数据,已经填充好到 16 字节倍数。
  • encrypt() 方法会将其加密,返回 ciphertext(密文),类型为 bytes。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值