微软在wincrypt.h中定义了大量的加解密算法的API,方便了软件加解密的实现,可以使我们不必关注密码学的算法,就可以实现高效率的软件加密。下面通过一个类,对API实现简单的封装。详细代码如下:
头文件:MyCryptOpt.h
#pragma once #include "windows.h" #include "wincrypt.h" #define MY_ENCODING_TYPE (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING) #define KEYLENGTH 0x00800000 #define ENCRYPT_ALGORITHM CALG_RC4 #define ENCRYPT_BLOCK_SIZE 8 class CMyCryptOpt { public: CMyCryptOpt(void); ~CMyCryptOpt(void); BOOL InitCrypt(); void DestroyCrypt(); BOOL MyEncryptFile(LPSTR lpSourceFile, LPSTR lpDestFile, LPSTR lpPassword); BOOL MyDecryptFile(LPSTR lpSourceFile, LPSTR lpDestFile, LPSTR lpPassword); protected: BOOL CryptProcess(LPSTR lpSourceFile, LPSTR lpDestFile, LPSTR lpPassword); private: FILE *m_hSource; FILE *m_hDestination; HCRYPTPROV m_hCryptProv; HCRYPTKEY m_hKey; HCRYPTHASH m_hHash; PBYTE m_pbBuffer; DWORD m_dwBlockLen; DWORD m_dwBufferLen; DWORD m_dwCount; };
源文件:MyCryptOpt.cpp
#include "StdAfx.h" #include "MyCryptOpt.h" CMyCryptOpt::CMyCryptOpt(void) { } CMyCryptOpt::~CMyCryptOpt(void) { } BOOL CMyCryptOpt::InitCrypt() { // 获得一个CSP句柄 if (!CryptAcquireContext(&m_hCryptProv,NULL,NULL,PROV_RSA_FULL,0)) { if (!CryptAcquireContext( &m_hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET)) { OutputDebugString("CryptAcquireContext() error!"); return FALSE; } } // 创建一个会话密钥 if (!CryptCreateHash( m_hCryptProv, CALG_MD5, 0, 0, &m_hHash)) { OutputDebugString("CryptCreateHash() error!"); return FALSE; } return TRUE; } void CMyCryptOpt::DestroyCrypt() { // close files if (m_hSource) fclose(m_hSource); if (m_hDestination) fclose(m_hDestination); // free memory if (m_pbBuffer) free(m_pbBuffer); // destroy session key if (m_hKey) CryptDestroyKey(m_hKey); // destroy hash object CryptDestroyHash(m_hHash); m_hHash = NULL; // Release provider handle if (m_hCryptProv) CryptReleaseContext(m_hCryptProv,0); } BOOL CMyCryptOpt::MyEncryptFile(LPSTR lpSourceFile, LPSTR lpDestFile, LPSTR lpPassword) { // process for encrypt if (!CryptProcess(lpSourceFile,lpDestFile,lpPassword)) return FALSE; // 加密源文件,并将加密后数据写入目标文件 do { // read source file m_dwCount = fread(m_pbBuffer,1,m_dwBlockLen,m_hSource); if (ferror(m_hSource)) { OutputDebugString("读写源文件错误!"); return FALSE; } // encrypt data if (!CryptEncrypt( m_hKey, 0, feof(m_hSource), 0, m_pbBuffer, &m_dwCount, m_dwBufferLen)) { OutputDebugString("CryptEncrypt() failed!"); return FALSE; } // write data to file fwrite(m_pbBuffer,1,m_dwCount,m_hDestination); if (ferror(m_hDestination)) { OutputDebugString("write file error!"); return FALSE; } } while (!feof(m_hSource)); return TRUE; } BOOL CMyCryptOpt::MyDecryptFile(LPSTR lpSourceFile, LPSTR lpDestFile, LPSTR lpPassword) { // process for decrypt if (!CryptProcess(lpSourceFile,lpDestFile,lpPassword)) return FALSE; // 解密源文件,并将解密后数据写入目标文件 do { // read source file m_dwCount = fread(m_pbBuffer,1,m_dwBlockLen,m_hSource); if (ferror(m_hSource)) { OutputDebugString("读写源文件错误!"); return FALSE; } // decrypt data if (!CryptDecrypt( m_hKey, 0, feof(m_hSource), 0, m_pbBuffer, &m_dwCount)) { OutputDebugString("CryptEncrypt() failed!"); return FALSE; } // write data to file fwrite(m_pbBuffer,1,m_dwCount,m_hDestination); if (ferror(m_hDestination)) { OutputDebugString("write file error!"); return FALSE; } } while (!feof(m_hSource)); return TRUE; } BOOL CMyCryptOpt::CryptProcess(LPSTR lpSourceFile, LPSTR lpDestFile, LPSTR lpPassword) { // 打开要加密的源文件 m_hSource = fopen(lpSourceFile,"rb"); if (!m_hSource) { OutputDebugString("open source file failed!"); return FALSE; } // 打开加密后产生的目标文件 m_hDestination = fopen(lpDestFile,"wb"); if (!m_hDestination) { OutputDebugString("open destination file failed!"); return FALSE; } // 用输入的密码产生一个散列 if (!CryptHashData( m_hHash, (BYTE*)lpPassword, strlen(lpPassword), 0)) { OutputDebugString("CryptHashData() failed!"); return FALSE; } // 通过散列生成会话密钥 if (!CryptDeriveKey( m_hCryptProv, ENCRYPT_ALGORITHM, m_hHash, KEYLENGTH, &m_hKey)) { OutputDebugString("CryptDeriveKey() failed!"); return FALSE; } // 因为加密算法是按ENCRYPT_BLOCK_SIZE 大小的块加密的,所以被加密的 // 数据长度必须是ENCRYPT_BLOCK_SIZE 的整数倍。下面计算一次加密的 // 数据长度。 m_dwBlockLen = 1000 - 1000 % ENCRYPT_BLOCK_SIZE; // Determine the block size. If a block cipher is used, // it must have room for an extra block. if (ENCRYPT_BLOCK_SIZE > 1) { m_dwBufferLen = m_dwBlockLen + ENCRYPT_BLOCK_SIZE; } else { m_dwBufferLen = m_dwBlockLen; } // 为缓冲区分配内存 m_pbBuffer = (BYTE*)malloc(m_dwBufferLen); if (!m_pbBuffer) { OutputDebugString("分配内存错误!"); return FALSE; } return TRUE; }