上一篇使用了加密和导出密钥,这一篇讲解一下文件解密和导出密钥
#include <tchar.h>
#include <stdio.h>
#include <windows.h>
#include <wincrypt.h>
#include <conio.h>
#pragma comment (lib, "advapi32")
#define KEYLENGTH 0x00800000
#define ENCRYPT_ALGORITHM CALG_RC4
#define ENCRYPT_BLOCK_SIZE 8
bool MyDecryptFile(
LPTSTR szSource,
LPTSTR szDestination,
LPTSTR szPassword,
LPTSTR szkeyblob);
void MyHandleError(
LPTSTR psz,
int nErrorNumber);
int main()
{
LPTSTR pszSource = (LPTSTR)L"D:\\testSecurity\\hello22.txt";
LPTSTR pszDestination = (LPTSTR)L"D:\\testSecurity\\hello33.txt";
LPTSTR pszkeyblobSource = (LPTSTR)L"D:\\testSecurity\\exportkeyblob.txt";
LPTSTR pszPassword = NULL;
//LPTSTR pszPassword = NULL;
//pszPassword = (LPTSTR)L"123456";
//---------------------------------------------------------------
// Call EncryptFile to do the actual encryption.
if (MyDecryptFile(pszSource, pszDestination, pszPassword, pszkeyblobSource))
{
_tprintf(TEXT("Encryption of the file %s was successful. \n"),pszSource);
_tprintf(TEXT("The encrypted data is in file %s.\n"),pszDestination);
}
else
{
MyHandleError(TEXT("Error encrypting file!\n"),GetLastError());
}
getchar();
return 0;
}
bool MyDecryptFile(LPTSTR pszSourceFile,LPTSTR pszDestinationFile,LPTSTR pszPassword,LPTSTR pszkeyblobSource)
{
//---------------------------------------------------------------
// Declare and initialize local variables.
bool fReturn = false;
HANDLE hSourceFile = INVALID_HANDLE_VALUE;
HANDLE hDestinationFile = INVALID_HANDLE_VALUE;
HANDLE hkeyblobsoucerFile = INVALID_HANDLE_VALUE;
HCRYPTKEY hKey = NULL;
HCRYPTHASH hHash = NULL;
HCRYPTPROV hCryptProv = NULL;
DWORD dwCount;
PBYTE pbBuffer = NULL;
DWORD dwBlockLen;
DWORD dwBufferLen;
//---------------------------------------------------------------
// Open the source file.
hSourceFile = CreateFile(
pszSourceFile,
FILE_READ_DATA,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (INVALID_HANDLE_VALUE != hSourceFile)
{
_tprintf(TEXT("The source encrypted file, %s, is open. \n"),pszSourceFile);
}
else
{
_tprintf(TEXT("The source encrypted file, %s, is open. \n"),pszSourceFile);
MyHandleError(TEXT("Error opening source plaintext file!\n"),GetLastError());
goto Exit_MyDecryptFile;
}
//---------------------------------------------------------------
// Open the destination file.
hDestinationFile = CreateFile(
pszDestinationFile,
FILE_WRITE_DATA,
FILE_SHARE_READ,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (INVALID_HANDLE_VALUE != hDestinationFile)
{
_tprintf(TEXT("The destination file, %s, is open. \n"),pszDestinationFile);
}
else
{
MyHandleError(TEXT("Error opening destination file!\n"),GetLastError());
goto Exit_MyDecryptFile;
}
//---------------------------------------------------------------
// Get the handle to the default provider.
if (!CryptAcquireContext(
&hCryptProv,
NULL,
MS_ENHANCED_PROV,
PROV_RSA_FULL, //这里为使用的加密策略
0))
{
//
if (GetLastError() == NTE_BAD_KEYSET)
{
if (!CryptAcquireContext(
&hCryptProv,
NULL,
MS_ENHANCED_PROV,
PROV_RSA_FULL,
CRYPT_NEWKEYSET))
{
MyHandleError(TEXT("Error during CryptAcquireContext!\n"),GetLastError());
goto Exit_MyDecryptFile;
//return FALSE;
}
}
else
{
MyHandleError(TEXT("Error during CryptAcquireContext!\n"),GetLastError());
goto Exit_MyDecryptFile;
//return FALSE;
}
}
_tprintf(TEXT("A cryptographic provider has been acquired. \n"));
// Create the session key.
if (pszPassword == NULL)
{
//-----------------------------------------------------------
// Decrypt the file with the saved session key.
DWORD dwKeyBlobLen = 0x00;
PBYTE pbKeyBlob = NULL;
hkeyblobsoucerFile = CreateFile(
pszkeyblobSource,
FILE_READ_DATA,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (INVALID_HANDLE_VALUE != hkeyblobsoucerFile)
{
_tprintf(TEXT("The source encrypted file, %s, is open. \n"), pszDestinationFile);
}
else
{
_tprintf(TEXT("The source encrypted file, %s, is open. \n"), pszDestinationFile);
MyHandleError(TEXT("Error opening source plaintext file!\n"), GetLastError());
goto Exit_MyDecryptFile;
}
//先读取keyBlob的长度,key blob文件的前4字节
if (!ReadFile(
hkeyblobsoucerFile,
&dwKeyBlobLen,
sizeof(DWORD),
&dwCount,
NULL))
{
MyHandleError(TEXT("Error reading key BLOB length!\n"),GetLastError());
goto Exit_MyDecryptFile;
}
// 为keyblob分配内存,读出的长度要拿第一个字节
dwKeyBlobLen = dwKeyBlobLen & 0x000000FF;
if (!(pbKeyBlob = (PBYTE)malloc(dwKeyBlobLen)))
{
MyHandleError(TEXT("Memory allocation error.\n"),E_OUTOFMEMORY);
}
if (!ReadFile(
hkeyblobsoucerFile,
pbKeyBlob,
dwKeyBlobLen,
&dwCount,
NULL))
{
MyHandleError(TEXT("Error reading key BLOB length!\n"),GetLastError());
goto Exit_MyDecryptFile;
}
//将key blob导入CSP容器
if (!CryptImportKey(
hCryptProv,
pbKeyBlob,
dwKeyBlobLen,
0,
0,
&hKey))
{
MyHandleError(TEXT("Error during CryptImportKey!/n"),GetLastError());
goto Exit_MyDecryptFile;
}
if (pbKeyBlob)
{
free(pbKeyBlob);
}
}
else
{
// 创建一个hash对象,将password hash以后再通过CryptDeriveKey得到密钥
if (!CryptCreateHash(
hCryptProv,
CALG_MD5,
0,
0,
&hHash))
{
MyHandleError(TEXT("Error during CryptCreateHash!\n"),GetLastError());
goto Exit_MyDecryptFile;
}
// Hash password后将hash信息保存在hHash中
if (!CryptHashData(
hHash,
(BYTE *)pszPassword,
lstrlen(pszPassword),
0))
{
MyHandleError(TEXT("Error during CryptHashData!\n"),GetLastError());
goto Exit_MyDecryptFile;
}
// 再使用已经对password的hash对象生成密钥
if (!CryptDeriveKey(
hCryptProv,
ENCRYPT_ALGORITHM,
hHash,
KEYLENGTH,
&hKey))
{
MyHandleError(TEXT("Error during CryptDeriveKey!\n"),GetLastError());
goto Exit_MyDecryptFile;
}
}
//每一次加密的字节长度,必须要是ENCRYPT_BLOCK_SIZE的整数倍
dwBlockLen = 1000 - 1000 % ENCRYPT_BLOCK_SIZE;
dwBufferLen = dwBlockLen;
// Allocate memory for the file read buffer.
if (!(pbBuffer = (PBYTE)malloc(dwBufferLen)))
{
MyHandleError(TEXT("Out of memory!\n"), E_OUTOFMEMORY);
goto Exit_MyDecryptFile;
}
//解密数据
bool fEOF = false;
do
{
//从要加密的文件每次读取dwBlockLen个字节进行加密
if (!ReadFile(
hSourceFile,
pbBuffer,
dwBlockLen,
&dwCount,
NULL))
{
MyHandleError(TEXT("Error reading from source file!\n"),GetLastError());
goto Exit_MyDecryptFile;
}
if (dwCount <= dwBlockLen)
{
fEOF = TRUE;
}
//解密数据
if (!CryptDecrypt(
hKey,
0,
fEOF,
0,
pbBuffer,
&dwCount))
{
MyHandleError(TEXT("Error during CryptDecrypt!\n"),GetLastError());
goto Exit_MyDecryptFile;
}
// 将解密后的数据写入目标文件.
if (!WriteFile(
hDestinationFile,
pbBuffer,
dwCount,
&dwCount,
NULL))
{
MyHandleError(TEXT("Error writing ciphertext.\n"),GetLastError());
goto Exit_MyDecryptFile;
}
} while (!fEOF);
fReturn = true;
Exit_MyDecryptFile:
//---------------------------------------------------------------
// Free the file read buffer.
if (pbBuffer)
{
free(pbBuffer);
}
//---------------------------------------------------------------
// Close files.
if (hSourceFile)
{
CloseHandle(hSourceFile);
}
if (hDestinationFile)
{
CloseHandle(hDestinationFile);
}
//-----------------------------------------------------------
// Release the hash object.
if (hHash)
{
if (!(CryptDestroyHash(hHash)))
{
MyHandleError(TEXT("Error during CryptDestroyHash.\n"),GetLastError());
}
hHash = NULL;
}
//---------------------------------------------------------------
// Release the session key.
if (hKey)
{
if (!(CryptDestroyKey(hKey)))
{
MyHandleError(TEXT("Error during CryptDestroyKey!\n"),GetLastError());
}
}
//---------------------------------------------------------------
// Release the provider handle.
if (hCryptProv)
{
if (!(CryptReleaseContext(hCryptProv, 0)))
{
MyHandleError(TEXT("Error during CryptReleaseContext!\n"),GetLastError());
}
}
getchar();
return fReturn;
}
void MyHandleError(LPTSTR psz, int nErrorNumber)
{
_ftprintf(stderr, TEXT("An error occurred in the program. \n"));
_ftprintf(stderr, TEXT("%s\n"), psz);
_ftprintf(stderr, TEXT("Error number %x.\n"), nErrorNumber);
}
已经加密的文件:
导入密钥文件:
解密后的文件: