使用openssl编码实现一本自签名证书的示例(改进版)

// ca_demo.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

#include <openssl/conf.h>
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/bn.h>
#include <openssl/txt_db.h>
#include <openssl/evp.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <openssl/objects.h>
#include <openssl/pem.h>
#include <openssl/engine.h>
#include <openssl/pkcs12.h>
#include <memory.h>
#include <malloc.h>
#include <stdio.h>

/**//*描述符长度*/
#define MA_X509_ENTITY_LEN 128

/**//*密钥对文件名字长度*/
#define MA_X509_RSAKEY_FILENAME_LEN 256

/**//*证书文件名字长度*/
#define MA_X509_CERT_FILENAME_LEN 256

/**//*密钥对长度*/
#define MA_X509_RSAKEY_LEN 1024

/**//*版本号*/
#define MA_X509_V1 0
#define MA_X509_V2 1
#define MA_X509_V3 2

/**//*序列号*/
#define MA_SN 1111

/**//*设置RSA密钥对的存储密钥*/
char *szX509RsaPswd = "PASSWORD";

X509_REQ *req = NULL;
X509_NAME *pSubjectName=NULL;
X509_NAME_ENTRY *ent=NULL;
EVP_PKEY *pNewRsaKey = NULL;
EVP_MD *digest=NULL;

/**//*CONFIG*/
char szCountry[MA_X509_ENTITY_LEN] = ...{0};
char szState[MA_X509_ENTITY_LEN] = ...{0};
char szLocation[MA_X509_ENTITY_LEN] = ...{0};
char szCommonName[MA_X509_ENTITY_LEN] = ...{0};
char szOrganization[MA_X509_ENTITY_LEN] = ...{0};
char szOrganizationUnit[MA_X509_ENTITY_LEN] = ...{0};
char szIsser[MA_X509_ENTITY_LEN] = ...{0};
unsigned long ulSn = 0;

char szRsaKeyFileName[MA_X509_RSAKEY_FILENAME_LEN] = ...{0};
char szRsaKey[MA_X509_RSAKEY_LEN] = ...{0};
char szCertFileName[MA_X509_CERT_FILENAME_LEN] = ...{0};
char szCaRsaKeyFileName[MA_X509_RSAKEY_FILENAME_LEN] = ...{0};

/**//*CA证书*/
X509 *m_pCACert = NULL;

int isCa = 0;

/**//*默认配置*/
int read_init()
...{
    FILE *pFile = NULL;

    strcpy(szCountry, "CN");
    strcpy(szState, "ZJ");
    strcpy(szLocation, "HZ");
    strcpy(szCommonName, "CA_TEST");
    strcpy(szOrganization, "CODESTART");
    strcpy(szOrganizationUnit, "FW");

    pFile = fopen("config.ini", "r");
    if(NULL == pFile)
    ...{
        printf("read_init:read config file error ");
        return -1;
    }

    /**//******************
    CN=piky
    COUNTRY=CN
    STATE=ZJ
    LOCATION=HZ
    ORGANIZATION=SNS
    ISSUER=SELF
    ******************/

    fscanf(pFile, "CN=%s ", szCommonName);
    fscanf(pFile, "COUNTRY=%s ", szCountry);
    fscanf(pFile, "STATE=%s ", szState);
    fscanf(pFile, "LOCATION=%s ", szLocation);
    fscanf(pFile, "ORGANIZATION=%s ", szOrganization);
    fscanf(pFile, "ISSUER=%s ", szIsser);
    fscanf(pFile, "ISSUERKEY=%s ", szCaRsaKeyFileName);
    fscanf(pFile, "SN=%d", &ulSn);

    printf("read entity: CN=%s,COUNTRY=%s,STATE=%s,LOCATION=%s,ORGANIZATION=%s,ISSUER=%s,ISSUERKEY=%s ",
        szCommonName,
        szCountry,
        szState,
        szLocation,
        szOrganization,
        szIsser,
        szCaRsaKeyFileName);

    sprintf(szCertFileName, "CN=%s.cert.pem", szCommonName);
    sprintf(szRsaKeyFileName, "CN=%s.key.pem",szCommonName);

    if (!strcmp(szIsser, "SELF") || 0 == szIsser[0])
    ...{
        isCa = 1;
        sprintf(szCertFileName, "ca.cert.pem");
        sprintf(szRsaKeyFileName, "ca.key.pem");
    }

    return 0;
}

