一、 前言
簽名講過使用我們使用AES加密算法與服務端進行數據加解密交互,對AES來說,secret key,如果我們把key硬編碼在代碼裏面,被逆向後也很容易找到對應的key,隱藏我們需要設計一套算法來保證key是動態生成,不是硬編碼在代碼裏。這裏我們使用MD5以及DES來增加算法的破解難度,其中的核心是MD5摘要算法,它的出現保證了secret key的產生不是唯一的。
二、具體實現方案
1)MD5介紹
參考百度百科:https://baike.baidu.com/item/MD5/212708?fr=aladdin
MD5即Message-Digest Algorithm 5(信息-摘要算法5),用於確保信息傳輸完整一致。具有以下特點:
- 壓縮性:任意長度的數據,算出的MD5值長度都是固定的。
- 容易計算:從原數據計算出MD5值很容易。
- 抗修改性:對原數據進行任何改動,哪怕只修改1個字節,所得到的MD5值都有很大區別。
- 強抗碰撞:已知原數據和其MD5值,想找到一個具有相同MD5值的數據(即僞造數據)是非常困難的。
MD5作用:
把一個任意長度的字節串變換成一定長的十六進制數字串,只要原始內容不變,產生的摘要內容就不會變。
結合MD5生成一個AES Secret Key
secrete key 的生成原理,對任意一個字符進行MD5,取出MD值,與對應長度key進行位運算,保證產生的index在目標數據的長度範圍內,再根據index取出值,從而生成secret key。具體實現代碼如下:
#include <string>
#include "openssl/md5.h"
using namespace std;
const char strKey[] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};
string createKey(const string &key){
unsigned char md[MD5_DIGEST_LENGTH];
const char *tem = key.c_str();
MD5((const unsigned char*)tem, key.length(),(unsigned char*)&md);
int len = MD5_DIGEST_LENGTH;
//key length = 16
char keyChar[len];
int index = 0;
for(int i = 0; i < len; i++){
keyChar[index++] = strKey[(md[i] >> 2) & 0x3D];
}
string rs(keyChar,len);
return rs;
}
1)結合DES
上述方式已經生成了AES的secret key,但是爲了增加破解難度,再次結合DES算法,解密一個數據,作爲生成key的原始內容。這裏DES的實現和AES的實現都相似,採用CBC/PKCS5Padding填充模式,具體實現參考如下代碼:
#include "openssl/des.h"
/***
* src:明文
* srcLen:明文長度
* key:密鑰
* keyLen:密鑰長度
* outLen:密文長度
* 返回值:密文 需要free
*
*/
unsigned char *des_encrypt(unsigned char *src, int srcLen, unsigned char *aesKey, int keyLen, int *outLen)
{
int aes_block_size = 8;
int blockCount = 0;
int quotient = srcLen / aes_block_size;
int mod = srcLen % aes_block_size;
blockCount = quotient + 1;
int allLength = blockCount * aes_block_size;
int padding = aes_block_size - mod;
char *in = (char *)malloc(allLength);
memset(in, padding, allLength);
memcpy(in, src, srcLen);
DES_cblock key;
DES_key_schedule key_schedule;
memcpy(key,aesKey,keyLen);
DES_set_key_unchecked(&key, &key_schedule);
//IV
DES_cblock ivec;
memcpy(ivec, aesKey, keyLen);
//out
char *out = (char *)malloc(allLength);
memset(out, 0x00, allLength);
*outLen = allLength;
DES_ncbc_encrypt((unsigned char*)in, (unsigned char*)out, allLength, &key_schedule, &ivec, DES_ENCRYPT);
free(in);
return (unsigned char*)out;
}
/**
* decrypt
* src:密文
* srcLen:密文長度
* key:密鑰
* keyLen:密鑰長度
* outLen:明文長度
* 返回值: 明文 需要free
*/
unsigned char *des_decrypt(unsigned char *src, int srcLen, unsigned char *aesKey, int keyLen, int *outLen)
{
DES_cblock key;
DES_key_schedule key_schedule;
memcpy(key,aesKey,keyLen);
DES_set_key_unchecked(&key, &key_schedule);
unsigned char *tmp = (unsigned char *)malloc(srcLen);
memset(tmp,0,srcLen);
//IV
DES_cblock iv;
memcpy(iv, aesKey, keyLen);
DES_ncbc_encrypt((const unsigned char *)src, tmp, srcLen, &key_schedule, &iv, DES_DECRYPT);
int unpadding = tmp[srcLen - 1];
*outLen = srcLen - unpadding;
char *out = (char *)malloc(*outLen);
memcpy(out, tmp, *outLen);
free(tmp);
return (unsigned char*)out;
}
三、總結
- 介紹了MD5的特性
- 如何結合MD5生成AES Secret Key
- DES的實現,對於這兩者的結合使用,將在後面的章節介紹