首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

CryptoAPI 檔案加密解密完整實作指南

     編輯:關於C++

CryptoAPI 架構概覽

CryptoAPI 位於應用程式與密碼服務提供者 (CSP) 之間,類似 GDI 與顯示驅動程式關係。CSP 實作具體演算法 (軟體或硬體),應用程式透過標準 API 呼叫,無需處理底層數學細節。核心元件:

  • 簡易訊息函式
  • 低層訊息函式
  • 基礎加密函式
  • 憑證編解碼函式
  • 憑證存儲管理函式

加密原理:混合加密系統

  • 對稱加密 (Session Key):速度快,適合大量資料 (RC2, RC4, 3DES, AES)。
  • 非對稱加密 (公開/私密鑰對):速度慢,僅用於加密 Session Key 或數位簽章 (RSA, DSS)。
  • 雜湊 (Hash):產生固定長度摘要 (MD5, SHA),驗證完整性。

實務流程:資料用 Session Key 加密 → Session Key 用接收者公鑰加密 → 傳送加密資料與加密後的 Session Key。

檔案加密程式碼 (RC2/RC4 可切換)


#define USE_BLOCK_CIPHER  // 定義使用 RC2 區塊加密,否則用 RC4 流加密
#ifdef USE_BLOCK_CIPHER
#define ENCRYPT_ALGORITHM CALG_RC2
#define ENCRYPT_BLOCK_SIZE 8
#else
#define ENCRYPT_ALGORITHM CALG_RC4
#define ENCRYPT_BLOCK_SIZE 1
#endif

BOOL CAPIEncryptFile(PCHAR szSource, PCHAR szDestination, PCHAR szPassword) {
    FILE *hSource = fopen(szSource, "rb");
    FILE *hDest = fopen(szDestination, "wb");
    HCRYPTPROV hProv = 0;
    HCRYPTKEY hKey = 0, hXchgKey = 0;
    HCRYPTHASH hHash = 0;
    PBYTE pbKeyBlob = NULL;
    DWORD dwKeyBlobLen, dwBlockLen, dwBufferLen, dwCount;
    PBYTE pbBuffer = NULL;

    // 取得預設 CSP
    CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, 0);

    if (szPassword == NULL) {
        // 隨機 Session Key + 公鑰加密
        CryptGenKey(hProv, ENCRYPT_ALGORITHM, CRYPT_EXPORTABLE, &hKey);
        CryptGetUserKey(hProv, AT_KEYEXCHANGE, &hXchgKey);
        CryptExportKey(hKey, hXchgKey, SIMPLEBLOB, 0, NULL, &dwKeyBlobLen);
        pbKeyBlob = (PBYTE)malloc(dwKeyBlobLen);
        CryptExportKey(hKey, hXchgKey, SIMPLEBLOB, 0, pbKeyBlob, &dwKeyBlobLen);
        CryptDestroyKey(hXchgKey);
        // 寫入 Key Blob 長度與內容至檔案頭
        fwrite(&dwKeyBlobLen, sizeof(DWORD), 1, hDest);
        fwrite(pbKeyBlob, 1, dwKeyBlobLen, hDest);
    } else {
        // 密碼衍生金鑰 (PBKDF1 風格)
        CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash);
        CryptHashData(hHash, (BYTE*)szPassword, strlen(szPassword), 0);
        CryptDeriveKey(hProv, ENCRYPT_ALGORITHM, hHash, 0, &hKey);
        CryptDestroyHash(hHash);
    }

    // 計算區塊大小 (須為演算法區塊大小倍數)
    dwBlockLen = 1000 - 1000 % ENCRYPT_BLOCK_SIZE;
    dwBufferLen = (ENCRYPT_BLOCK_SIZE > 1) ? dwBlockLen + ENCRYPT_BLOCK_SIZE : dwBlockLen;
    pbBuffer = (PBYTE)malloc(dwBufferLen);

    // 逐塊加密寫入
    do {
        dwCount = fread(pbBuffer, 1, dwBlockLen, hSource);
        BOOL eof = feof(hSource);
        CryptEncrypt(hKey, 0, eof, 0, pbBuffer, &dwCount, dwBufferLen);
        fwrite(pbBuffer, 1, dwCount, hDest);
    } while (!feof(hSource));

    // 清理資源...
    return TRUE;
}

檔案解密程式碼


BOOL CAPIDecryptFile(PCHAR szSource, PCHAR szDestination, PCHAR szPassword) {
    // 開啟檔案、取得 CSP 同加密邏輯
    if (szPassword == NULL) {
        // 讀取檔案頭的 Key Blob
        fread(&dwKeyBlobLen, sizeof(DWORD), 1, hSource);
        pbKeyBlob = (PBYTE)malloc(dwKeyBlobLen);
        fread(pbKeyBlob, 1, dwKeyBlobLen, hSource);
        CryptImportKey(hProv, pbKeyBlob, dwKeyBlobLen, 0, 0, &hKey);
    } else {
        // 密碼衍生金鑰 (同加密)
        CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash);
        CryptHashData(hHash, (BYTE*)szPassword, strlen(szPassword), 0);
        CryptDeriveKey(hProv, ENCRYPT_ALGORITHM, hHash, 0, &hKey);
        CryptDestroyHash(hHash);
    }

    // 逐塊解密
    do {
        dwCount = fread(pbBuffer, 1, dwBlockLen, hSource);
        BOOL eof = feof(hSource);
        CryptDecrypt(hKey, 0, eof, 0, pbBuffer, &dwCount);
        fwrite(pbBuffer, 1, dwCount, hDest);
    } while (!feof(hSource));
    // 清理...
    return TRUE;
}

編譯與執行注意事項

  • 需定義 _WIN32_WINNT=0x0400 以上
  • 連結 advapi32.lib (CryptoAPI 位於此庫)
  • 區塊加密 (RC2) 需處理填補,緩衝區預留一個區塊大小
  • 流加密 (RC4) 無區塊對齊問題,ENCRYPT_BLOCK_SIZE=1
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved