以下代码并非完全原创,有所参考借鉴。

/* 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证书相关推荐

  1. 使用openssl 生成RSA、SM2、ECC的P12证书的方法

    主流 Web 服务软件证书 一般来说,主流的 Web 服务软件,通常都基于 OpenSSL 和 Java 两种基础密码库. Tomcat.Weblogic.JBoss等Web服务软件,一般使用Java ...

  2. linux下利用openssl来实现证书的颁发(详细步骤)--转载和修改

    原文地址:http://www.cnblogs.com/firtree/p/4028354.html linux下利用openssl来实现证书的颁发(详细步骤) 1.首先需要安装openssl,一个开 ...

  3. 使用Openssl签发SSL证书

    本文主要记述在Linux系统上使用Openssl创建SSL证书的流程,作为个人学习笔记.自签名证书分为自签名私有证书和自签名CA证书两种.自签名私有证书无法被吊销,自签名CA证书可以被吊销. 什么是o ...

  4. http系列---OpenSSL生成根证书CA及签发子证书

    文章目录 1. 前言 2. 修改OpenSSL的配置 3. 生成根证书 4. 用根证书签发server端证书 5. 用根证书签发client端证书 6. 导出证书 7. 附项目证书目录 1. 前言 系 ...

  5. 使用openssl 转换pkcs12证书为pem格式

    使用openssl 转换pkcs12证书为pem格式 pkcs证书一般是.p12或.pfx格式,一般会有证书密码. 使用3步将证书导出: 第一步先导出为key文件 举例输出key文件为priv.p12 ...

  6. iOS:苹果推送(APNS)-pem/p12证书的生成

        pem文件是服务器向苹果服务器做推送时候需要的文件,主要是做服务器的小伙伴们要用,下面介绍一下pem文件的生成. 打开KeychainAccess,在Certificates里面找到上篇文章中 ...

  7. 密码学专题 证书和CA指令 申请证书|建立CA|CA操作|使用证书|验证证书

    Req指令介绍 功能概述和指令格式 req指令一般来说应该是提供给证书申请用户的工具,用来生成证书请求以便交给CA验证和签发证书.但是,OpenSSL的req指令的功能远比这样的要求强大得多,它不仅可 ...

  8. 微信支付中的p12证书提取公钥、私钥、证书、序列号等

    今天做微信支付开发,然后产品给我了相应的商户号.apikey.公众号.p12证书等等.说准备工作都已经做好了,可以进行开发了.但是我看微信文档里没有提到p12证书,都是pem证书.怎么办,百度吧. 原 ...

  9. openssl私有CA证书签发与单双向认证

    什么是CA? CA是数字认证中心的简称.指的是发放.管理.废除数字证书的机构. CA的作用: 检查证书持有者身份的合法性.签发证书(在证书上签字),以防证书被伪造或篡改,以及对证书和密钥进行管理. 建 ...

最新文章

  1. dataframe 去除重复
  2. Redis的设计与实现之对象
  3. 【Linux内核】内存映射原理
  4. LeetCode训练
  5. OJ1053: 正弦函数(纯数学思想和编程思想两种方法实现)(C语言)
  6. word设置多级标题样式及编号
  7. Himall商城枚举帮助类EnumHelper(1)
  8. 【Feign请求头丢失问题】no suitable HttpMessageConverter found for response type
  9. 美团面试-2016校园招聘
  10. 海信智能电视如何看电视直播
  11. 为fetch添加拦截器功能
  12. 服务器光猫一直亮不响应,光猫光信号正常,且光猫和路由器都重启过,还是上不了网咋办?...
  13. 编程之美 2.1 求二进制中1的个数
  14. 光模块价格由带宽还是距离决定_广州单模光模块价格
  15. 遥感相关专业英语词汇汇总
  16. POJ ZOJ题目分类
  17. Unity中根据设备名称获取串口号
  18. 呼吁重视孩子写字姿势
  19. 南宁富士康c语言笔试题,富士康笔试题目
  20. Android 高质量开发之崩溃优化,2020-2021字节跳动Android面试真题解析

热门文章

  1. STM32CuBeMX(HAL库)实现定时器中断(STM32F407ZGT6)
  2. 知网查重时间一般是多久
  3. 音频切歌消除POP声或者噪音算法,淡入淡出算法
  4. 傅占杰:VR体验与产品营销的本质
  5. IGBT损耗计算及散热设计方法
  6. 【重要】2023年上半年有三AI新课程规划出炉,讲师持续招募中!
  7. 百度地图-地铁图调起
  8. 中龍鸿业:怎么看懂理财产品阐明书,四点很重要
  9. flash与字符串:字符串与属性
  10. 物联网盒子是什么?有什么用?