常见的加密方式
AES加密解密注意事项
AES加密需要:明文 + 密钥+ 偏移量(IV)+密码模式(算法/模式/填充) AES解密需要:密文 + 密钥+ 偏移量(IV)+密码模式(算法/模式/填充)
AES加密模式
- 电码本模式(ECB)(不需要偏移量)
- 密码分组链接模式(CBC)
- 计算器模式(CTR)
- 密码反馈模式(CFB)
- 输出反馈模式(OFB)
AES的工作流程
AES的原理
AES算法通过多轮次的置换-置换网络(SPN)结构来实现加密过程。每轮操作包括字节替换(SubBytes)、行移位(ShiftRows)、列混合(MixColumns)和添加轮密钥(AddRoundKey)四个步骤。这些步骤的组合使得AES算法能够有效地混淆和扩散输入数据,从而生成难以破解的密文。
AES的密钥
-
AES支持多种密钥长度,最常见的是128位、192位和256位。密钥长度越长,加密强度越高,相应地,计算资源消耗也会增加。在实际应用中,通常需要根据数据的重要性和安全需求选择合适的密钥长度。2.1 密钥扩展AE
-
算法的第一步是密钥扩展。在这一步中,算法将输入的密钥(可以是128位、192位或256位)扩展成多个轮密钥。这些轮密钥将在后续的加密轮次中使用。密钥扩展过程确保了每轮加密都使用不同的密钥,从而增强了算法的安全性。
-
三、密钥长度 只能是128、192或256位。 128位对应16个字节(8位一个字节)、192位对应24个字节、256位对应32个字节;位数越高加密强度越大, 但加密效率越低。
128:aaaaaaaaaaaaaaaa 192:aaaaaaaaaaaaaaaacccccccc 256:aaaaaaaaaaaaaaaabbbbbbbbbbbbbbbb
AES的填充
因为AES的块大小是固定的16字节,RSA的块大小根据密钥长度和填充方式而定。由于AES每次只能处理固定长度的数据(即一个块大小),当数据大小不是块大小的整数倍时,就需要对原始数据进行填充,因此填充对AES来说是技术原理上的需求。因为无法保证数据一定是对齐的。以下是其填充方式
- PKCS7(Padding Cryptography System 7)填充:在明文末尾添加填充字节,填充字节的值等于需要填充的字节数。
- PKCS5(Padding Cryptography System 5)填充:与PKCS7填充类似,但用于8字节分组的加密算法。
- NoPadding填充:不进行任何填充,要求明文长度必须是分组长度的整数倍。
利用python写aes加密
密码分组链接模式(CBC)
from Crypto.Cipher import AES
password = b'1234567812345678' #秘钥,b就是表示为bytes类型(密钥必须是16字节)
iv = b'1234567812345678' # iv偏移量,bytes类型(偏移量必须是16字节)
text = bytes('你好吗',encoding='utf-8') #需要加密的内容,bytes类型(一个汉字由多个字节组成,故须先转化成字节,进行填充)
a=16-len(text)%16
text=text+bytes(chr(a)*a,encoding='utf-8')
aes = AES.new(password,AES.MODE_CBC,iv) #创建一个aes对象
# AES.MODE_CBC 表示模式是CBC模式
en_text = aes.encrypt(text)
print("密文:",en_text) #加密明文,bytes类型
aes = AES.new(password,AES.MODE_CBC,iv) #CBC模式下解密需要重新创建一个aes对象
den_text = aes.decrypt(en_text)
print("明文:",str(den_text,'utf-8'))
电码本模式(ECB)(不需要偏移量)
from Crypto.Cipher import AES
password = b'1234567812345678' #秘钥,b就是表示为bytes类型
iv = b'1234567812345678' # iv偏移量,bytes类型
text = bytes('你好吗',encoding='utf-8') #需要加密的内容,bytes类型
a=16-len(text)%16
text=text+bytes(chr(a)*a,encoding='utf-8')
aes = AES.new(password,AES.MODE_ECB) #创建一个aes对象
# AES.MODE_CBC 表示模式是CBC模式
en_text = aes.encrypt(text)
print("密文:",en_text) #加密明文,bytes类型
aes = AES.new(password,AES.MODE_ECB) #CBC模式下解密需要重新创建一个aes对象
den_text = aes.decrypt(en_text)
print("明文:",str(den_text,'utf-8'))
利用js写aes加密
const **CryptoJS**=require("crypto-js")
function getAesString(data, key, iv) { //加密
let keys = **CryptoJS**.enc.Utf8.parse(key)
let vis = **CryptoJS**.enc.Utf8.parse(iv)
let encrypt = **CryptoJS**.AES.encrypt(data, keys, {
iv: vis, //iv偏移量 CBC需加偏移量
mode: **CryptoJS**.mode.CBC, //CBC模式
// mode: CryptoJS.mode.ECB, //ECB模式
padding: **CryptoJS**.pad.Pkcs7 //padding处理
});
// debugger
return encrypt.toString(); //加密完成后,转换成字符串
}
function getDAesString(encrypted, key, iv) { // 解密
var key = **CryptoJS**.enc.Utf8.parse(key);
var iv = **CryptoJS**.enc.Utf8.parse(iv);
var decrypted =**CryptoJS**.AES.decrypt(encrypted,key,{
iv:iv,
mode:**CryptoJS**.mode.CBC,
padding:**CryptoJS**.pad.Pkcs7
});
return decrypted.toString(**CryptoJS**.enc.Utf8);
}
/*
// AES 对称秘钥加密
const aes = {
en: (data, key) => getAesString(data, key.key, key.iv),
de: (data, key) => getDAesString(data, key.key, key.iv)
};
扩展利用CryptoJS进行其他的加密
// BASE64
const base64 = {
en: (data) => CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(data)),
de: (data) => CryptoJS.enc.Base64.parse(data).toString(CryptoJS.enc.Utf8)
};
// SHA256
const sha256 = (data) => {
return CryptoJS.SHA256(data).toString();
};
// MD5
const md5 = (data) => {
return CryptoJS.MD5(data).toString();
};