APP安全(四)-結合MD5、DES生成一個AES Secret Key

一、 前言

簽名講過使用我們使用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),用於確保信息傳輸完整一致。具有以下特點:

  1. 壓縮性:任意長度的數據,算出的MD5值長度都是固定的。
  2. 容易計算:從原數據計算出MD5值很容易。
  3. 抗修改性:對原數據進行任何改動,哪怕只修改1個字節,所得到的MD5值都有很大區別。
  4. 強抗碰撞:已知原數據和其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;
}

三、總結

  1. 介紹了MD5的特性
  2. 如何結合MD5生成AES Secret Key
  3. DES的實現,對於這兩者的結合使用,將在後面的章節介紹

項目github地址

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章