AES
属于对称加密算法
三要素:
- 秘钥
- 填充
- 模式
秘钥
对称加密之所以对称,是因为这类算法对明文的加密和解密使用的是同一个秘钥
AES 支持三种长度的秘钥:
- 128位 128的性能最好
- 192位
- 256位 256的安全性最高,加密轮数更多。
这三种不同长度的秘钥,在底层的加密过程中,处理的加密轮数不同。
填充
AES加密分组的特性:AES加密并不是将明文一股脑加密成密文,而是先拆分成一个个的独立的明文块,每个明文快块128bit。
假设一段明文块长度是192bit,按照每128bit一个明文块来拆分的话,第二个明文块只有64bit,不足128bit,此时就需要对不足128bit的明文块进行填充。
填充的 种类:
- NoPadding
不做任何填充,要求明文必须是128bit的整数倍
- PKCS7Padding
用0填充,对于末尾为0的,容易误判,从而解密出错,并不推荐
- ZeroPadding(当明文块少于16个字节,少多少个字节,就用对应数字来填充。例如,少5个,后面就是5个5,少6个,就是6个6)
1,2,3,4,5,6,2,3,4,5,4,4,4,4, # 缺4个,就用4来填充
1,2,3,4,5,6,2,3,4,5,5,5,5,5 # 缺5个,就用数字5来填充
- AnsiX923
- Iso10126
- Iso97971
模式
AES的工作模式,体现在吧明文块加密成密文块的过程中
AES算法提供了5种工作模式:
- CBC
- EBC
- CTR
- CFB
- OFB
模式之间的主体思想是近似的,在处理细节上有 一些差别。
ECB模式:
ECB(Electronic CodeBook Book) 是最简单的工作模式,在这个模式下,每个明文快的加密都是完全独立的,互不干涉。
优点:
- 简单
- 有利于并行计算
缺点:
- 相同的明文块加密后是相同明文块,安全性较差
CBC模式
CBC模式(Cipher Block Chaining)引入了一个新的概念:初始向量IV(Initialization Vector)
IV的作用类似MD5中的"加盐",目的是防止相同的明文加密成为相同的密文
CBC模式在每一个明文块加密前会让明文块和一个值先做异或操作。
IV为作为初始化变量,参与第一个明文块的异或,后续的每一个明文块和它前一个明文块加密后的密文相异或。
这样,相同明文块加密后的密文显然不一样。
优点:
- 安全性高
缺点:
- 无法并行计算,性能上不如ECB
- 引入了初始化向量IV,增加了复杂度
加密流程总结:
- 把明文按照128bit拆分成若干个明文块
- 按照选择的填充方式对最后一个明文块填充
- 每一个明文块利用AES加密器和秘钥,加密成密文块
- 拼接所有的密文快,成为最终的密文结果
示例:
var CryptoJS = require("Crypto-js");
function aesEncrypto(text, key, iv) { // 加密
key = CryptoJS.enc.Utf8.parse(key);
iv = CryptoJS.enc.Utf8.parse(iv);
var encryptoed = CryptoJS.AES.encrypt(text, key, {
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
})
var encryptoed__=CryptoJS.enc.Utf8.parse(encryptoed)
return encryptoed
}
function aesDecrypto(encryptoed, key, iv) { // 解密
key = CryptoJS.enc.Utf8.parse(key);
iv = CryptoJS.enc.Utf8.parse(iv);
var result = CryptoJS.AES.decrypt(encryptoed, key, {
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
})
return result.toString(CryptoJS.enc.Utf8)
}
var text = "wo ai python"; // 明文
var key = "ABC123456789"; // 秘钥
var iv = "hehehehehehe"; // iv
var encryptoed = aesEncrypto(text, key, iv);
console.log(encryptoed.toString());
var decod = aesDecrypto(encryptoed, key, iv);
console.log(decod);