背景:
当前开发中,lua中有需要用到aes加密的需求,底层c++是有aes模块的,但是程序一直没有用到,我修改了一番。两点:加密,解密
梳理流程:
加密:字符串输入,秘钥输入,16的倍数不足的补N(N为不足的位数,例:12个字符串,缺4个,后面4个全部补4),AES加密,加密完成,base64再加密,输出
解密:密码输入,秘钥输入,base64解密,16的倍数不足的补N(N为不足的位数,例:12个字符串,缺4个,后面4个全部补4),解密完成,处理解密后字符串中的N(从尾部开始,等于N的字符串,全部删除),输出
代码逻辑:
aes.cpp(源代码)
int AES_ECB_Cipher::encode(const unsigned char* src, uint32_t src_len, unsigned char* dest, uint32_t& len)
{
// check input null pointer
if (nullptr == src)
{
return -1;
}
// make sure dest buff is larger than src buff
if(len < src_len)
{
return -1;
}
unsigned char encode_buf[1024];
memset(encode_buf, 0, sizeof(encode_buf));
memcpy(encode_buf, src, src_len);
uint32_t encode_buf_size = src_len;
// input been padded well with pkcs5padding
uint8_t pading_size = AES_ECB_Cipher::KEYLEN - encode_buf_size % AES_ECB_Cipher::KEYLEN;
// PKCS5Padding rules: ²¹(16-len)¸ö(16-len)
for (uint8_t pading = 0; pading < pading_size; pading++)
{
encode_buf[encode_buf_size + pading] = pading_size;
}
encode_buf_size += pading_size;
uint32_t round = encode_buf_size / AES_ECB_Cipher::KEYLEN;
const unsigned char * iv = mKey;
for (uint32_t i = 0; i < round; ++i)
{
AES128_ECB_encrypt(encode_buf + i * AES_ECB_Cipher::KEYLEN, dest + i * AES_ECB_Cipher::KEYLEN);
if (use_cbc)
{
for (int j = 0; j < AES_ECB_Cipher::KEYLEN; ++j)
{
(dest + i * AES_ECB_Cipher::KEYLEN)[j] ^= iv[j];
}
iv = encode_buf + i * AES_ECB_Cipher::KEYLEN;
}
}
len = encode_buf_size;
if (len < 0 || len <= src_len)
{
return -1;
}
dest[len] = 0;
return 0;
}
int AES_ECB_Cipher::decode(const unsigned char* src, uint32_t src_len, unsigned char* dest, uint32_t& len)
{
// check input null pointer
if (nullptr == src)
{
return -1;
}
// make sure dest buff is larger than src buff
if(len < src_len)
{
return -1;
}
unsigned char encode_buf[1024];
memset(encode_buf, 0, sizeof(encode_buf));
memcpy(encode_buf, src, src_len);
uint8_t pading_size = src_len % AES_ECB_Cipher::KEYLEN;
for (uint8_t pading = 0; pading < pading_size; pading++)
{
encode_buf[src_len + pading] = pading_size;
}
src_len += pading_size;
// assume input has been padded well with pkcs5padding
if (src_len % AES_ECB_Cipher::KEYLEN != 0)
{
return -1;
}
uint32_t round = src_len / AES_ECB_Cipher::KEYLEN;
const unsigned char * iv = mKey;
for (uint32_t i = 0; i < round; ++i)
{
AES128_ECB_decrypt(encode_buf + i * AES_ECB_Cipher::KEYLEN, dest + i * AES_ECB_Cipher::KEYLEN);
if (use_cbc)
{
for (int j = 0; j < AES_ECB_Cipher::KEYLEN; ++j)
{
(dest + i * AES_ECB_Cipher::KEYLEN)[j] ^= iv[j];
}
iv = encode_buf + i * AES_ECB_Cipher::KEYLEN;
}
}
// unpad with pkcs5, remove unused charactors
uint8_t lastASIIC = (uint8_t)dest[src_len - 1];
for (int i = src_len - 1; i >= src_len - lastASIIC; i--)
{
if (dest[i] != lastASIIC)
{
return -1;
}
else
{
dest[i] = 0;
}
}
return 0;
}
lua_aes.cpp(c++和lua交互的代码)
int lua_to_aes_EncryptData(lua_State *L)
{
char *inbuf = (char*)luaL_checkstring(L, 1);
if (inbuf == nullptr)
{
return 0;
}
char* key = (char*)luaL_checkstring(L, 2);
if (key == nullptr)
{
return 0;
}
AES_ECB_Cipher aes((unsigned char*)key);
char out[1024]={0};
uint32_t dlen = 1024;
aes.encode((unsigned char*)inbuf,strlen(inbuf),(unsigned char*)out,dlen);
char* out1 = nullptr;
int dlen1 = cocos2d::base64Encode((unsigned char*)out, (unsigned int)dlen, &out1);
lua_pushlstring(L,(char*)out1, dlen1);
return 1;
}
int lua_to_aes_DecryptData(lua_State *L)
{
char *inbuf = (char*)luaL_checkstring(L, 1);
if (inbuf == nullptr)
{
return 0;
}
char* key = (char*)luaL_checkstring(L, 2);
if (key == nullptr)
{
return 0;
}
unsigned char* outbuf1 = nullptr;
int dlen1 = cocos2d::base64Decode((unsigned char*)inbuf, strlen(inbuf), &outbuf1);
AES_ECB_Cipher aes((unsigned char*)key);
char out[1024] = { 0 };
uint32_t dlen = 1024;
aes.decode((unsigned char*)outbuf1, dlen1, (unsigned char*)out, dlen);
lua_pushlstring(L,(char*)out,sizeof(out));
return 1;
}
main.lua(lua中如何使用)
加密:local postdata = aes.encode("123456","aaaa")
解密:local postdata1= aes.decode(postdata ,"aaaa")
备注:
1、代码写完以后,可以根据网页上的在线aes密码解析,对应我们的代码输出,检查是不是可行的代码
2、不论是加解密,都需要再进行一次base64的加解密,相结合
3、字符16位补齐的,去除的,在加解密中一定不要忘记
4、此文章只贴可行代码,aes代码加密原理自行百度