CryptoAPI 位於應用程式與密碼服務提供者 (CSP) 之間,類似 GDI 與顯示驅動程式關係。CSP 實作具體演算法 (軟體或硬體),應用程式透過標準 API 呼叫,無需處理底層數學細節。核心元件:
實務流程:資料用 Session Key 加密 → Session Key 用接收者公鑰加密 → 傳送加密資料與加密後的 Session Key。
#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 位於此庫)ENCRYPT_BLOCK_SIZE=1