Aes是分组加密算法,主要基于块加密,选取固定长度的密钥去加密明文中固定长度的块,生成的密文块与明文块长度一样。
AES加密模式:
Aes共五种加密模式,本文以cbc模式为列。
1.电码本模式(Electronic Codebook Book (ECB)
2.密码分组链接模式(Cipher Block Chaining (CBC))
3.计算器模式(Counter (CTR))
4.密码反馈模式(Cipher FeedBack (CFB))
5.输出反馈模式(Output FeedBack (OFB))
使用场景:
Aes加密主要使用于对数据加密后还需要通过密文解密出明文的场景,如无需解出明文的可使用安全性更高的非对称加密。
Aes对数据加密前需要先设置加密密钥,加密密钥的长度决定了暴力破解的难度,如果系统内存、性能允许,建议使用256 位以上长度的密钥进行加密。对密文解密时需要设置同样的密钥解密。
通过AES_set_encrypt_key接口可以设置加密密钥:
int AES_set_encrypt_key(const unsigned char *userKey, const int bits,
AES_KEY *key);
userKey: 密钥数值;
bits:密钥长度,以bit为单位,如果密钥数字是16个字节,则此参数值应为128;
key: AES_KEY对象指针;
返回值: 0 成功, -1 userkey,key为空, -2: 密钥长度不是128,192,256;
通过AES_set_decrypt_key设置解密密钥
int AES_set_decrypt_key(const unsigned char *userKey, const int bits,
AES_KEY *key);
userKey: 密钥数值;
bits:密钥长度,以bit为单位,如果密钥数字是16个字节,则此参数值应为128;
key: AES_KEY对象指针;
返回值: 0 成功, -1 userkey,key为空, -2: 密钥长度不是128,192,256;
Aes每次加密的内存块是16个字节,所以需要加密的内存块必须是16个字节的整数倍,若不是则需要进行补齐。ivec、usrKey可指通过函数随机生成后保存,也可以直接指定。
加密接口
void AES_cbc_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const AES_KEY *key,
unsigned char *ivec, const int enc);
解密接口
void AES_cbc_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const AES_KEY *key,
unsigned char *ivec, const int enc);
使用代码实例:
static unsigned char key[AES_BLOCK_SIZE*2] = "1wradfr4e3fefefad4545454h6thrsf";
int aes256_encrypt(char* str_in, char* out)
{
int i;
int len;
AES_KEY aes;
unsigned char iv[AES_BLOCK_SIZE] = {0};
if (!str_in || !out)
return 0;
len = strlen(str_in);
for (i = 0; i < 16; ++i)
iv[i] = i+32;
if (AES_set_encrypt_key((unsigned char*)key, 256, &aes) < 0){
return 0;
}
AES_cbc_encrypt((unsigned char*)str_in, (unsigned char*)out, len, &aes, iv, AES_ENCRYPT);
return 1;
}
int aes256_decrypt(char* str_in, char* out)
{
int i;
int len;
AES_KEY aes;
unsigned char iv[AES_BLOCK_SIZE] = {0};
if (!str_in || !out)
return -1;
len = strlen(str_in);
//确保里面的内容加密解密一样
for (i = 0; i < 16; ++i)
iv[i] = i+32;
if (AES_set_decrypt_key((unsigned char*)key, 256, &aes) < 0)
{
return -1;
}
AES_cbc_encrypt((unsigned char*)str_in, (unsigned char*)out, len, &aes, iv, AES_DECRYPT);
return 0;
}