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 ...
随机推荐
- Redhat系的Linux系统里,网络主要设置文件简介【转载】
以下是原文地址,转载请指明出处: http://blog.chinaunix.net/uid-26495963-id-3230810.html 一.配置文件详解在RHEL或者CentOS等Redhat ...
- scrapy 爬取天猫商品信息
spider # -*- coding: utf-8 -*- from urllib.parse import urlencode import requests import scrapy impo ...
- CF1137F Matches Are Not a Child's Play(树链剖分)
题面 我们定义一棵树的删除序列为:每一次将树中编号最小的叶子删掉,将该节点编号加入到当前序列的最末端,最后只剩下一个节点时将该节点的编号加入到结尾. 例如对于上图中的树,它的删除序列为:2 4 3 1 ...
- CSS中#和.的区别
id:用来定义页面中大的样式,如栏目划分,顶部,正文,底部等:用#top的形式来定义: class:用来定义一些比较细节的样式,如具体的一个菜单,一行文字等,用.text的形式来定义. 定义HTML中 ...
- php 其他格式数据与数组互转
class otherArr { private $char="UTF-8"; private $cvs_fege=","; // cvs 分割符 /**数组 ...
- 高精度的N进制转换模板(转K神)
/* 高精度进制转换 把oldBase 进制的数转化为newBase 进制的数输出. 调用方法,输入str, oldBase newBase. change(); solve(); output(); ...
- POJ - 1733 离散化 并查集
题意:求问数列区间奇偶信息正确与否 和上一题一样(甚至弱化),加个离散就ok啦 #include<iostream> #include<algorithm> #include& ...
- 1144 The Missing Number (20 分)
Given N integers, you are supposed to find the smallest positive integer that is NOT in the given li ...
- Oracle SET UNUSED的用法
SET UNUSED的用法 原理:清楚掉字典信息(撤消存储空间),不可恢复. 可以使用 SET UNUSED选项标记一列或者多列不可用. 使用DROP SET UNUSED选项删除被被标记 ...
- 腾讯云(Linux)安装.net core sdk2.1、net core runtime2.1
按照微软指令安装: sdk2.1:https://www.microsoft.com/net/download/linux-package-manager/centos/sdk-current 1. ...