程序使用RC5算法对文件内容进行加密,同时加密文件名,加密后的文件名和文件签名一起进行Base64编码,最后生成一个加密名称作为新的文件名,只有输入正确密码才能查看文件名和文件内容。
命令行参数介绍
加密文件:-e -k key -i filename [-t directory] [-p prefix]
例:encrypt.exe -e -k 123456 test.txt C:/encrypt_file/
解密文件:-d -k key -i filename [-t directory]
例:encrypt.exe -d -k 123456 kml_811jW7BCsRZ2oIeqvqc=.rwz C:/decrypt_file/
校对文件:-c -k key -i filename1 -i filename2
例:encrypt.exe -c -k 123456 -i test.txt -i kml_811jW7BCsRZ2oIeqvqc=.rwz
列出指定目录下的加密文件:-l -k key [-t directory]
例:encrypt.exe -l -k 123456 -t C:/encrypt_file/
输出: 列出 C:/encrypt_file/ 下的加密文件
文件名 长度 加密文件名
==================== ======== ============================================
test.txt 920.00B kml_811jW7BCsRZ2oIeqvqc=.rwz
共找到 1 个加密文件
#include <windows.h>
#include <stdio.h>
#define RC5_R 12
#define RC5_P 0xb7e15163
#define RC5_Q 0x9e3779b9
#define ROTL(x, c) (((x) << ((c) & 31)) | ((x) >> (32 - ((c) & 31))))
#define ROTR(x, c) (((x) >> ((c) & 31)) | ((x) << (32 - ((c) & 31))))
#define MAX_FILENAME 140
#define FILE_ENCRYPT_SIGNATURE '/xe7ZWR'
typedef unsigned char UCHAR;
typedef unsigned short USHORT;
typedef unsigned long ULONG;
typedef struct _FILE_ENCRYPT_HEADER
{
union
{
ULONG dwSignature;
struct
{
USHORT wSignature;
USHORT cCheckCode : 14;
USHORT cCheckValue : 2;
};
};
ULONG dwFirstEncrypt : 4;
ULONG dwSecondEncrypt : 4;
ULONG dwReserved : 8;
ULONG dwJunkFill : 16;
char cFileName[];
} FILE_ENCRYPT_HEADER, *PFILE_ENCRYPT_HEADER;
static ULONG rc5_sbox[RC5_R * 2 + 2];
static char base64_alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
static int base64_table_empty = 1;
static UCHAR base64_table[256];
ULONG Base64Encode(void *dst, void *src, ULONG len)
{
UCHAR *p1 = src;
char *p2 = dst;
ULONG i, v;
for (i = 0; i < len; i += 3)
{
switch (len - i)
{
case 1:
v = (p1[i] << 16);
*p2++ = base64_alphabet[v >> 18];
*p2++ = base64_alphabet[(v >> 12) & 63];
*p2++ = base64_alphabet[64];
*p2++ = base64_alphabet[64];
break;
case 2:
v = (p1[i] << 16) | (p1[i + 1] << 8);
*p2++ = base64_alphabet[v >> 18];
*p2++ = base64_alphabet[(v >> 12) & 63];
*p2++ = base64_alphabet[(v >> 6) & 63];
*p2++ = base64_alphabet[64];
break;
default:
v = (p1[i] << 16) | (p1[i + 1] << 8) | p1[i + 2];
*p2++ = base64_alphabet[v >> 18];
*p2++ = base64_alphabet[(v >> 12) & 63];
*p2++ = base64_alphabet[(v >> 6) & 63];
*p2++ = base64_alphabet[v & 63];
break;
}
}
*p2++ = '/0';
return p2 - (char *)dst;
}
ULONG Base64Decode(void *dst, void *src,ULONG len)
{
char *p1 = src;
UCHAR *p2 = dst;
ULONG i, v, n;
if (base64_table_empty)
{
for (i = 0; i < sizeof(base64_table); i++)
base64_table[i] = 255;
for (i = 0; i < 64; i++)
base64_table[base64_alphabet[i]] = (char)i;
base64_table_empty = 0;
}
for (i = 0, n = 0; i < len; i++)
{
if (base64_table[p1[i]] == 255)
break;
v = base64_table[p1[i]] | (v << 6);
n += 6;
if (n >= 8)
{
n -= 8;
*p2++ = (UCHAR)(v >> n);
}
}
return p2 - (UCHAR *)dst;
}
void rc5_key(UCHAR *pbKey, ULONG dwLen)
{
ULONG i, j, k, A, B;
ULONG *S;
ULONG L[16];
ULONG SL, LL;
SL = (RC5_R + 1) * 2;
LL = (dwLen + 3) >> 2;
S = rc5_sbox;
L[dwLen >> 2] = 0;
memcpy((UCHAR *)L, pbKey, dwLen);
S[0] = RC5_P;
for (i = 1; i < SL; i++)
{
S[i] = S[i - 1] + RC5_Q;
}
i = (SL > LL ? SL : LL) * 3;
A = B = j = k = 0;
for (; i > 0; i--)
{
A = S[j] = ROTL(S[j] + (A + B), 3);
B = L[k] = ROTL(L[k] + (A + B), (A + B));
if (++j >= SL) j = 0;
if (++k >= LL) k = 0;
}
}
static void rc5_encrypt1(UCHAR *pOut, UCHAR *pIn)
{
ULONG i, A, B;
ULONG *S;
S = rc5_sbox;
A = ((ULONG *)pIn)[0] + S[0];
B = ((ULONG *)pIn)[1] + S[1];
for (i = 1; i <= RC5_R; i++)
{
A = ROTL(A ^ B, B) + S[2 * i];
B = ROTL(B ^ A, A) + S[2 * i + 1];
}
((ULONG *)pOut)[0] = A;
((ULONG *)pOut)[1] = B;
}
static void rc5_decrypt1(UCHAR *pOut, UCHAR *pIn)
{
ULONG i, A, B;
ULONG *S;
S = rc5_sbox;
B = ((ULONG *)pIn)[1];
A = ((ULONG *)pIn)[0];
for (i = RC5_R; i > 0; i--)
{
B = ROTR(B - S[2 * i + 1], A) ^ A;
A = ROTR(A - S[2 * i], B) ^ B;
}
((ULONG *)pOut)[1] = B - S[1];
((ULONG *)pOut)[0] = A - S[0];
}
void rc5_encrypt(void *dst, void *src, ULONG len)
{
ULONG i, m, n;
if (len < 8)
{
for (i = 0; i < len; i++)
((UCHAR *)dst)[i] = ((UCHAR *)src)[i] ^ (UCHAR)rc5_sbox[i];
return;
}
if (len & 7)
{
n = (len & 7) + 8;
m = len - n;
}
else
{
n = 0;
m = len;
}
for (i = 0; i < m; i += 8)
{
rc5_encrypt1((UCHAR *)dst + i, (UCHAR *)src + i);
}
if (n)
{
memcpy((UCHAR *)dst + i, (UCHAR *)src + i, n);
rc5_encrypt1((UCHAR *)dst + i, (UCHAR *)dst + i);
rc5_encrypt1((UCHAR *)dst + i + n - 8, (UCHAR *)dst + i + n - 8);
}
}
void rc5_decrypt(void *dst, void *src, ULONG len)
{
ULONG i, m, n;
if (len < 8)
{
for (i = 0; i < len; i++)
((UCHAR *)dst)[i] = ((UCHAR *)src)[i] ^ (UCHAR)rc5_sbox[i];
return;
}
if (len & 7)
{
n = (len & 7) + 8;
m = len - n;
}
else
{
n = 0;
m = len;
}
for (i = 0; i < m; i += 8)
{
rc5_decrypt1((UCHAR *)dst + i, (UCHAR *)src + i);
}
if (n)
{
memcpy((UCHAR *)dst + i, (UCHAR *)src + i, n);
rc5_decrypt1((UCHAR *)dst + i + n - 8, (UCHAR *)dst + i + n - 8);
rc5_decrypt1((UCHAR *)dst + i, (UCHAR *)dst + i);
}
}
void Replace(char *lpStr, int ch1, int ch2)
{
int i, l = strlen(lpStr);
for (i = 0; i < l; i++)
{
if (lpStr[i] == (char)ch1)
lpStr[i] = (char)ch2;
}
}
int ProcessFile(char *lpSrcFile, char *lpDstFile, int type)
{
HANDLE hSrcFile, hDstFile;
ULONG i, j, nFileSize, nBlockSize;
ULONG nReadBytes, nWriteBytes;
UCHAR buf[0x10000];
hSrcFile = CreateFile(lpSrcFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if (hSrcFile == INVALID_HANDLE_VALUE)
{
printf("创建文件 %s 失败,错误码: %d/n", lpSrcFile, GetLastError());
return -1;
}
nFileSize = GetFileSize(hSrcFile, NULL);
if (nFileSize == -1)
{
CloseHandle(hSrcFile);
printf("GetFileSize 失败,错误码: %d/n", GetLastError());
return -1;
}
hDstFile = CreateFile(lpDstFile, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_NEW, 0, NULL);
if (hDstFile == INVALID_HANDLE_VALUE)
{
CloseHandle(hSrcFile);
printf("创建文件 %s 失败,错误码: %d/n", lpDstFile, GetLastError());
return -1;
}
if (SetFilePointer(hDstFile, nFileSize, NULL, FILE_BEGIN) == -1)
goto failed;
if (!SetEndOfFile(hDstFile))
goto failed;
SetFilePointer(hDstFile, 0, NULL, FILE_BEGIN);
for (i = 0; i < nFileSize; i += nBlockSize)
{
nBlockSize = min(nFileSize - i, sizeof(buf));
for (j = 0; j < nBlockSize; j += nReadBytes)
{
if (!ReadFile(hSrcFile, buf + j, nBlockSize - j, &nReadBytes, NULL))
goto failed;
}
switch (type)
{
case 1:
rc5_encrypt(buf, buf, nBlockSize);
break;
case 2:
rc5_decrypt(buf, buf, nBlockSize);
break;
}
for (j = 0; j < nBlockSize; j += nWriteBytes)
{
if (!WriteFile(hDstFile, buf + j, nBlockSize - j, &nWriteBytes, NULL))
goto failed;
}
printf("/r已完成 %2d%%", i / (nFileSize / 100));
}
printf("/r写入文件完成/n");
CloseHandle(hSrcFile);
CloseHandle(hDstFile);
return 0;
failed:
printf("/r写入文件失败/n");
CloseHandle(hSrcFile);
CloseHandle(hDstFile);
DeleteFile(lpDstFile);
return -1;
}
int DoFileEncrypt(char *lpFileName, char *lpOutDir, char *pPrefix)
{
char szNewFile[MAX_PATH];
char szPartName[MAX_PATH];
char szOutFile[MAX_PATH];
char buffer[200];
int nNameLength;
PFILE_ENCRYPT_HEADER feh;
feh = (PFILE_ENCRYPT_HEADER)szNewFile;
strcpy(szPartName, strrchr(lpFileName, '//') + 1);
if (strlen(szPartName) > MAX_FILENAME)
{
printf("%s 文件名太长,最大文件名长度 %d/n", lpFileName, MAX_FILENAME);
return -1;
}
srand(GetTickCount());
strcpy(feh->cFileName, szPartName);
feh->wSignature = 0xa3b5;
feh->cCheckValue = (USHORT)rand();
feh->cCheckCode = feh->cCheckValue ^ 0x77;
feh->dwFirstEncrypt = 1;
feh->dwSecondEncrypt = 0;
feh->dwReserved = 0;
feh->dwJunkFill = rand() & 0x7fff;
nNameLength = sizeof(FILE_ENCRYPT_HEADER) + strlen(szPartName) + 1;
rc5_encrypt(buffer, szNewFile, nNameLength);
Base64Encode(szNewFile, buffer, nNameLength);
Replace(szNewFile, '/', '_');
if (pPrefix != NULL)
sprintf(szOutFile, "%s//%s-%s.rwz", lpOutDir, pPrefix, szNewFile);
else
sprintf(szOutFile, "%s//%s.rwz", lpOutDir, szNewFile);
printf("开始加密 %s 到 %s/n", lpFileName, szOutFile);
return ProcessFile(lpFileName, szOutFile, 1);
}
int DoFileDecrypt(char *lpFileName, char *lpOutDir)
{
char szPartName[MAX_PATH];
char szOutFile[MAX_PATH];
char buffer[200];
int nNameLength;
PFILE_ENCRYPT_HEADER feh;
char *pExtName;
feh = (PFILE_ENCRYPT_HEADER)buffer;
strcpy(szPartName, strrchr(lpFileName, '//') + 1);
Replace(szPartName, '_', '/');
pExtName = strrchr(szPartName, '-');
if (pExtName != NULL)
{
strcpy(szPartName, pExtName + 1);
}
pExtName = strrchr(szPartName, '.');
if (pExtName != NULL)
{
*pExtName = '/0';
}
if (strlen(szPartName) < 12)
{
printf("%s 文件名信息不正确/n", szPartName);
return -1;
}
nNameLength = Base64Decode(buffer, szPartName, -1);
rc5_decrypt(buffer, buffer, nNameLength);
if (feh->dwSignature != FILE_ENCRYPT_SIGNATURE)
{
if (feh->wSignature != 0xa3b5 || feh->cCheckValue != (feh->cCheckCode ^ 0x77))
{
printf("%s 文件签名失配,密码错误?/n", szPartName);
return -1;
}
}
sprintf(szOutFile, "%s//%s", lpOutDir, feh->cFileName);
printf("开始解密 %s 到 %s/n", lpFileName, szOutFile);
return ProcessFile(lpFileName, szOutFile, 2);
}
int DoCheckFile(char *lpFileName1, char *lpFileName2)
{
HANDLE hSrcFile, hDstFile;
ULONG i, j, nFileSize, nBlockSize;
ULONG nReadBytes;
UCHAR buf1[0x10000], buf2[0x10000];
printf("开始校对文件:源 %s 目标 %s/n", lpFileName1, lpFileName2);
hSrcFile = CreateFile(lpFileName1, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if (hSrcFile == INVALID_HANDLE_VALUE)
{
printf("打开文件 %s 失败,错误码: %d/n", lpFileName1, GetLastError());
return -1;
}
nFileSize = GetFileSize(hSrcFile, NULL);
if (nFileSize == -1)
{
CloseHandle(hSrcFile);
printf("GetFileSize 失败,错误码: %d/n", GetLastError());
return -1;
}
hDstFile = CreateFile(lpFileName2, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if (hDstFile == INVALID_HANDLE_VALUE)
{
CloseHandle(hSrcFile);
printf("打开文件 %s 失败,错误码: %d/n", lpFileName2, GetLastError());
return -1;
}
if (nFileSize != GetFileSize(hDstFile, NULL))
{
printf("校对失败,文件长度不一致/n");
goto failed;
}
for (i = 0; i < nFileSize; i += nBlockSize)
{
nBlockSize = min(nFileSize - i, sizeof(buf1));
for (j = 0; j < nBlockSize; j += nReadBytes)
{
if (!ReadFile(hSrcFile, buf1 + j, nBlockSize - j, &nReadBytes, NULL))
{
printf("读取文件失败,错误码 %d/n", GetLastError());
goto failed;
}
}
for (j = 0; j < nBlockSize; j += nReadBytes)
{
if (!ReadFile(hDstFile, buf2 + j, nBlockSize - j, &nReadBytes, NULL))
{
printf("读取文件失败,错误码 %d/n", GetLastError());
goto failed;
}
}
rc5_decrypt(buf1, buf1, nBlockSize);
if (memcmp(buf1, buf2, nBlockSize) != 0)
{
printf("校对失败,文件内容不一致/n");
goto failed;
}
printf("/r已完成 %2d%%", i / (nFileSize / 100));
}
printf("/r校对文件完成/n");
failed:
CloseHandle(hSrcFile);
CloseHandle(hDstFile);
return 0;
}
int DoListFile(char *lpDirPath)
{
WIN32_FIND_DATA wfd;
HANDLE hFind;
char szFind[MAX_PATH];
char szPartName[MAX_PATH];
char buffer[200];
PFILE_ENCRYPT_HEADER feh;
int nNameLength;
char *pExtName;
double nFileLength;
char szFileLength[60];
int nFileCount = 0;
printf(" 列出 %s 下的加密文件/n", lpDirPath);
printf("文件名 长度 加密文件名/n");
printf("==================== ======== ============================================/n");
sprintf(szFind, "%s//*.rwz", lpDirPath);
feh = (PFILE_ENCRYPT_HEADER)buffer;
hFind = FindFirstFile(szFind, &wfd);
if (hFind == INVALID_HANDLE_VALUE)
{
return 0;
}
do
{
if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
if (wfd.cFileName[0] == '.' && (*(short *)(wfd.cFileName + 1) == '.' || !wfd.cFileName[1]))
continue;
}
strcpy(szPartName, wfd.cFileName);
Replace(szPartName, '_', '/');
pExtName = strrchr(szPartName, '-');
if (pExtName != NULL)
{
strcpy(szPartName, pExtName + 1);
}
pExtName = strrchr(szPartName, '.');
if (pExtName != NULL)
{
*pExtName = '/0';
}
if (strlen(szPartName) < 12)
continue;
nNameLength = Base64Decode(buffer, szPartName, -1);
rc5_decrypt(buffer, buffer, nNameLength);
if (feh->dwSignature != FILE_ENCRYPT_SIGNATURE)
{
if (feh->wSignature != 0xa3b5 || feh->cCheckValue != (feh->cCheckCode ^ 0x77))
continue;
}
nFileLength = wfd.nFileSizeLow;
if (nFileLength > 1000 * 1000 * 1000)
{
nFileLength /= 1024 * 1024 * 1024;
sprintf(szFileLength, "%3.2fGB", nFileLength);
}
if (nFileLength > 1000 * 1000)
{
nFileLength /= 1024 * 1024;
sprintf(szFileLength, "%3.2fMB", nFileLength);
}
else if (nFileLength > 1000)
{
nFileLength /= 1024;
sprintf(szFileLength, "%3.2fKB", nFileLength);
}
else
{
sprintf(szFileLength, "%3.2fB ", nFileLength);
}
printf("%-20.20s %8.8s %-44.44s/n", feh->cFileName, szFileLength, wfd.cFileName);
nFileCount++;
} while (FindNextFile(hFind, &wfd));
printf("共找到 %d 个加密文件/n", nFileCount);
FindClose(hFind);
return 0;
}
void usage(char *lpAppName)
{
printf("加密文件:%s -e -k key -i filename [-t directory] [-p prefix]/n", lpAppName);
printf("解密文件:%s -d -k key -i filename [-t directory]/n", lpAppName);
printf("校对文件:%s -c -k key -i filename1 -i filename2/n", lpAppName);
printf("列出指定目录下的加密文件:%s -l -k key [-t directory]/n", lpAppName);
}
int main(int argc, char *argv[])
{
char szInputFile[MAX_PATH] = {0};
char szTargetDir[MAX_PATH] = {0};
char *pPrefix = NULL;
int i;
if (argc < 4)
{
usage(argv[0]);
return -1;
}
if (argc == 4)
{
rc5_key(argv[1], strlen(argv[1]));
ProcessFile(argv[2], argv[3], 2);
return 0;
}
if (stricmp(argv[2], "-k") != 0)
{
usage(argv[0]);
return -1;
}
rc5_key(argv[3], strlen(argv[3]));
if (stricmp(argv[1], "-e") == 0)
{
if (argc < 6)
{
usage(argv[0]);
return -1;
}
if (stricmp(argv[4], "-i") != 0)
{
usage(argv[0]);
return -1;
}
GetFullPathName(argv[5], sizeof(szInputFile), szInputFile, NULL);
if (argc > 6)
{
for (i = 6; i < argc; i += 2)
{
if (stricmp(argv[i] , "-t") == 0 && i + 1 < argc)
{
GetFullPathName(argv[i + 1], sizeof(szTargetDir), szTargetDir, NULL);
continue;
}
if (stricmp(argv[i], "-p") == 0 && i + 1 < argc)
{
pPrefix = argv[i + 1];
continue;
}
usage(argv[0]);
return -1;
}
}
if (szTargetDir[0] == '/0')
{
char *p = strrchr(szInputFile, '//');
lstrcpyn(szTargetDir, szInputFile, p - szInputFile + 1);
}
return DoFileEncrypt(szInputFile, szTargetDir, pPrefix);
}
if (stricmp(argv[1], "-d") == 0)
{
if (argc != 6 && argc != 8)
{
usage(argv[0]);
return -1;
}
if (stricmp(argv[4], "-i") != 0)
{
usage(argv[0]);
return -1;
}
GetFullPathName(argv[5], sizeof(szInputFile), szInputFile, NULL);
if (argc == 8)
{
if (stricmp(argv[6] , "-t") != 0)
{
usage(argv[0]);
return -1;
}
GetFullPathName(argv[7], sizeof(szTargetDir), szTargetDir, NULL);
}
else
{
char *p = strrchr(szInputFile, '//');
lstrcpyn(szTargetDir, szInputFile, p - szInputFile + 1);
}
return DoFileDecrypt(szInputFile, szTargetDir);
}
if (stricmp(argv[1], "-l") == 0)
{
if (argc == 4)
GetCurrentDirectory(MAX_PATH, szTargetDir);
else if (argc == 6 && stricmp(argv[4], "-t") == 0)
strcpy(szTargetDir, argv[5]);
else
{
usage(argv[0]);
return -1;
}
return DoListFile(szTargetDir);
}
if (stricmp(argv[1], "-c") == 0)
{
if (argc != 8)
{
usage(argv[0]);
return -1;
}
if (stricmp(argv[4], "-i") != 0 ||
stricmp(argv[6], "-i") != 0)
{
usage(argv[0]);
return -1;
}
GetFullPathName(argv[5], sizeof(szInputFile), szInputFile, NULL);
GetFullPathName(argv[7], sizeof(szTargetDir), szTargetDir, NULL);
return DoCheckFile(szInputFile, szTargetDir);
}
usage(argv[0]);
return -1;
}