#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解密文件的功能。
#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解密文件的功能。
瞎扯啊。 MD5加密了,还解密个P啊。