1 简介
高级加密标准(英语:Advanced Encryption Standard,缩写:AES),在密码学中又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准
2 加密过程
AES加密数据块分组长度必须为128比特,密钥长度可以是128比特、192比特、256比特中的任意一个(如果数据块及密钥长度不足时,会补齐)。
AES加密有很多轮的重复和变换。
大致步骤如下:
1、密钥扩展(KeyExpansion),
2、初始轮(Initial Round),
3、重复轮(Rounds),每一轮又包括:SubBytes、ShiftRows、MixColumns、AddRoundKey,
4、最终轮(Final Round),最终轮没有MixColumns。
各轮AES加密循环(除最后一轮外)均包含4个步骤:
AddRoundKey — 矩阵中的每一个字节都与该次轮秘钥(round key)做XOR运算;每个子密钥由密钥生成方案产生。
SubBytes — 通过个非线性的替换函数,用查找表的方式把每个字节替换成对应的字节。
ShiftRows — 将矩阵中的每个横列进行循环式移位。
MixColumns — 为了充分混合矩阵中各个直行的操作。这个步骤使用线性转换来混合每列的四个字节。
3 加密模式
常见5种,ECB、CBC、CFB、OFB、CTR
ECB:是一种基础的加密方式,密文被分割成分组长度相等的块(不足补齐),然后单独一个个加密,一个个输出组成密文。
CBC:是一种循环模式,前一个分组的密文和当前分组的明文异或操作后再加密,这样做的目的是增强破解难度。
CFB/OFB实际上是一种反馈模式,目的也是增强破解的难度。
ECB模式加密流程:
CBC模式加密流程:
4 Openssl加密接口
AES加密接口:
//设置加密密钥,使用字符缓冲区
int AES_set_encrypt_key(
const unsigned char *userKey,
const int bits,
AES_KEY *key);
//设置解密密钥,同样适用字符缓冲区
int AES_set_decrypt_key(
const unsigned char *userKey,
const int bits,
AES_KEY *key);
//加解密的接口,通过最后的enc来区分是加密还是解密操作
//每次执行AES_cbc_encrypt后,iv(向量)会被更新,
//所以需要自己保存它。
void AES_cbc_encrypt(
const unsigned char *in,
unsigned char *out,
const unsigned long length,
const AES_KEY *key,
unsigned char *ivec,
const int enc);
EVP封装加密接口:(如果加密明文不是16的整数倍,会进行数据填充,因此如果和其他加密代码混合使用,需要特别注意)
//加密相关函数
void EVP_CIPHER_CTX_init(EVP_CIPHER_CTX *a);
int EVP_EncryptInit_ex(EVP_CIPHER_CTX *ctx,
const EVP_CIPHER *cipher,//加密算法
ENGINE *impl,
const unsigned char *key,
const unsigned char *iv);
int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx,
unsigned char *out,
int *outl,
const unsigned char *in,
int inl);
int EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx,
unsigned char *out,
int *outl);
//解密相关函数
int EVP_DecryptInit_ex(EVP_CIPHER_CTX *ctx,
const EVP_CIPHER *cipher,
ENGINE *impl,
const unsigned char *key,
const unsigned char *iv);
int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx,
unsigned char *out,
int *outl,
const unsigned char *in,
int inl);
int EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx,
unsigned char *outm,
int *outl);
5 Javascript加密脚本
Js脚本文件(需要注意js加密和C配置使用时,需要将字符串转换为ASCII进行加密,否则无法对应):
加密:AesEncrypt(plaintext, key, mode) //mode目前支持ECB、CBC
解密:AesDecrypt(ciphertext, key, mode)
数组转字符串:byteArrayToString(byteArray) //将解密后的明文数组转化为字符串
6 附件:密码加密规范