解析P12证书

解析P12证书1.从磁盘上的证书文件中读取证书数据unsignedchar*pbP12Data;//证书数据unsignedlongulP12DataLen;//证书数据长度2.让用户输入证书密码char*szPwd;//证书密码3.将证书密码转换成UNICODE格式(最好采用二次调用方式)LPWSTRpWideChar=NULL;int

大家好,又见面了,我是你们的朋友全栈君。1.从磁盘上的证书文件中读取证书数据

unsigned char* pbP12Data; // 证书数据

unsigned long ulP12DataLen; // 证书数据长度

2.让用户输入证书密码

char* szPwd; // 证书密码

3.将证书密码转换成UNICODE格式(最好采用二次调用方式)

LPWSTR pWideChar = NULL;

int nWideChar = 0;

nWideChar = MultiByteToWideChar(CP_ACP, 0, szPwd, -1, pWideChar, nWideChar);

pWideChar = new WCHAR[nWideChar];

memset(pWideChar, 0, sizeof(WCHAR)*nWideChar);

MultiByteToWideChar(CP_ACP, 0, szPwd, -1, pWideChar, nWideChar);

4.将证书数据导入临时store

CRYPT_DATA_BLOB blob;

memset(&blob, 0, sizeof(blob));

blob.pbData = pbP12Data;

blob.cbData = ulP12DataLen;

HCERTSTORE hCertStore = NULL;

hCertStore = PFXImportCertStore(&blob, pWideChar, CRYPT_EXPORTABLE);

5.在store中查找证书,获取CertContext

PCCERT_CONTEXT pCertContext = CertFindCertificateInStore(hCertStore, X509_ASN_ENCODING|PKCS_7_ASN_ENCODING, 0, CERT_FIND_ANY, NULL, NULL);

6.获取证书信息

CRYPT_INTEGER_BLOB snBlob = pCertContext->pCertInfo->SerialNumber; // 证书SN

pCertContext->pbCertEncoded; // X509格式证书数据

pCertContext->cbCertEncoded; // X509格式证书数据长度

7.获取CSP句柄

HCRYPTPROV hProv = NULL;

DWORD dwKeySpec = 0;

BOOL bCallerFreeProv = FALSE;

CryptAcquireCertificatePrivateKey(pCertContext, 0, NULL, &hProv, &dwKeySpec, &bCallerFreeProv);

8.获取密钥句柄

HCRYPTKEY hKey = NULL;

CryptGetUserKey(hProv, dwKeySpec, &hKey);

9.导出私钥(最好采用二次调用方式)

BYTE* pbData = NULL;

DWORD dwDataLen = 0;

CryptExportKey(hKey, NULL, PRIVATEKEYBLOB, 0, pbData, &dwDataLen);

pbData = new BYTE[dwDataLen];

memset(pbData, 0, dwDataLen);

CryptExportKey(hKey, NULL, PRIVATEKEYBLOB, 0, pbData, &dwDataLen);

10.获取公私钥信息

BYTE *p = pbData+ sizeof(PUBLICKEYSTRUC); 

(*(RSAPUBKEY*)p).bitlen; // 公私钥模长(以bit为单位)

(*(RSAPUBKEY*)p).pubexp; // 公钥的e(注意字节顺序)

p += sizeof(RSAPUBKEY); // 公私钥的n(注意字节顺序)

p += ((*(RSAPUBKEY*)p).bitlen)/8; // 私钥的p(注意字节顺序)

p += ((*(RSAPUBKEY*)p).bitlen)/16; // 私钥的q(注意字节顺序)

p += ((*(RSAPUBKEY*)p).bitlen)/16; // 私钥的dp(注意字节顺序)

p += ((*(RSAPUBKEY*)p).bitlen)/16; // 私钥的dq(注意字节顺序)

p += ((*(RSAPUBKEY*)p).bitlen)/16; // 私钥的qu(注意字节顺序)

p += ((*(RSAPUBKEY*)p).bitlen)/16; // 私钥的d(注意字节顺序)

11.清理工作

delete[] pbData;

pbData = NULL;

CryptDestroyKey(hKey);

CryptReleaseContext(hProv, 0);

CertFreeCertificateContext(pCertContext);

CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);

delete[] pWideChar;

pWideChar = NULL;

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/148171.html原文链接:https://javaforall.net

赞 (0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • FDD 与 TDD LTE区别

    FDD 与 TDD LTE区别虽然国内4G牌照迟迟不见发布,但私底下各大运营商和终端商早已摩拳擦掌,各网用户尤其是备受折磨的中国移动用户也都在期待4G时代的到来。放眼望去,目前在全球81个国家已有213张LTE商用网络,其中FDD-LTE商用网络192张、TD-LTE商用网络11张,而中国4G如箭在弦,被认为是一场由中国移动积极促成的产业大跃进。随着大家不断谈论4G,相关的新名词也不断涌现,包括不同制式的网

    2022年5月30日
  • java常用类之Calendar类[通俗易懂]

    java常用类之Calendar类[通俗易懂]java常用类之Calendar类Calendar类提供了获取或者设置各种日历的字段的方法。构造方法protectedCalendar():由于修饰符是prodected;所以无法直接创建该对象其他方法方法名说明staticCalendargetInstance()使用默认时区或区域获取日历voidset(intyear,intmonth,intdate,inthourofday,intminute,intsecond)设置日历的时分秒

    2022年9月15日
  • 调用so库文件以及里面的方法「建议收藏」

    调用so库文件以及里面的方法「建议收藏」之前文章写过一篇JNI生成so库文件 并调用里面的方法手把手教你—JNI的实现实际开发中 so库是别人给你的,不是你自己写的没所以就要用别人的so库文件。有很多情况,有一种是比较简单的:既有so库文件又有对应的jar包,这样的话 直接就可以调用里面的方法了。第二种比较坑爹,限制也比较多,所以现在就主要研究一下第二种吧(只有so库 其他什么都没有)第一

    2022年6月16日
  • 再学C++ Primer(11)-模板与泛型编程

    再学C++ Primer(11)-模板与泛型编程

    2021年8月22日
  • php网页运行不出来_phpstudy启动后就停止

    php网页运行不出来_phpstudy启动后就停止phpstudy中的nginx无法启动,报错:10049最近使用phpstudy的nginx+php环境编写laravel项目,老是报错,nginx无法启动,闪了一下,又变成了红色。下面整理一下解决方案:1.查看nginx的配置文件,一般是80端口,我这里根据不同项目修改了,所以我的是8093:2.win+R键,输入cmd,输入端口查询命令netstat-aon|findstr80,查看响应端口是否被占用,这里举例80端口;3.可以看到占用80端口程序的pid是3364,然后输入命令task

    2022年9月28日
  • 详解java动态代理机制以及使用场景

    详解java动态代理机制以及使用场景详解java动态代理机制以及使用场景

    2022年4月23日

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号