#define ENCRYPT_FLAG        "IGEF"
#define ENCRYPT_FLAG_LEN    4
#define ENCRYPT_MAX_BLOCK   0x100
#define ENCRYPT_FILE_BLOCK  1024*1024*2#define RESERVE_SIZE (1024-sizeof(IG_HEADER)-sizeof(ENCRYPT_INFO)-sizeof(DOC_SEC_ATTR))
// 文件头格式
typedef struct _IG_HEADER {
    char            szFlag[ENCRYPT_FLAG_LEN]; // 加密标记
    DWORD           dwMajorVersion; // 模块主版本
    DWORD           dwMinorVersion; // 模块副版本
} IG_HEADER, *PIG_HEADER;// 加密方式
typedef struct _ENCRYPT_INFO {
    DWORD           dwEncryptType;  // 加密算法
    DWORD           dwKeyLength;    // 密钥长度
    DWORD           dwBlockLen;     // 分块长度
    DWORD           dwEncryptLen;   // 最大加密长度(0为加密整个文件)
    char            KeyMd5[33];     // 密钥MD5
} ENCRYPT_INFO, *PENCRYPT_INFO;//受保护文件安全属性
typedef struct _DOC_SEC_ATTR {
    BOOL            bValid;         // 是否有安全属性
    int             nMaxOpenCount;  // 有效打开次数
    SYSTEMTIME      stEndTime;      // 有效阅览截至时间
    char            szHWIDMD5[33];  // 计算机硬件MD5
} DOC_SEC_ATTR, *PDOC_SEC_ATTR;// 完整的加密文件头(1024 BYTE)
typedef struct _ENCRYPT_HEADER {
    IG_HEADER       IGHdr;
    ENCRYPT_INFO    EncryptInfo;
    DOC_SEC_ATTR    DocSecAttr;
    char            Reserve[RESERVE_SIZE];
} ENCRYPT_HEADER, *PENCRYPT_HEADER;
// 由szKey生成长度为dwKeyLen的密钥,保存至szEncryptKey
void SetEncryptKey(char *szKey, DWORD dwKeyLen, char *szEncryptKey)
{
    char szMd5[MAX_PATH] = {0};
    char szFullKey[1024+1] = {0};    MD5(szKey, szFullKey);    while (strlen(szFullKey) < dwKeyLen) {
        MD5(szFullKey, szMd5);
        strcat(szFullKey, szMd5);
    }
    szFullKey[dwKeyLen] = '\0';
    strcpy(szEncryptKey, szFullKey);
}BOOL need_decrypt(unsigned char *pBuffer, int nBufLen)
{
    if (strncmp(ENCRYPT_FLAG, (char *)pBuffer, strlen(ENCRYPT_FLAG)) != 0) return FALSE;
    return TRUE;
}// 根据文件头判断文件是否需要解密
int NeedDecrypt(WCHAR *wFileName)
{
    char pBuf[ENCRYPT_FLAG_LEN+1] = {0};
    FILE *fStream = _wfopen(wFileName, L"rb");
    if (!fStream) {
        if (GetLastError() == 2) return 0;
        return -1;
    }    fread(pBuf, 1, sizeof(pBuf)-1, fStream);
    fclose(fStream);
    if (strncmp(ENCRYPT_FLAG, (char *)pBuf, strlen(ENCRYPT_FLAG)) != 0) return 0;
    return 1;
}// XOR加密
void xor_crypt(
    unsigned char *pInBuffer,
    unsigned char *pOutBuffer,
    unsigned long cbBuffer,
    unsigned char *pKey,
    unsigned long ulKeyLen,
    unsigned long ulOffset
    )
{
    char *c = (char *)&ulOffset;
    for (unsigned long i=0; i<cbBuffer; i++) {
        unsigned u = ulOffset%ulKeyLen;
        unsigned char p = *pInBuffer ^ pKey[u];
        p = p ^ c[0];
        p = p ^ c[1];
        p = p ^ c[2];
        p = p ^ c[3];
        *pOutBuffer = p;        pInBuffer++;
        pOutBuffer++;
        ulOffset++;
    }
}void decrypt_buf(
   char *key,
   unsigned char *inbuf,
   unsigned long len,
   unsigned char *outbuf,
   unsigned long offset
   )
{
    long n = 0;
    for (int i=0; i<len; i+=ENCRYPT_MAX_BLOCK) {
        n = len-i;
        if (n < ENCRYPT_MAX_BLOCK) {
            decrypt(inbuf+i, outbuf+i, len-i, key, strlen(key), offset+i);
            break;
        }
        xor_crypt(inbuf+i, outbuf+i, ENCRYPT_MAX_BLOCK, key, strlen(key), offset+i);
    }
}// 根据最大加密文件尺寸解密缓冲区
VOID DecryptBlock(ENCRYPT_INFO *pEncryptInfo,
    char *szKey,
    unsigned char *pInBuf,
    unsigned long ulBufLen,
    unsigned char *pOutBuf,
    unsigned long ulOffset
    )
{
    if (pEncryptInfo->dwEncryptLen > 0) {        if (pEncryptInfo->dwEncryptLen > ulOffset) {
            int nEncryptLen = pEncryptInfo->dwEncryptLen - ulOffset - ulBufLen;            if (nEncryptLen >= 0) {
                // 解密整块内容
                decrypt_buf(szKey, pInBuf, ulBufLen, pOutBuf, ulOffset);
            }
            else {
                if (pInBuf != pOutBuf) {
                    // 复制内容
                    memcpy(pOutBuf, pInBuf, ulBufLen);
                }
                // 解密部分内容
                decrypt_buf(szKey, pInBuf, ulBufLen+nEncryptLen, pOutBuf, ulOffset);
            }
        }
        else if (pInBuf != pOutBuf) {
            // 复制内容
            memcpy(pOutBuf, pInBuf, ulBufLen);
        }
    }
    else {
        // 解密整块内容
        decrypt_block(pEncryptInfo, szKey, pInBuf, ulBufLen, pOutBuf, ulOffset);
    }
}// 解密文件
BOOL DecodeFile(WCHAR *wInFile, WCHAR *wOutFile, char *szKey)
{
    // 打开源文件
    HANDLE hInFile = CreateFileW(wInFile,
        GENERIC_READ,
        FILE_SHARE_READ | FILE_SHARE_WRITE,
        NULL,
        OPEN_EXISTING,
        FILE_ATTRIBUTE_NORMAL,
        NULL);
    if (hInFile == INVALID_HANDLE_VALUE) {
        return FALSE;
    }    // 读取文件前4个字节,判断是否需要解密
    unsigned char pFlag[ENCRYPT_FLAG_LEN+1] = {0};
    DWORD dwRead = 0;
    ReadFile(hInFile, pFlag, ENCRYPT_FLAG_LEN, &dwRead, NULL);
    if (dwFileLength>=ENCRYPT_FLAG_LEN && dwRead!=ENCRYPT_FLAG_LEN) {
        CloseHandle(hInFile);
        return FALSE;
    }
    CloseHandle(hInFile);    // 判断是否需要解密
    BOOL bNeedDecode = need_decrypt(pFlag, ENCRYPT_FLAG_LEN);    // 文件不需要解密
    if (!bNeedDecode) {
        return FALSE;
    }    // 打开源文件,读取加密头结构
    hInFile = CreateFileW(wInFile,
        GENERIC_READ,
        FILE_SHARE_READ | FILE_SHARE_WRITE,
        NULL,
        OPEN_EXISTING,
        FILE_ATTRIBUTE_NORMAL,
        NULL);
    if (hInFile == INVALID_HANDLE_VALUE) {
        return FALSE;
    }    int nHdrLen = sizeof(ENCRYPT_HEADER);
    ENCRYPT_HEADER EncryptHdr = {0};
    if (!ReadFile(hInFile, &EncryptHdr, nHdrLen, &dwRead, NULL) || dwRead != nHdrLen) {
        CloseHandle(hInFile);
        return FALSE;
    }
    CloseHandle(hInFile);    // 判断密钥HASH是否相同
    char szMd5[MAX_PATH] = {0};
    MD5(szKey, szMd5);
    if (strcmp(EncryptHdr.EncryptInfo.KeyMd5, szMd5) != 0) {
        SetLastError(ERROR_INVALID_PARAMETER);
        return FALSE;
    }
    // 判断密钥长度是否相同
    if (strlen(szKey) != EncryptHdr.EncryptInfo.dwKeyLength) {
        return FALSE;
    }    // 打开源文件,读取密文内容
    hInFile = CreateFileW(wInFile,
        GENERIC_READ,
        FILE_SHARE_READ | FILE_SHARE_WRITE,
        NULL,
        OPEN_EXISTING,
        FILE_ATTRIBUTE_NORMAL,
        NULL);
    if (hInFile == INVALID_HANDLE_VALUE) {
        return FALSE;
    }
    SetFilePointer(hInFile, nHdrLen, NULL, FILE_BEGIN);    // 打开目标文件,写入明文内容
    HANDLE hOutFile = CreateFileW(wOutFile,
        GENERIC_WRITE,
        FILE_SHARE_READ | FILE_SHARE_WRITE,
        NULL,
        CREATE_ALWAYS,
        FILE_ATTRIBUTE_NORMAL,
        NULL);
    if (hOutFile == INVALID_HANDLE_VALUE) {
        CloseHandle(hInFile);
        return FALSE;
    }    // 调整解密后的文件长度
    dwFileLength -= nHdrLen;    // 以ENCRYPT_MAX_BLOCK为单位,将源文件分块解密
    int nReadLen = 0;
    if (dwFileLength <= ENCRYPT_FILE_BLOCK) nReadLen = dwFileLength;
    else nReadLen = ENCRYPT_FILE_BLOCK;    DWORD dwTotalLen = 0;
    unsigned char *pBuf = (unsigned char *)SafeMalloc(ENCRYPT_FILE_BLOCK);
    while (dwTotalLen < dwFileLength) {
        // 读取密文
        dwRead = 0;
        BOOL res = ReadFile(hInFile, pBuf, nReadLen, &dwRead, NULL);
        if ( !res ||
             ((dwRead != nReadLen) && (dwRead+dwTotalLen != dwFileLength)) ) {
            CloseHandle(hInFile);
            CloseHandle(hOutFile);
            SafeFree(&pBuf);
            return FALSE;
        }        // 解密文件内容
        DecryptBlock(szKey, pBuf, dwRead, pBuf, dwTotalLen);        // 写入明文
        DWORD dwWrite = 0;
        res = WriteFile(hOutFile, pBuf, dwRead, &dwWrite, NULL);
        if (!res || dwWrite != dwRead) {
            CloseHandle(hInFile);
            CloseHandle(hOutFile);
            SafeFree(&pBuf);
            return FALSE;
        }        dwTotalLen += dwRead;
    }    CloseHandle(hInFile);
    CloseHandle(hOutFile);
    SafeFree(&pBuf);    // 解密完毕
    return TRUE;
}
改了几行,增加了对KEY MD5的检查,如果KEY的MD5不匹配,就不继续解密了1、SetEncryptKey()的作用是,传入szKey参数(key_content)和dwKeyLen参数(key_length),生成真正的szEncryptKey;
2、通过MD5函数计算szEncryptKey获得szMD5;
3、调用DecodeFile()函数,使用szEncryptKey作为szKey参数来解密文件。
2、通过MD5函数计算szEncryptKey获得szMD5;
这一步先不处理也可以,先实现通过key_content和key_length生成szEncryptKey,并使用这个key解密文件的功能。