命令行文件加密工具源碼


程序使用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;
}


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com