int read_cert(X509** pCert, char *pCertFile)
...{
    BIO *pbio;
    if(NULL == pCert || NULL == pCertFile)
    ...{
        printf("read_cert:parament error(%x,%x) ", *pCert, pCertFile);
        return -1;
    }

    pbio = BIO_new_file(pCertFile,"r");
    if(NULL == pbio)
    ...{
        printf("read_cert:create bio file error ");
        return -1;
    }

    *pCert = PEM_read_bio_X509(pbio,NULL,NULL,NULL);
    if(NULL == *pCert)
    ...{
        printf("read_cert:call PEM_read_bio_X509 error ");
        BIO_free(pbio);
        return -1;
    }

    BIO_free(pbio);
    return 0;
}

int read_rsa_key(EVP_PKEY **pNewRsaKey, char *pRsaKeyFile, unsigned char*pPwd)
...{
    BIO *pbio;
    if(NULL == pNewRsaKey || NULL == pRsaKeyFile || NULL == pPwd)
    ...{
        return -1;
    }

    pbio = BIO_new_file(pRsaKeyFile,"r");
    if(NULL == pbio)
    ...{
        return -1;
    }

    *pNewRsaKey = PEM_read_bio_PrivateKey(pbio,NULL,0,NULL);
    if(NULL == *pNewRsaKey)
    ...{
        printf("read_rsa_key:call PEM_read_bio_PrivateKey error ");
        BIO_free(pbio);
        return -1;
    }

    BIO_free(pbio);
    return 0;
}

/**//*存储RSA密钥对*/
int save_rsa_key(EVP_PKEY *pNewRsaKey)
...{
    BIO *pbio;

    if(NULL == pNewRsaKey)
    ...{
        return -1;
    }

    pbio = BIO_new_file(szRsaKeyFileName,"w");
    if(NULL == pbio)
    ...{
        printf(" save_rsa_key:create bio file error");
        return -1;
    }

    /**//*存储密钥*/
/**//*if(!PEM_write_bio_PrivateKey(pbio, pNewRsaKey,EVP_des_cbc(),
            (unsigned char *)szX509RsaPswd, strlen(szX509RsaPswd),0,NULL))*/

    if(!PEM_write_bio_PrivateKey(pbio, pNewRsaKey,NULL,NULL, 0,0,NULL))
    ...{
        printf("save_rsa_key:call PEM_write_bio_PrivateKey error");
        return -1;
    }

    BIO_free(pbio);
    return 0;
}

/**//*存储证书*/
int save_cert(X509 *pCert, char *pCertFile)
...{
    BIO *pbio;

    if(NULL == pCert || NULL == pCertFile)
    ...{
        return -1;
    }

    pbio = BIO_new_file(pCertFile,"w");
    if(NULL == pbio)
    ...{
        return -1;
    }

    if(!PEM_write_bio_X509(pbio,pCert))
    ...{
        printf("save_cert:call PEM_write_bio_X509 error ");
        return -1;
    }

    BIO_free(pbio);
    return 0;
}

/**//*读取配置文件*/
int read_config()
...{
    read_init();
    return 0;
}

void add_subject_entity(char *key, char *value)
...{
    int nid;
    X509_NAME_ENTRY *ent;
    if( (nid =OBJ_txt2nid(key)) == NID_undef )
    ...{
        printf(" add_subject_entity:concert nid error");
        return ;
    }

    ent = X509_NAME_ENTRY_create_by_NID(NULL,nid,MBSTRING_UTF8,
        (unsigned char*)value,-1);
    if(ent == NULL)
    ...{
        printf("add_subject_entity:create ent error");
        return;
    }

    if(X509_NAME_add_entry(pSubjectName,ent,-1,0) != 1)
    ...{
        printf("add_subject_entity:add to subjectname error");
        return;
    }
    return;
}

