使用openssl操作P12证书
以下代码并非完全原创,有所参考借鉴。
/* vi:set tw=0 ts=4 sw=4 noet: */
/************************************************************************/
/*! \file: p12op.cpp
* \brief:
*
* \version: 1.0
* \author: f7zz , f7zz@yahoo.com
* \Company: ZLab
* \date: 2005-6-30 14:32:41 中国标准时间
*
* \bug:
* \warning:
*
* CVS: $Id$
************************************************************************/
/** 从DER、PEM、P12格式中读取公钥证书.
* 由该函数导出的X509必须释放(X509_free)
*/
X509 * BaseLoadCert (BIO * Cert, int iFormat, char *strPwd)
{
X509 *x = NULL;
switch (iFormat)
{
case DER:
x = d2i_X509_bio (Cert, NULL);
break;
case PEM:
x = PEM_read_bio_X509 (Cert, NULL, NULL, NULL); //PEM_read_bio_X509_AUX
break;
case P12:
{
PKCS12 *p12 = d2i_PKCS12_bio (Cert, NULL);
PKCS12_parse (p12, strPwd, NULL, &x, NULL);
PKCS12_free (p12);
p12 = NULL;
break;
}
default:
break;
}
return x;
}
/** 载入证书.
* 尝试使用DER/PEM格式两种格式
* 由该函数导出的X509必须释放
*/
X509 * LoadCert (char *cert, int certlen)
{
BIO *in = NULL;
X509 *x509 = NULL;
assert(cert);
if (certlen == 0) /// 输入为磁盘文件
{
if ((in = BIO_new_file (cert, "r")) == NULL)
{
return NULL;
}
}
else // 输入为内存中文件
{
if ((in = BIO_new_mem_buf (cert, certlen)) == NULL) //只读类型
{
return NULL;
}
}
if ((x509 = BaseLoadCert (in, DER, NULL)) == NULL) //尝试DER
{
BIO_reset (in);
x509 = BaseLoadCert (in, PEM, NULL); //尝试PEM
}
BIO_free (in);
in = NULL;
in = 0;
return x509;
}
/** 尝试从DER/PEM/P12格式导出密钥
* 由该函数导出的EVP_PKEY必须释放
*/
EVP_PKEY * BaseLoadKey (BIO * bio, int iFormat, char *strPwd)
{
EVP_PKEY *pkey = NULL;
switch (iFormat)
{
case DER:
pkey = d2i_PrivateKey_bio (bio, NULL);
break;
case PEM:
pkey = PEM_read_bio_PrivateKey (bio, NULL, NULL, strPwd);
break;
case P12:
{
PKCS12 *p12 = d2i_PKCS12_bio (bio, NULL);
PKCS12_parse (p12, strPwd, &pkey, NULL, NULL);
PKCS12_free (p12);
p12 = NULL;
break;
}
default:
break;
}
return pkey;
}
/** 载入私钥.
* 尝试DER/PEM格式
*/
EVP_PKEY * LoadKey (char *key, int keylen, char *pass)
{
EVP_PKEY *pkey = NULL;
BIO *in = NULL;
if (keylen == 0) //输入为磁盘文件
{
if ((in = BIO_new_file (key, "r")) == NULL)
{
return NULL;
}
}
else //输入为内存中文件
{
if ((in = BIO_new_mem_buf (key, keylen)) == NULL) //只读类型
{
return NULL;
}
}
if ((pkey = BaseLoadKey (in, DER, pass)) == NULL) //尝试DER
{
BIO_reset (in);
pkey = BaseLoadKey (in, PEM, pass); //尝试PEM
}
if (in != NULL)
BIO_free (in);
return pkey;
}
/** 载入p12.
*
*/
PKCS12 * LoadP12 (char *strP12File, char *strP12Pwd)
{
FILE *fp = NULL;
PKCS12 *p12 = NULL;
assert(strP12File);
assert(strP12Pwd);
/// 读入P12
if (!(fp = fopen (strP12File, "rb")))
return NULL;
p12 = d2i_PKCS12_fp (fp, NULL);
fclose(fp);
if (!p12)
return NULL;
return p12;
}
int p12_ChangePwd (char *strP12, char *strPwd, char *strNewPwd)
{
FILE *fp = NULL;
PKCS12 *p12 = NULL;
int reval;
assert(strP12);
assert(strPwd);
assert(strNewPwd);
OpenSSL_add_all_algorithms ();
/// 读入P12
if (!(fp = fopen (strP12, "r+bc")))
{
/* deferr(ERR_P12CHGPWD_OPENFILE, "p12_ChangePwd(): Error Open p12 file.") */
return ERR_P12CHGPWD_OPENFILE;
}
p12 = d2i_PKCS12_fp (fp, NULL);
if (!p12)
{
fclose (fp);
/* deferr(ERR_P12CHGPWD_READFILE, "p12_ChangePwd(): Error Read p12 file.") */
return ERR_P12CHGPWD_READFILE;
}
reval = PKCS12_newpass (p12, strPwd, strNewPwd);
if (!reval)
{
PKCS12_free (p12);
p12 = NULL;
fclose (fp);
/* deferr(ERR_P12CHGPWD_UPDATE, "p12_ChangePwd(): Error Update Password.") */
return ERR_P12CHGPWD_UPDATE;
}
/// i2d_PKCS12_fp的bug, 对于老文件,必须将文件指针移到文件头
fseek (fp, 0, SEEK_SET);
reval = i2d_PKCS12_fp (fp, p12);
if (!reval)
{
PKCS12_free (p12);
p12 = NULL;
fclose (fp);
/* deferr(ERR_P12CHGPWD_UPDATE, "p12_ChangePwd(): Error Update Password.") */
return ERR_P12CHGPWD_UPDATE;
}
/// 释放
PKCS12_free (p12);
p12 = NULL;
fclose (fp);
return 1;
}
int p12_VerifyPwd (char *strP12, char *strPwd)
{
int reval;
assert(strP12);
assert(strPwd);
reval = p12_ChangePwd (strP12, strPwd, strPwd);
if (reval != 1)
{
/* deferr(ERR_P12VERIFYPWD, "p12_ChangePwd(): Error Verify Password.") */
return ERR_P12VERIFYPWD;
}
return 1;
}
int p12_ExpToNewP12 (char *strP12, /*源p12文件 */
char *strPwd, /*源p12密码 */
char *strPwd2, /*新p12密码 */
char *strOutP12 /*新p12文件 */
)
{
int reval;
FILE *fp = NULL;
EVP_PKEY *key = NULL;
X509 *cert = NULL;
STACK_OF (X509) * ca = NULL;
PKCS12 *p12 = NULL;
int len = 0, wlen = 0;
assert(strP12);
assert(strPwd);
assert(strPwd2);
assert(strOutP12);
OpenSSL_add_all_algorithms ();
/// 读入P12,并分解
if (!(fp = fopen (strP12, "rb")))
{
/* deferr(ERR_P12EXP_OPENFILE, "p12_ExpNewP12(): Error Open p12 file.") */
return ERR_P12EXP_OPENFILE;
}
p12 = d2i_PKCS12_fp (fp, NULL);
fclose (fp);
if (!p12)
{
/* deferr(ERR_P12EXP_READFILE, "p12_ExpNewP12(): Error Read p12 file.") */
return ERR_P12EXP_READFILE;
}
if (!PKCS12_parse (p12, strPwd, &key, &cert, &ca))
{
PKCS12_free(p12);
p12 = NULL;
/* deferr(ERR_P12EXP_PARSE, "p12_ExpNewP12(): Error Parse p12 file.") */
return ERR_P12EXP_PARSE;
}
PKCS12_free (p12);
p12 = NULL;
/// 生成新P12
p12 = PKCS12_create (strPwd2, "Duplicated", key, cert, ca, 0, 0, 0, 0, 0);
if (!p12)
{
/* deferr(ERR_P12EXP_CREATESTRUCT, "p12_ExpNewP12(): Error Create p12 struct.") */
reval = ERR_P12EXP_CREATESTRUCT;
goto Cleanup;
}
/// 创建新p12文件,并保存
if (!(fp = fopen (strOutP12, "wb")))
{
/* deferr(ERR_P12EXP_CREATEFILE, "p12_ExpNewP12(): Error Create p12 file.") */
reval = ERR_P12EXP_CREATEFILE;
goto Cleanup;
}
i2d_PKCS12_fp (fp, p12);
reval = 1;
Cleanup:
/// 释放
if(p12 != NULL)
PKCS12_free (p12);
if (fp != NULL)
fclose (fp);
if (cert != NULL)
X509_free (cert);
if (key != NULL)
EVP_PKEY_free (key);
if (ca != NULL)
{
for(;;)
{
X509 *x5 = sk_X509_pop(ca);
if (!x5)
break;
X509_free(x5);
}
sk_X509_free (ca);
}
return reval;
}
int p12_ExpToCertKey (char *strP12, char *strPwd, int iFormat, char *Cert, char *Key, char *Ca)
{
int reval;
EVP_PKEY *key = NULL;
X509 *cert = NULL;
STACK_OF (X509) * ca = NULL;
BIO *bio = NULL, *bioCert = NULL, *bioKey = NULL, *bioCaCert = NULL;
PKCS12 *p12 = NULL;
int reval1 = 0, reval2 = 0, reval3 = 0;
assert(strP12);
assert(strPwd);
assert(iFormat);
assert(Cert);
assert(Key);
assert(Ca);
OpenSSL_add_all_algorithms ();
if (!(bio = BIO_new_file (strP12, "r")))
{
/* deferr(ERR_P12EXPCK_OPENFILE, "p12_ExpToCertKey(): Error Open p12 file.") */
return ERR_P12EXPCK_OPENFILE;
}
p12 = d2i_PKCS12_bio (bio, NULL);
BIO_free (bio);
bio = NULL;
if (!p12)
{
/* deferr(ERR_P12EXPCK_READFILE, "p12_ExpToCertKey(): Error Read p12 file.") */
return ERR_P12EXPCK_READFILE;
}
if (!PKCS12_parse (p12, strPwd, &key, &cert, &ca))
{
/* deferr(ERR_P12EXPCK_PARSE, "p12_ExpToCertKey(): Error Parse p12 file.") */
return ERR_P12EXPCK_PARSE;
}
PKCS12_free (p12);
p12 = NULL;
/// 输出文件
if ((bioCert = BIO_new_file (Cert, "w")) == NULL)
{
/* deferr(ERR_P12EXPCK_CREATECERTFILE, "p12_ExpToCertKey(): Error Create Cert File.") */
reval = ERR_P12EXPCK_CREATECERTFILE;
goto Cleanup;
}
if ((bioKey = BIO_new_file (Key, "w")) == NULL)
{
/* deferr(ERR_P12EXPCK_CREATEKEYFILE, "p12_ExpToCertKey(): Error Create Key File.") */
reval = ERR_P12EXPCK_CREATEKEYFILE;
goto Cleanup;
}
if (iFormat == DER)
{
reval1 = i2d_X509_bio (bioCert, cert);
reval2 = i2d_PrivateKey_bio (bioKey, key);
}
else if (iFormat == PEM)
{
reval1 = PEM_write_bio_X509 (bioCert, cert);
reval2 = PEM_write_bio_PrivateKey (bioKey, key, NULL, NULL, 0, 0, NULL);
}
BIO_free (bioCert);
bioCert = NULL;
BIO_free (bioKey);
bioKey = NULL;
X509_free (cert);
cert = NULL;
EVP_PKEY_free (key);
key = NULL;
if (ca && sk_num (ca))
{
if ((bioCaCert = BIO_new_file (Ca, "w")) == NULL)
{
/* deferr(ERR_P12EXPCK_CREATEFILE, "p12_ExpToCertKey(): Error Create Cert or Key File.") */
reval = ERR_P12EXPCK_CREATEFILE;
goto Cleanup;
}
if (iFormat == DER)
{
/* deferr(ERR_P12EXPCK_NOTSURPORT, "p12_ExpToCertKey(): Not Surport _MCRT_EXPORT DER ca cert.") */
reval = ERR_P12EXPCK_NOTSURPORT;
goto Cleanup;
}
else if (iFormat == PEM)
{
int i;
for (i = 0; i < sk_X509_num (ca); i++)
reval3 = PEM_write_bio_X509_AUX (bioCaCert, sk_X509_value (ca, i));
}
BIO_free (bioCaCert);
bioCaCert = NULL;
}
else
reval3 = 1;
if (reval1 == 0 || reval2 == 0 || reval3 == 0)
{
/* deferr(ERR_P12EXPCK_FAILED, "p12_ExpToCertKey(): Error _MCRT_EXPORT Cert or Key File.") */
reval = ERR_P12EXPCK_FAILED;
goto Cleanup;
}
reval = 1;
Cleanup:
if (bio != NULL)
BIO_free(bio);
if (bioCert != NULL)
BIO_free(bioCert);
if (bioKey != NULL)
BIO_free(bioKey);
if (bioCaCert != NULL)
BIO_free(bioCaCert);
if (key != NULL)
EVP_PKEY_free(key);
if (cert != NULL)
X509_free(cert);
if (ca != NULL)
{
for(;;)
{
X509 *x5 = sk_X509_pop(ca);
if (!x5)
break;
X509_free(x5);
}
sk_X509_free (ca);
}
return reval;
}
int p12_impfromCertKey (char *strP12, char *strPwd, int iFormat, char *strCert, char *strKey, char *strCa)
{
int reval;
FILE *fp = NULL;
EVP_PKEY *key = NULL;
X509 *cert = NULL, *ca0 = NULL;
STACK_OF (X509) * ca = NULL;
PKCS12 *p12 = NULL;
int len = 0, wlen = 0;
OpenSSL_add_all_algorithms ();
// 加载cert,key,ca
cert = LoadCert (strCert, 0);
if (cert == NULL)
{
printf("p12_impfromCertKey(): LoadCert Error!\n");
return ERR_CERTGETI_OPEN;
}
key = LoadKey (strKey, 0, NULL); /// 默认密钥为明文
if (key == NULL)
{
printf("p12_impfromCertKey(): LoadKey Error!\n");
return -1;
}
ca0 = LoadCert (strCa, 0);
if (ca0 == NULL)
{
printf("p12_impfromCertKey(): LoadCert CA Error!\n");
return ERR_CERTGETI_OPEN;
}
ca = sk_X509_new_null();
if (ca == NULL)
{
printf("p12_impfromCertKey(): sk_X509_new_null Error!\n");
return -1;
}
printf("4\n");
if (!sk_X509_push(ca, ca0))
{
printf("p12_impfromCertKey(): sk_X509_push Error!\n");
return -1;
}
/// 生成新P12
p12 = PKCS12_create (strPwd, "Duplicated", key, cert, ca, 0, 0, 0, 0, 0);
if (!p12)
{
/* deferr(ERR_P12EXP_CREATESTRUCT, "p12_ExpNewP12(): Error Create p12 struct.") */
reval = ERR_P12EXP_CREATESTRUCT;
goto Cleanup;
}
/// 创建新p12文件,并保存
if (!(fp = fopen (strP12, "wb")))
{
/* deferr(ERR_P12EXP_CREATEFILE, "p12_ExpNewP12(): Error Create p12 file.") */
reval = ERR_P12EXP_CREATEFILE;
goto Cleanup;
}
i2d_PKCS12_fp (fp, p12);
reval = 1;
Cleanup:
/// 释放
if(p12 != NULL)
PKCS12_free (p12);
if (fp != NULL)
fclose (fp);
if (cert != NULL)
X509_free (cert);
if (key != NULL)
EVP_PKEY_free (key);
if (ca != NULL)
{
for(;;)
{
X509 *x5 = sk_X509_pop(ca);
if (!x5)
break;
X509_free(x5);
}
sk_X509_free (ca);
}
return reval;
}
在windows下使用vc编译的openssl的库是要分debug和release的,比如用release的程序去调debug的库,某些 函数可能会有错,比如以上用到的d2i_PKCS12_bio函数(在我用的0.9.7g,最新的版本未测试过)中,所以敬请注意。
如果你的windows下使用gcc编译程序和库,就不会由什么问题.
http://laokaddk.blog.51cto.com/368606/596124/
使用openssl操作P12证书相关推荐
- 使用openssl 生成RSA、SM2、ECC的P12证书的方法
主流 Web 服务软件证书 一般来说,主流的 Web 服务软件,通常都基于 OpenSSL 和 Java 两种基础密码库. Tomcat.Weblogic.JBoss等Web服务软件,一般使用Java ...
- linux下利用openssl来实现证书的颁发(详细步骤)--转载和修改
原文地址:http://www.cnblogs.com/firtree/p/4028354.html linux下利用openssl来实现证书的颁发(详细步骤) 1.首先需要安装openssl,一个开 ...
- 使用Openssl签发SSL证书
本文主要记述在Linux系统上使用Openssl创建SSL证书的流程,作为个人学习笔记.自签名证书分为自签名私有证书和自签名CA证书两种.自签名私有证书无法被吊销,自签名CA证书可以被吊销. 什么是o ...
- http系列---OpenSSL生成根证书CA及签发子证书
文章目录 1. 前言 2. 修改OpenSSL的配置 3. 生成根证书 4. 用根证书签发server端证书 5. 用根证书签发client端证书 6. 导出证书 7. 附项目证书目录 1. 前言 系 ...
- 使用openssl 转换pkcs12证书为pem格式
使用openssl 转换pkcs12证书为pem格式 pkcs证书一般是.p12或.pfx格式,一般会有证书密码. 使用3步将证书导出: 第一步先导出为key文件 举例输出key文件为priv.p12 ...
- iOS:苹果推送(APNS)-pem/p12证书的生成
pem文件是服务器向苹果服务器做推送时候需要的文件,主要是做服务器的小伙伴们要用,下面介绍一下pem文件的生成. 打开KeychainAccess,在Certificates里面找到上篇文章中 ...
- 密码学专题 证书和CA指令 申请证书|建立CA|CA操作|使用证书|验证证书
Req指令介绍 功能概述和指令格式 req指令一般来说应该是提供给证书申请用户的工具,用来生成证书请求以便交给CA验证和签发证书.但是,OpenSSL的req指令的功能远比这样的要求强大得多,它不仅可 ...
- 微信支付中的p12证书提取公钥、私钥、证书、序列号等
今天做微信支付开发,然后产品给我了相应的商户号.apikey.公众号.p12证书等等.说准备工作都已经做好了,可以进行开发了.但是我看微信文档里没有提到p12证书,都是pem证书.怎么办,百度吧. 原 ...
- openssl私有CA证书签发与单双向认证
什么是CA? CA是数字认证中心的简称.指的是发放.管理.废除数字证书的机构. CA的作用: 检查证书持有者身份的合法性.签发证书(在证书上签字),以防证书被伪造或篡改,以及对证书和密钥进行管理. 建 ...
最新文章
- dataframe 去除重复
- Redis的设计与实现之对象
- 【Linux内核】内存映射原理
- LeetCode训练
- OJ1053: 正弦函数(纯数学思想和编程思想两种方法实现)(C语言)
- word设置多级标题样式及编号
- Himall商城枚举帮助类EnumHelper(1)
- 【Feign请求头丢失问题】no suitable HttpMessageConverter found for response type
- 美团面试-2016校园招聘
- 海信智能电视如何看电视直播
- 为fetch添加拦截器功能
- 服务器光猫一直亮不响应,光猫光信号正常,且光猫和路由器都重启过,还是上不了网咋办?...
- 编程之美 2.1 求二进制中1的个数
- 光模块价格由带宽还是距离决定_广州单模光模块价格
- 遥感相关专业英语词汇汇总
- POJ ZOJ题目分类
- Unity中根据设备名称获取串口号
- 呼吁重视孩子写字姿势
- 南宁富士康c语言笔试题,富士康笔试题目
- Android 高质量开发之崩溃优化,2020-2021字节跳动Android面试真题解析