MicroSoft CryptoAPI data/file encrypt/decrypt
linux 用第三方庫(kù) Crypto++, 還未實(shí)戰(zhàn)。
CryptoAPI使用兩種密鑰:會(huì)話(huà)密鑰與公共/私人密鑰對(duì)。會(huì)話(huà)密鑰使用相同的加密和解密密鑰,這種算法較快,但必須保證密鑰的安全傳遞。公共/私人密鑰對(duì)使用一個(gè)公共密鑰和一個(gè)私人密鑰,私人密鑰只有專(zhuān)人才能使用,公共密鑰可以廣泛傳播。如果密鑰對(duì)中的一個(gè)用于加密,另一個(gè)一定用于解密。公共/私人密鑰對(duì)算法很慢,一般只用于加密小批數(shù)據(jù),例如用于加密會(huì)話(huà)密鑰。
?
#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, //這個(gè)參數(shù)這里用的是缺省值,指得是缺省得CSP模塊,你也可以傳入一個(gè)LPCTSTR類(lèi)型的字符串,指定CSP模塊 ??
PROV_RSA_FULL, //這里為使用的加密策略 ??0
);
返回true, 則正常; false, 則異常
?
二. 創(chuàng)建密鑰
1. 根據(jù)固定password, 主要用于對(duì)稱(chēng)加密
//初始化一個(gè)HASH對(duì)象,產(chǎn)生一個(gè)空的HASH對(duì)象
CryptCreateHash( ??
hCryptProv,?? //密鑰容器句柄 ??
CALG_MD5, //指定的hash算法
0, ??
0, ??
&hHash? //hash句柄
);
//對(duì)數(shù)據(jù)使用hash后, 保存在hHash中
CryptHashData( ??
hHash, ??
(BYTE *)pszPassword,?? //LPTSTR pszPassword ??
lstrlen(pszPassword), ??
0
);
//利用hash對(duì)象生成密鑰
CryptDeriveKey(? //從某一數(shù)據(jù)產(chǎn)生會(huì)話(huà)密鑰。有點(diǎn)類(lèi)似CryptGenKey,但是產(chǎn)生的會(huì)話(huà)密鑰來(lái)自固定數(shù)據(jù),而CryptGenKey是隨機(jī)產(chǎn)生的。并且不能產(chǎn)生公 / 私鑰對(duì) ??
hCryptProv,?? //密鑰容器句柄 ??
ENCRYPT_ALGORITHM, //in,指定的算法,類(lèi)似CryptGenKey ??
hHash, //in,HASH對(duì)象的句柄 ??
KEYLENGTH, //in,指定產(chǎn)生密鑰的類(lèi)型 ??
&hKey);??? //in, out, 產(chǎn)生的密鑰句柄地址
?
2. 隨機(jī)產(chǎn)生, 每次產(chǎn)生都不一樣,解密時(shí),要根據(jù)獲取的blob解密, 主要用于非對(duì)稱(chēng)加密
//產(chǎn)生一個(gè)隨機(jī)的交換密鑰或者公/私鑰對(duì)
CryptGenKey(?
hCryptProv,?? //密鑰容器句柄 ??
ENCRYPT_ALGORITHM,? //表明產(chǎn)生私鑰所使用的算法或者公鑰生成的算法 ??
KEYLENGTH | CRYPT_EXPORTABLE, //表示密鑰使用的長(zhǎng)度,參數(shù)可以為0,采用默認(rèn)的密鑰長(zhǎng)度 ??
&hKey? //獲取密鑰句柄
);
?
//獲取交換密鑰
CryptGetUserKey( ??
hCryptProv,?? //密鑰容器句柄 ??
AT_KEYEXCHANGE, //AT_KEYEXCHANGE(交換密鑰) or AT_SIGNATURE(簽名密鑰) ??
&hXchgKey? //獲取交換密鑰
);
//以下3步是用交換密鑰將密鑰加密后,存儲(chǔ)到Blob
a. 導(dǎo)出密鑰只是先獲取導(dǎo)出key Blob的長(zhǎng)度
CryptExportKey( ??
hKey, //需要導(dǎo)出的密鑰句柄 ??
hXchgKey, //將待導(dǎo)出密鑰用交換密鑰進(jìn)行加密,假如是公開(kāi)的BLOG當(dāng)然就設(shè)置為0 ??
SIMPLEBLOB, // 指定導(dǎo)出的密鑰BLOB類(lèi)型,BLOB也就是一種存儲(chǔ)結(jié)構(gòu)。六個(gè)參數(shù)見(jiàn)MSDN ??
0, ??
NULL, //導(dǎo)出的數(shù)據(jù)指針,以后就可以將這個(gè)數(shù)據(jù)寫(xiě)如磁盤(pán)或者別的任務(wù) ??
&dwKeyBlobLen? //導(dǎo)出的數(shù)據(jù)長(zhǎng)度
);
b. 為Blob分配內(nèi)存
pbKeyBlob = (BYTE *)malloc(dwKeyBlobLen);
c. 用交換密鑰加密后,存儲(chǔ)到Blob
CryptExportKey( ???hKey, ???hXchgKey, ???SIMPLEBLOB, ???0, ???pbKeyBlob, ???&dwKeyBlobLen);
//釋放交換密鑰 if(hXchgKey) ?
CryptDestroyKey(hXchgKey);
//創(chuàng)建導(dǎo)出的Keyblob目標(biāo)文件
hexportkeyDestinationFile ?= CreateFile(pszexportkeyDestination, ??FILE_WRITE_DATA, ??FILE_SHARE_READ, ??NULL, ??OPEN_ALWAYS, ??FILE_ATTRIBUTE_NORMAL, ??NULL);
//將keyblob長(zhǎng)度保存到文件中
WriteFile( ??hexportkeyDestinationFile, ??&dwKeyBlobLen, ??sizeof(DWORD), ??&dwCount, ??NULL)
//將keyblob內(nèi)容寫(xiě)入
WriteFile( ???hexportkeyDestinationFile, ???pbKeyBlob, ???dwKeyBlobLen, ???&dwCount, ???NULL);
free(pbKeyBlob);
?
3. 根據(jù)key產(chǎn)生固定的blob產(chǎn)生, 用于對(duì)稱(chēng)加密
#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;??? //結(jié)構(gòu)參考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)) ?
{
}
}
?
三. 解密
經(jīng)過(guò)一和二,the session key(會(huì)話(huà)密鑰)就創(chuàng)建好了,如果不是隨機(jī)產(chǎn)生出來(lái)的,the session key(會(huì)話(huà)密鑰)就被寫(xiě)到文件中或保存起來(lái)以便解密時(shí)用
由password或key產(chǎn)生的hKey, 可由CrytImportKey導(dǎo)入
CryptImportKey(m_hProv, (BYTE*)m_pstKeyBlob, sizeof(stKeyBlobType), 0, 0, &m_hKey)); //獲取key句柄
?
?四. 代碼
1. 根據(jù)key產(chǎn)生固定的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;??? //結(jié)構(gòu)參考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. 根據(jù)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. 隨機(jī)產(chǎn)生hKey, 每次都不一樣
來(lái)自微軟的例子。
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
?
轉(zhuǎn)載于:https://www.cnblogs.com/henryliublog/p/10287327.html
總結(jié)
以上是生活随笔為你收集整理的MicroSoft CryptoAPI data/file encrypt/decrypt的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Hadoop 之 MapReduce 的
- 下一篇: 学习最大流问题推荐几个好的博客