MicroSoft CryptoAPI data/file encrypt/decrypt
linux 用第三方庫 Crypto++, 還未實戰。
CryptoAPI使用兩種密鑰:會話密鑰與公共/私人密鑰對。會話密鑰使用相同的加密和解密密鑰,這種算法較快,但必須保證密鑰的安全傳遞。公共/私人密鑰對使用一個公共密鑰和一個私人密鑰,私人密鑰只有專人才能使用,公共密鑰可以廣泛傳播。如果密鑰對中的一個用于加密,另一個一定用于解密。公共/私人密鑰對算法很慢,一般只用于加密小批數據,例如用于加密會話密鑰。
?
#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
?
常用步驟:
一. 獲取容器handle
CryptAcquireContext( ??
&hCryptProv, //返回的CSP句柄,密鑰容器 ??
NULL,?? //密鑰容器的名字 ??
MS_ENHANCED_PROV, //這個參數這里用的是缺省值,指得是缺省得CSP模塊,你也可以傳入一個LPCTSTR類型的字符串,指定CSP模塊 ??
PROV_RSA_FULL, //這里為使用的加密策略 ??0
);
返回true, 則正常; false, 則異常
?
二. 創建密鑰
1. 根據固定password, 主要用于對稱加密
//初始化一個HASH對象,產生一個空的HASH對象
CryptCreateHash( ??
hCryptProv,?? //密鑰容器句柄 ??
CALG_MD5, //指定的hash算法
0, ??
0, ??
&hHash? //hash句柄
);
//對數據使用hash后, 保存在hHash中
CryptHashData( ??
hHash, ??
(BYTE *)pszPassword,?? //LPTSTR pszPassword ??
lstrlen(pszPassword), ??
0
);
//利用hash對象生成密鑰
CryptDeriveKey(? //從某一數據產生會話密鑰。有點類似CryptGenKey,但是產生的會話密鑰來自固定數據,而CryptGenKey是隨機產生的。并且不能產生公 / 私鑰對 ??
hCryptProv,?? //密鑰容器句柄 ??
ENCRYPT_ALGORITHM, //in,指定的算法,類似CryptGenKey ??
hHash, //in,HASH對象的句柄 ??
KEYLENGTH, //in,指定產生密鑰的類型 ??
&hKey);??? //in, out, 產生的密鑰句柄地址
?
2. 隨機產生, 每次產生都不一樣,解密時,要根據獲取的blob解密, 主要用于非對稱加密
//產生一個隨機的交換密鑰或者公/私鑰對
CryptGenKey(?
hCryptProv,?? //密鑰容器句柄 ??
ENCRYPT_ALGORITHM,? //表明產生私鑰所使用的算法或者公鑰生成的算法 ??
KEYLENGTH | CRYPT_EXPORTABLE, //表示密鑰使用的長度,參數可以為0,采用默認的密鑰長度 ??
&hKey? //獲取密鑰句柄
);
?
//獲取交換密鑰
CryptGetUserKey( ??
hCryptProv,?? //密鑰容器句柄 ??
AT_KEYEXCHANGE, //AT_KEYEXCHANGE(交換密鑰) or AT_SIGNATURE(簽名密鑰) ??
&hXchgKey? //獲取交換密鑰
);
//以下3步是用交換密鑰將密鑰加密后,存儲到Blob
a. 導出密鑰只是先獲取導出key Blob的長度
CryptExportKey( ??
hKey, //需要導出的密鑰句柄 ??
hXchgKey, //將待導出密鑰用交換密鑰進行加密,假如是公開的BLOG當然就設置為0 ??
SIMPLEBLOB, // 指定導出的密鑰BLOB類型,BLOB也就是一種存儲結構。六個參數見MSDN ??
0, ??
NULL, //導出的數據指針,以后就可以將這個數據寫如磁盤或者別的任務 ??
&dwKeyBlobLen? //導出的數據長度
);
b. 為Blob分配內存
pbKeyBlob = (BYTE *)malloc(dwKeyBlobLen);
c. 用交換密鑰加密后,存儲到Blob
CryptExportKey( ???hKey, ???hXchgKey, ???SIMPLEBLOB, ???0, ???pbKeyBlob, ???&dwKeyBlobLen);
//釋放交換密鑰 if(hXchgKey) ?
CryptDestroyKey(hXchgKey);
//創建導出的Keyblob目標文件
hexportkeyDestinationFile ?= CreateFile(pszexportkeyDestination, ??FILE_WRITE_DATA, ??FILE_SHARE_READ, ??NULL, ??OPEN_ALWAYS, ??FILE_ATTRIBUTE_NORMAL, ??NULL);
//將keyblob長度保存到文件中
WriteFile( ??hexportkeyDestinationFile, ??&dwKeyBlobLen, ??sizeof(DWORD), ??&dwCount, ??NULL)
//將keyblob內容寫入
WriteFile( ???hexportkeyDestinationFile, ???pbKeyBlob, ???dwKeyBlobLen, ???&dwCount, ???NULL);
free(pbKeyBlob);
?
3. 根據key產生固定的blob產生, 用于對稱加密
#define ENCRYPT_ALGORITHM CALG_DES
#define ENCRYPT_BLOCK_SIZE 8
#define KEYSIZE 8
typedef struct _stKeyBlob
{ ?
BLOBHEADER hdr; ?
DWORD cbKeySize; ?
BYTE rgbKeyData[KEYSIZE];
?_stKeyBlob() ?
{ ??
hdr.bType = PLAINTEXTKEYBLOB; ??
hdr.bVersion = CUR_BLOB_VERSION; ??
hdr.reserved = 0; ??
hdr.aiKeyAlg = ENCRYPT_ALGORITHM; ??
cbKeySize = KEYSIZE; ??
memset(rgbKeyData, 0, KEYSIZE); ?
}
} stKeyBlobType;??? //結構參考MSDN - CryptImportKey
?
XML_EnDecryption::XML_EnDecryption(BYTE pbKey[], DWORD dwKeyLen)
{
? init(); ?m_pstKeyBlob = new stKeyBlobType(); ?
?memcpy(m_pstKeyBlob->rgbKeyData, pbKey, dwKeyLen > KEYSIZE ? KEYSIZE : dwKeyLen);
?if (!CryptImportKey(m_hProv, (BYTE*)m_pstKeyBlob, sizeof(stKeyBlobType), 0, 0, &m_hKey)) ?
{
}
}
?
三. 解密
經過一和二,the session key(會話密鑰)就創建好了,如果不是隨機產生出來的,the session key(會話密鑰)就被寫到文件中或保存起來以便解密時用
由password或key產生的hKey, 可由CrytImportKey導入
CryptImportKey(m_hProv, (BYTE*)m_pstKeyBlob, sizeof(stKeyBlobType), 0, 0, &m_hKey)); //獲取key句柄
?
?四. 代碼
1. 根據key產生固定的blob
#ifndef _XMLENCDEC_H_EFOFWEJOSDJFJ3933F3F894FJ3F23OFJ230FJFJWEFJWWEFWE
#define _XMLENCDEC_H_EFOFWEJOSDJFJ3933F3F894FJ3F23OFJ230FJFJWEFJWWEFWE
#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_DES #define ENCRYPT_BLOCK_SIZE 8
#define KEYSIZE 8
typedef struct _stKeyBlob
{ ?
BLOBHEADER hdr; ?
DWORD cbKeySize; ?
BYTE rgbKeyData[KEYSIZE];
? _stKeyBlob() ?
{ ??
hdr.bType = PLAINTEXTKEYBLOB; ??
hdr.bVersion = CUR_BLOB_VERSION; ??
hdr.reserved = 0; ??
hdr.aiKeyAlg = ENCRYPT_ALGORITHM; ??
cbKeySize = KEYSIZE; ??
memset(rgbKeyData, 0, KEYSIZE); ?
}
} stKeyBlobType;??? //結構參考MSDN - CryptImportKey
?
class XML_EnDecryption
{
public: ?
XML_EnDecryption(BYTE pbKey[] = NULL, DWORD dwKeyLen = 0); ?
virtual ~XML_EnDecryption();
? void GetLastCryptError(LPTSTR psz, int nErrorNumber);
? BOOL DES(__in const BYTE* pbData, __in DWORD cbDataLen, __out BYTE* pbBuf, __inout DWORD* pcbBufLen, __in BOOL bIsDecrypt = FALSE, __in BOOL isLast = TRUE);
? void GetBufferLen(__in const BYTE* pbData, __in DWORD cbDataLen, DWORD* pBufferLen);
? BOOL XmlEncDec(LPTSTR pszSourceFile, LPTSTR pszDestinationFile, BOOL isDecrypt = FALSE);
private: ?
bool init(); ?
bool InitialCSP(); ?
bool IsCSPValided(); ?
bool ReleaseCSP();
private: ?
HCRYPTPROV?m_hProv; ?
bool??m_bAcquireContextOK;
? HCRYPTKEY?m_hKey;
? DWORD m_dwLastError;
? stKeyBlobType* m_pstKeyBlob;
};
#endif? //_PUBLIC_H_EFOFWEJOSDJFJ3933F3F894FJ3F23OFJ230FJFJWEFJWWEFWE
?
2. 根據password, hash后得到hKey
#ifndef _XMLENCDEC_H_EFOFWEJOSDJFJ3933F3F894PEPROGEPROGPOEPWEOVWOEVOWEV
#define _XMLENCDEC_H_EFOFWEJOSDJFJ3933F3F894PEPROGEPROGPOEPWEOVWOEVOWEV
#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
?
class XML_EnDecryption
{
public: ?
XML_EnDecryption(LPTSTR m_pszPassword); ?
virtual ~XML_EnDecryption();
? void GetBufferLen(__in const BYTE* pbData, __in DWORD cbDataLen, DWORD* pBufferLen);
? BOOL DES(__in const BYTE* pbData, __in DWORD cbDataLen, __out BYTE* pbBuf, __inout DWORD* pcbBufLen, __in BOOL bIsDecrypt = FALSE, __in BOOL isLast = TRUE);
? BOOL XmlDes(LPTSTR pszSourceFile, LPTSTR pszDestinationFile, BOOL isDecrypt = FALSE);
? void GetLastCryptError(LPTSTR psz, int nErrorNumber); ? private: //?int getKey(); ?bool HashPassword();
private: ?
bool init(); ?
bool ReleaseCSP(); ?
bool InitialCSP(); ?
bool IsCSPValided();
private: ?
HCRYPTPROV?m_hProv; ?
bool??m_bAcquireContextOK; ?
HCRYPTHASH? m_hHash; ?
HCRYPTKEY?m_hKey; ?
DWORD m_dwLastError; ?
LPTSTR m_pszPassword;
};
#endif? //_XMLENCDEC_H_EFOFWEJOSDJFJ3933F3F894PEPROGEPROGPOEPWEOVWOEVOWEV
?
3. 隨機產生hKey, 每次都不一樣
來自微軟的例子。
https://docs.microsoft.com/zh-cn/windows/desktop/SecCrypto/example-c-program-encrypting-a-file
https://docs.microsoft.com/zh-cn/windows/desktop/SecCrypto/example-c-program-decrypting-a-file
?
轉載于:https://www.cnblogs.com/henryliublog/p/10287327.html
總結
以上是生活随笔為你收集整理的MicroSoft CryptoAPI data/file encrypt/decrypt的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Hadoop 之 MapReduce 的
- 下一篇: 学习最大流问题推荐几个好的博客