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的更多相关文章

  1. 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 ...

  2. 【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 ...

  3. 使用 Microsoft.ApplicationBlocks.Data SqlHelper 查询超时以及解决方案

     提示: 后面附有文件,不喜欢看吐槽的,直接到文章结尾下载 摘要:Data Access Application Block 是一个 .NET 组件,包含优化的数据访问代码,可以帮助用户调用存储过程以 ...

  4. ORA-01157报错"cannot identify/lock data file"解决

    sqlplus以管理员方式接入数据库,启动时出现报错,如下: > sqlplus "/as sysdba" SQL> startup ...... ORA-01157: ...

  5. Unity3D发布WebPlayer时Failed to download data file解决方案

    今天发布WebPlayer时, 发现直接打开html是可以正常运行的, 但是通过iis访问的话就会报错: Failed to download data file. 一开始以为是防火墙, 后来发现不是 ...

  6. [OpenGL] mac上运行NateRobin的OpenGL教程找不到 data file 解决方案

    之前买的OpenGL编程指南第七版一直没看,最近开始看了,然后按照教程推荐的去指定网址下载NateRobin的OpenGL教程,但发现网址已经提示Error:404了, 然后谷歌搜索到可用的下载网址为 ...

  7. 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 ...

  8. 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. ...

  9. mysql5.7服务器The innodb_system data file 'ibdata1' must be writable导致无法启动服务器

    现象如下:The innodb_system data file 'ibdata1' must be writable. 解决方案如下: 1.关闭mysqld进程: 2.删除配置文件中datadir所 ...

随机推荐

  1. Doom HDU - 5239 (找规律+线段树)

     题目链接: D - Doom  HDU - 5239  题目大意:首先是T组测试样例,然后n个数,m次询问,然后每一次询问给你一个区间,问你这个这段区间的加上上一次的和是多少,查询完之后,这段区间里 ...

  2. Numpy 多维数组简介

     NumPy是一个功能强大的Python库,主要用于对多维数组执行计算.NumPy这个词来源于两个单词-- Numerical和Python.NumPy提供了大量的库函数和操作,可以帮助程序员轻松地 ...

  3. git知识总结-2.git基本操作之操作汇总

    0.前言 一般来说,日常使用只要记住下图6个命令,就可以了.但是熟练使用,恐怕要记住60-100个命令. 上图分别为: Workspace:工作区 Index / Stage:暂存区 Reposito ...

  4. 【转】子类会调用父类的@PostConstruct方法

    如果一个类用@Service或@Component,那么只需要用@PostConstruct修饰某个方法,该方法能在类实例化的过程中自动执行,相当于类的构造函数.同时,具备了构造函数不具备的功能. @ ...

  5. 【codechef】FN/Fibonacci Number

    题意 给出 c 和 P ,求最小的非负整数 n 使得 \(Fib(n)=c(mod~ P)\) 其中 P 是质数且 模 10 等于一个完全平方数(也就是说 P 的末位是个完全平方数,那么只能是 1 或 ...

  6. PHP-高并发和大流量的解决方案

    一  高并发的概念在互联网时代,并发,高并发通常是指并发访问.也就是在某个时间点,有多少个访问同时到来. 二  高并发架构相关概念1.QPS (每秒查询率) : 每秒钟请求或者查询的数量,在互联网领域 ...

  7. Git初始配置和基本使用

    初次运行Git前的配置 本文是在安裝完git以后首先应做到一些配置,安装教程可以参考廖雪峰git教程 用户信息 当安装完 Git 应该做的第一件事就是设置你的用户名称与邮件地址. 这样做很重要,因为每 ...

  8. bzoj 2599

    还是点对之间的问题,果断上点分治 同样,把一条路径拆分成经过根节点的两条路径,对不经过根节点的路径递归处理 然后,我们逐个枚举根节点的子树,计算出子树中某一点到根节点的距离,然后在之前已经处理过的点中 ...

  9. Gradle安装步骤

    一. Gralde介绍 Gradle是基于Groovy语言的项目自动化建构工具,在使用Gradle之前常用的构建工具有Ant和Maven,使用这些工具我们可以用来管理项目依赖,打包,部署和发布等.使用 ...

  10. RAID磁盘阵列及CentOS7系统启动流程

    磁盘阵列(Redundant Arrays of Independent Disks,RAID),有“独立磁盘构成的具有冗余能力的阵列”之意,,数据读取无影响.将数据切割成许多区段,分别存放在各个硬盘 ...