CSP学习之导出密钥BLOB 解析
通过CryptExportKey( hKey, NULL, PUBLICKEYBLOB,0, NULL, &dwBlobLen)

#include <Windows.h>
#include <WinCrypt.h>
#include <stdio.h>
#include <tchar.h> #pragma comment(lib, "crypt32.lib") #define MY_ENCODING_TYPE (PKCS_7_ASN_ENCODING|X509_ASN_ENCODING) void HandleError(char * str)
{
printf("%s[%x]\n",str,GetLastError());
system("pause");
exit();
} int main(int argc, char* argv[])
{
HCRYPTPROV hCryptProv = NULL; //CSP句柄
LPCTSTR pszContainerName = TEXT("MyKeyContainer"); //CSP密钥容器句柄
HCRYPTKEY hKey = NULL;
BYTE* pbKeyBlob;
DWORD dwBlobLen; if(CryptAcquireContext(
&hCryptProv,
NULL,
NULL,
PROV_RSA_FULL,
))
{
printf("获取到");
_tprintf(TEXT("[%s]"), pszContainerName);
printf("的密钥容器\n");
}
else
{
//发生错误,如果是密钥容器不存在,则创建新的密钥容器
if (GetLastError() == NTE_BAD_KEYSET)
{
if (CryptAcquireContext(
&hCryptProv,
NULL,
NULL,
PROV_RSA_FULL,
CRYPT_NEWKEYSET))
{
printf("新的密钥容器已创建\n");
}
else
{
HandleError("无法创建密钥容器");
}
}
else
{
HandleError("无法获取CSP句柄");
}
} //获取一个加解密key句柄
if (CryptGetUserKey(hCryptProv, AT_KEYEXCHANGE, &hKey))
{
printf("获取到加解密key句柄\n");
}
else
{
if (GetLastError() == NTE_NO_KEY)
{
//因为没有密钥对, 创建一个
printf("密钥对不存在,创建一个密钥对\n");
if (CryptGenKey(hCryptProv, AT_KEYEXCHANGE,CRYPT_EXPORTABLE,&hKey))
{
printf("创建签名验签密钥对成功\n");
}
else
{
HandleError("创建密钥对失败");
}
}
else
{
HandleError("获取密钥对错误,签名验签密钥对不可用");
}
} //PUBLICKEYBLOB
//PRIVATEKEYBLOB
if(!(CryptExportKey( hKey, NULL, PUBLICKEYBLOB,, NULL, &dwBlobLen)))
{
HandleError("导出公钥信息失败");
} pbKeyBlob = (BYTE*)malloc(dwBlobLen); if(!(CryptExportKey( hKey, NULL, PUBLICKEYBLOB,, pbKeyBlob, &dwBlobLen)))
{
HandleError("导出公钥信息失败2;");
} printf("公钥BLOB信息如下:\n");
for(int i=;i<dwBlobLen;i++)
{
if (i % == )
{
printf("\n");
}
printf("%02X ", pbKeyBlob[i]);
}
printf("\n"); BLOBHEADER blobHeader;
RSAPUBKEY rsaPubkey;
PBYTE p = NULL;
p = pbKeyBlob;
//分析得到的BLOB
memcpy(&blobHeader.bType, p, );
p += ;
memcpy(&blobHeader.bVersion, p, );
p += ;
memcpy(&blobHeader.reserved, p, );
p += ;
memcpy(&blobHeader.aiKeyAlg, p, );
p += ; memcpy(&rsaPubkey.magic, p, );
p += ;
memcpy(&rsaPubkey.bitlen, p, );
p += ;
memcpy(&rsaPubkey.pubexp, p, );
p += ;
PBYTE reaMod = (PBYTE)LocalAlloc(LPTR, rsaPubkey.bitlen/);
memcpy(reaMod, p, rsaPubkey.bitlen/); //需要转换一下
BYTE bTemp;
for (int i=;i< rsaPubkey.bitlen//; i++)
{
bTemp = reaMod[i];
reaMod[i] = reaMod[rsaPubkey.bitlen/ - i - ];
reaMod[rsaPubkey.bitlen/- i - ] = bTemp;
} printf("BLOBHEADER.bType=[%02x]\n", blobHeader.bType);
printf("BLOBHEADER.bVersion=[%02x]\n", blobHeader.bVersion);
printf("BLOBHEADER.reserved=[%d]\n", blobHeader.reserved);
printf("BLOBHEADER.aiKeyAlg=[%d]\n\n", blobHeader.aiKeyAlg);
printf("rsaPubkey.magic=[");
char* q = (char *)&rsaPubkey.magic;
for (int i = ;i<;i++)
{
printf("%c",*q++);
} printf("]\nrsaPubkey.bitlen=[%d]\n", rsaPubkey.bitlen);
printf("rsaPubkey.pubexp=[%d]\n", rsaPubkey.pubexp);
printf("RSA MOD:\n");
for(int i=;i<rsaPubkey.bitlen/;i++)
{
if (i % == )
{
printf("\n");
}
printf("%02X ", reaMod[i]);
}
printf("\n"); //释放
LocalFree(reaMod); free(pbKeyBlob);
if (hKey)
{
CryptDestroyKey(hKey);
} if(hCryptProv)
{
CryptReleaseContext(hCryptProv, );
} if(CryptAcquireContext(
&hCryptProv,
NULL,
NULL,
PROV_RSA_FULL,
CRYPT_DELETEKEYSET))
{
printf("删除容器成功\n");
}
else
{
HandleError("删除容器失败");
}
system("pause");
return ;
}
结果如下:

导出私钥的代码跟导出公钥类似,修改CryptExportKey函数的第3个参数为PRIVATEKEYBLOB 即可。
CSP学习之导出密钥BLOB 解析的更多相关文章
- CSP学习之CryptoAPI初识
Crypto API目的就是提供开发者在windows下使用PKI的编程接口. Crypto 提供了很多的加解密相关函数,如编码.解码.加密解密,哈希,数字证书.证书管理证书存储等. 有关 ...
- Batik - 将svg转换成其他格式图片或PDF - [导出服务器配置] 导出服务器原理解析
导出服务器原理解析 Highcharts图表导出(或下载)本质上是将SVG代码转换为不同文件格式的过程,用到的工具是batik,所以所谓导出服务器,只不过是调用batik,将SVG代码转换并下载.下图 ...
- Android Animation学习(五) ApiDemos解析:容器布局动画 LayoutTransition
Android Animation学习(五) ApiDemos解析:容器布局动画 LayoutTransition Property animation系统还提供了对ViewGroup中的View改变 ...
- Android Animation学习(四) ApiDemos解析:多属性动画
Android Animation学习(四) ApiDemos解析:多属性动画 如果想同时改变多个属性,根据前面所学的,比较显而易见的一种思路是构造多个对象Animator , ( Animator可 ...
- Android Animation学习(三) ApiDemos解析:XML动画文件的使用
Android Animation学习(三) ApiDemos解析:XML动画文件的使用 可以用XML文件来定义Animation. 文件必须有一个唯一的根节点: <set>, <o ...
- Android Animation学习(二) ApiDemos解析:基本Animators使用
Android Animation学习(二) ApiDemos解析:基本Animatiors使用 Animator类提供了创建动画的基本结构,但是一般使用的是它的子类: ValueAnimator.O ...
- Android Animation学习(二) ApiDemos解析:基本Animatiors使用
Animator类提供了创建动画的基本结构,但是一般使用的是它的子类: ValueAnimator.ObjectAnimator.AnimatorSet ApiDemos中Animation部分是单独 ...
- Mybatis源码学习之parsing包(解析器)(二)
简述 大家都知道mybatis中,无论是配置文件mybatis-config.xml,还是SQL语句,都是写在XML文件中的,那么mybatis是如何解析这些XML文件呢?这就是本文将要学习的就是,m ...
- 简单学习一下ibd数据文件解析
来源:原创投稿 作者:花家舍 简介:数据库技术爱好者. GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源. 简单学习一下数据文件解析 这是尝试使用Golang语言简单解析My ...
随机推荐
- oracle调试存储过程不进去
右击存储过程,选中Add debug information即可
- docker 自定义镜像
step1:自定义镜像 原镜像 registry.aspider.avlyun.org/library/php-apache docker run -d --name xz_apache regist ...
- 控制台解析命行C#
//--------------------------------------------------------------------- /// <summary> /// Co ...
- vue 在路由中复用组件
首先需要在app.vue中引入: <template> <div id="app"> <!--<app-header></app-h ...
- Qt 学习之路 2(44):QFileSystemModel
Home / Qt 学习之路 2 / Qt 学习之路 2(44):QFileSystemModel Qt 学习之路 2(44):QFileSystemModel 豆子 2013年2月21日 Qt ...
- Vue 使用 axios post请求后台数据时 404
今天遇到Vue 使用 axios post请求后台数据时 404 使用postman 就能获取到 网上找了大半天 终于找到了解决方法,传送门:https://www.jianshu.com/p/b10 ...
- C++_标准模板库STL概念介绍3-函数对象
函数对象也叫做函数符(functor). 函数符是可以以函数方式和( )结合使用的任意对象. 包括函数名,指向函数的指针,重载了()运算符的类对象. 可以这样定义一个类: class Linear { ...
- SQL 随手记
SQL 学习片段: 建立一个简单的联系数据表, mobile_number char(11).mobile_province nvarchar(50).mobile_area nvarchar(200 ...
- Kibana6.x.x源码分析--ngReact使用
ngReact GitHub地址:https://github.com/ngReact/ngReact
- 欧拉图 欧拉回路 欧拉通路 Euler的认识 (转)
转:https://www.cnblogs.com/Ash-ly/p/5397702.html 定义: 欧拉回路:图G的一个回路,如果恰通过图G的每一条边,则该回路称为欧拉回路,具有欧拉回路的图称为欧 ...