int create_req()
...{
    /**//*读取配置文件*/
    if(0 != read_config())
    ...{
        return -1;
    }

    /**//*申请请求内存*/
    req = X509_REQ_new();

    /**//*创建密钥对*/
    pNewRsaKey = EVP_PKEY_new();
    EVP_PKEY_assign_RSA(pNewRsaKey, RSA_generate_key(512,0x10001,NULL,NULL));
    X509_REQ_set_pubkey(req,pNewRsaKey);

    /**//*保存密钥对*/
    if(0 != save_rsa_key(pNewRsaKey))
    ...{
        printf("call save_rsa_key error ");
        return -1;
    }

    pSubjectName = X509_NAME_new();
    if(pSubjectName == NULL)
    ...{
        printf("create_req_demo:create subjectname error ");
        return -1;
    }

    /**//*添加实体字段*/
    add_subject_entity("countryName", szCountry);
    add_subject_entity("stateOrProvinceName", szState);
    add_subject_entity("localityName", szLocation);
    add_subject_entity("organizationName", szOrganization);
    add_subject_entity("commonName", szCommonName);

    /**//*添加实体*/
    if(1 != X509_REQ_set_subject_name(req,pSubjectName))
    ...{
        printf("create_req_demo:add subjectname to req error");
        return -1;
    }

    return 0;
}

void create_cert_demo()
...{
    int ret = 0;
    X509 *certTmp =NULL;
    X509 *pCaCert = NULL;
    X509_NAME *pName=NULL;//X509_NAME_new();
    EVP_PKEY *pCaRsaKey = NULL;
    char szRsaKeyFileName[256] = ...{0};

    /**//*创建请求*/
    ret = create_req();
    if (0 != ret)
    ...{
        return;
    }

    /**//*if (!strcmp(szIsser, "SELF") || 0 == szIsser[0])
    {
        isCa = 1;
    }
    else*/
    if(0 == isCa)
    ...{
        if(0 != read_cert(&pCaCert, szIsser))
        ...{
            printf("read cert error ");
            return;
        }
    }

    /**//*申请内存*/
    certTmp = X509_new();
    if (NULL == certTmp)
    ...{
        printf("内存申请失败");
        return;
    }

    /**//*设置版本号:V3*/
    ret = X509_set_version(certTmp, MA_X509_V3);
    if (ret != 1)
    ...{
        printf("设置证书版本错误:0x%x",ret);
        return;
    }

    /**//*设置序列号*/
    ret = ASN1_INTEGER_set(X509_get_serialNumber(certTmp),ulSn);
    if (ret != 1)
    ...{
        printf("设置序列号错误:0x%x", ret);
        return;
    }

    /**//*设置开始时间*/
    if(!X509_gmtime_adj(X509_get_notBefore(certTmp),0))
    ...{
        printf("设置开始时间失败:0x%x", ret);
        return;
    }

    if (!X509_gmtime_adj(X509_get_notAfter(certTmp), (long)60*60*24*10))
    ...{
        printf("设置结束时间失败");
    }

    if (!X509_set_subject_name(certTmp, X509_REQ_get_subject_name(req)))
    ...{
        printf("设置请求失败");
    }

    EVP_PKEY *tmppkey = X509_REQ_get_pubkey(req);
    if (!tmppkey || !X509_set_pubkey(certTmp,tmppkey))
    ...{
        EVP_PKEY_free(tmppkey);
        printf("设置公钥失败");
    }
    EVP_PKEY_free(tmppkey);

    if(1 == isCa)
    ...{
        pName = X509_REQ_get_subject_name(req);
    }
    else
    ...{
        pName = X509_get_subject_name(pCaCert);
    }

    if(NULL == pName)
    ...{
        printf("get issuer name error ");
        return;
    }

    if (!X509_set_issuer_name(certTmp, pName))
    ...{
        printf("设置签发者名字失败 ");
        return;
    }

    if(1 == isCa)
    ...{
        X509_sign(certTmp, pNewRsaKey, EVP_sha1());
    }
    else
    ...{
        if(0 != read_rsa_key(&pCaRsaKey, szCaRsaKeyFileName, (unsigned char *)szX509RsaPswd))
        ...{
            printf("read rsa key error ");
            return;
        }
        X509_sign(certTmp, pCaRsaKey, EVP_sha1());
    }

    /**//**********************************************
    BIO *pbio;
    pbio = BIO_new(BIO_s_mem());
    PEM_write_bio_X509(pbio,certTmp);
    BUF_MEM * bptr;
    BIO_get_mem_ptr(pbio,&bptr);
 
    char *buf = (char *)malloc(bptr->length);
    if(NULL == buf)
    {
        printf("malloc error");
        return;
    }

    memcpy(buf, bptr->data, bptr->length);
    printf("%s ", buf);
    **********************************************/

    if(0 == save_cert(certTmp, szCertFileName))
    ...{
        printf("create cert successfully, cert file name is %s ", szCertFileName);
        return;
    }
    return;
}

int main(int argc, char* argv[])
...{
    create_cert_demo();
    system("pause");
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值