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
MicroSoft CryptoAPI data/file encrypt/decrypt的更多相关文章
- Can Microsoft’s exFAT file system bridge the gap between OSes?
转自:http://arstechnica.com/information-technology/2013/06/review-is-microsofts-new-data-sharing-syste ...
- 【MySQL】InnoDB: Error: checksum mismatch in data file 报错
参考:http://www.jb51.net/article/66951.htm 用5.7版本启动原5.5实例后,再用5.5启动出现以下报错 InnoDB: Error: checksum misma ...
- 使用 Microsoft.ApplicationBlocks.Data SqlHelper 查询超时以及解决方案
提示: 后面附有文件,不喜欢看吐槽的,直接到文章结尾下载 摘要:Data Access Application Block 是一个 .NET 组件,包含优化的数据访问代码,可以帮助用户调用存储过程以 ...
- ORA-01157报错"cannot identify/lock data file"解决
sqlplus以管理员方式接入数据库,启动时出现报错,如下: > sqlplus "/as sysdba" SQL> startup ...... ORA-01157: ...
- Unity3D发布WebPlayer时Failed to download data file解决方案
今天发布WebPlayer时, 发现直接打开html是可以正常运行的, 但是通过iis访问的话就会报错: Failed to download data file. 一开始以为是防火墙, 后来发现不是 ...
- [OpenGL] mac上运行NateRobin的OpenGL教程找不到 data file 解决方案
之前买的OpenGL编程指南第七版一直没看,最近开始看了,然后按照教程推荐的去指定网址下载NateRobin的OpenGL教程,但发现网址已经提示Error:404了, 然后谷歌搜索到可用的下载网址为 ...
- 1816647 - Error "Data file of SAP Note is incomplete" uploading a note in SNOTE
ymptom When uploading an SAP Note in transaction SNOTE you receive the error "Data file of SAP ...
- A very simple C++ module to encrypt/decrypt strings based on B64 and Vigenere ciper.
A very simple C++ module to encrypt/decrypt strings based on B64 and Vigenere ciper. https://github. ...
- mysql5.7服务器The innodb_system data file 'ibdata1' must be writable导致无法启动服务器
现象如下:The innodb_system data file 'ibdata1' must be writable. 解决方案如下: 1.关闭mysqld进程: 2.删除配置文件中datadir所 ...
随机推荐
- SimpleDateFormat日期格式解析
先看一个代码示例: import java.text.SimpleDateFormat; import java.util.Date; public class test{ public static ...
- SQLServer删除重复行
1.如果有ID字段,就是具有唯一性的字段 delect table where id not in ( select max(id) from table group by col1,col2,col ...
- Luogu 3371【模板】单源最短路径
Luogu 3371[模板]单源最短路径 第一次写博客用图论题来试一试 接下来是正文部分 题目描述 如题,给出一个有向图,请输出从某一点出发到所有点的最短路径长度. 输入输出格式 输入格式: 第一行包 ...
- iOS cocoapods 速度过慢问题
这个问题真的困扰了很久,虽然我也开了shadowsocks,但是我不知道git命令默认是不走shadowsocks的,所以速度慢的很. 今天拜读了 https://blog.csdn.net/wuqu ...
- css 生成图片添加的十字
<span class="add" title="继续上传"></span> .add { display: inline-block; ...
- Eclipse install new software无反应
一个问题可以有不同的解决方案 其他人提供了不少方案 我遇到了这个问题 但是这些解决方案都无济于事 于是 我就采取了一个新方案: 然后重新解压,找到里面的eclipse.exe重新打开就可以了 现在有反 ...
- js数据结构与算法——二叉树
function BinaryTree(){ var Node = function(key){ this.key = key; //值 this.left = null; //左箭头 this.ri ...
- 使用gethostname()函数和gethostbyname()函数获取主机相关信息
gethostname() : 返回本地主机的标准主机名. 原型如下: #include <unistd.h> int gethostname(char *name, size_t len ...
- mui slider禁止滑动
网上方法: mui('.mui-slider').slider().setStopped(true); 实际使用 mui('.mui-slider').slider().stopped = true; ...
- iOS 仿抖音 视频裁剪
1.最近做短视频拍摄.其中的裁剪界面要做得和抖音的视频裁剪效果一样 需求: 裁剪有一个最大裁剪时间.最小裁剪时间.左右拖动可以实时查看对应的视频画面.拖动进度条也能查看对应的画面 .拖动底部视图也能 ...