OpenSSL API

本文介绍如何使用OpenSSL库进行证书和密钥的处理,包括读取公钥和私钥,创建证书,以及生成P12格式的证书。通过具体的C语言代码示例,展示了从文件中读取X509对象,提取公钥,以及创建和签名证书的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

/**
 * @file cert_openssl.c
 * @brief 利用openssl api处理证书
 * @author zy
 * @date 2014-10-11 modify
 */
#include <stdio.h>
#include <unistd.h>
#include <openssl/pem.h>
#include <openssl/pkcs12.h>
#define CONTEXT_MAX_NUM 7
#define SERIAL_RAND_BITS 64
/**
* 描  述: 获取X509对象
* 参  数: @param[IN] cert_file  证书
* 返回值: X509对象
*/
X509* read_public_cert(const char* cert_file)
{
    X509 *x509 = NULL;
    
    FILE *fp = fopen (cert_file, "r");   
    if(!fp)
    {
        printf("read_public_cert, open cert failed!");
        return NULL; 
    }
    x509 = PEM_read_X509(fp, NULL, 0, NULL);
    if(x509 == NULL) 
    {  
        printf("read_public_cert, get x509 failed!");
        return NULL;   
    }
    return x509;
}
/**
* 描  述: 获取公钥
* 参  数: @param[IN] cert_file  证书
* 返回值: 公钥
*/
EVP_PKEY * read_public_key(const char* cert_file)
{
    X509 *x509 = NULL;
    EVP_PKEY *pkey = NULL;
    FILE *fp = fopen (cert_file, "r");   
    if(!fp)
    {
        printf("read_public_key, open cert failed!");
        return NULL;
    }
    x509 = PEM_read_X509(fp, NULL, 0, NULL);
    if(x509 == NULL) 
    {  
        printf("read_public_key, get x509 failed!");
        return NULL;   
    }
    fclose(fp);
    pkey = X509_extract_key(x509);
    X509_free(x509);
    if(pkey == NULL)
    {
        printf("read_public_key, get key failed!");
    }
    return pkey; 
}
/**
* 描  述: 获取私钥
* 参  数: @param[IN] key_file  证书
* 返回值: 私钥
*/
EVP_PKEY *read_private_key(const char* key_file)
{
    EVP_PKEY *pkey = NULL;
    
    FILE *fp = fopen(key_file, "r");
    if(!fp)
    {
        printf("read_private_key, open key failed!");
        return NULL;
    }
    pkey = PEM_read_PrivateKey(fp, NULL, 0, NULL);
    fclose(fp);
    if (pkey == NULL)
    {
        printf("read_private_key, get key failed!");
    }
    return pkey;
}
/**
* 描  述: 添加证书内容
* 参  数: @param[IN] name  X509_NAME
          @param[IN] ctx   使用者信息
          @param[IN] num   ctx数组长度
* 返回值: 1: 成功 0: 失败
*/
int add_cert_ctx(X509_NAME* name, char* ctx[], int num)
{
    int i = 0;
    int max = 0;
    int item[] = {NID_commonName, NID_countryName,
        NID_stateOrProvinceName, NID_localityName, 
        NID_organizationName, NID_organizationalUnitName,
        NID_pkcs9_emailAddress};
    max = sizeof(item)/sizeof(item[0]);
    max = max > num ? num : max;
    for(i=0; i<max; ++i)
    {
        if(!X509_NAME_add_entry_by_NID(name, item[i], MBSTRING_UTF8, ctx[i], -1, -1, 0))
        {
            printf("add_cert_ctx, add entry:%d to %s failed!", item[i], ctx[i]);
            return 0;
        }
    }
    return 1;
}
 
/**
* 描  述: 创建证书密钥
* 参  数: @param[OUT] pkey  EVP_PKEY
          @param[IN] bits   密钥长度
* 返回值: 1: 成功 0: 失败
*/
int create_client_key(EVP_PKEY** pkey, int bits)
{
    RSA *rsa = NULL;
    EVP_PKEY *pk = NULL;
    if((pk = EVP_PKEY_new()) == NULL)
    {
        printf("create_client_key, gen new key failed!");
        goto err;
    }
    rsa = RSA_generate_key(bits, RSA_F4, NULL, NULL);
    if(!EVP_PKEY_assign_RSA(pk, rsa))
    {
        printf("create_client_key, assign key failed!");
        EVP_PKEY_free(pk);
        goto err;
    }
    rsa = NULL;
    *pkey = pk;
    return 1;
 
err:
    return 0;
}
/**
* 描  述: CA签发证书
* 参  数: @param[OUT] x509p      EVP_PKEY
    @param[OUT] pkey       X509
    @param[IN] ca_file      CA
    @param[IN] ca_key_file   CA密钥
    @param[IN] serial      序列号
          @param[IN] days        过期时长
* 返回值: 1: 成功 0: 失败
*/
int create_ca_signed_crt(X509** x509p, EVP_PKEY** pkey, 
            const char* ca_file, const char* ca_key_file, const char* user, const int serial, const int days)
{
    X509* x = NULL;
    EVP_PKEY* pk = NULL;
    X509* xca = NULL;
    EVP_PKEY* xca_key = NULL;
    X509_NAME* name = NULL;
    //X509_NAME *tname = NULL;
    //char buf[256] = {0};
    char* ctx[] = {(char*)user, "bb", "cc", "dd", "ee", "ff", "ff@sf.com"};
    if(!create_client_key(&pk, 2048))
    {
        printf("create_ca_signed_crt, gen key failed!");
        goto err;
    }
    if((x = X509_new()) == NULL)
    {
        printf("create_ca_signed_crt, gen x509 failed!");
        goto err;
    }
    xca = read_public_cert(ca_file);
    xca_key = read_private_key(ca_key_file);
    if(!X509_check_private_key(xca, xca_key))
    {
        printf("create_ca_signed_crt, check ca %s and key %s failed!", ca_file, ca_key_file);
        goto err;
    }
    if(!X509_set_issuer_name(x, X509_get_subject_name(xca)))
    {
        printf("create_ca_signed_crt, set issuer failed!");
        goto err;
    }
    ASN1_INTEGER_set(X509_get_serialNumber(x), serial);
    if(X509_gmtime_adj(X509_get_notBefore(x), 0L) == NULL)
    {
        printf("create_ca_signed_crt, set cert begin time failed!");
        goto err;
    }
    if(X509_gmtime_adj(X509_get_notAfter(x), (long)60*60*24*days) == NULL)
    {
        printf("create_ca_signed_crt, set cert expired time failed!");
        goto err;
    }
    if(!X509_set_pubkey(x, pk))
    {
        printf("create_ca_signed_crt, set pubkey failed!");
        goto err;
    }
    //tname = X509_get_subject_name(xca);
    //X509_NAME_get_text_by_NID(tname, NID_localityName, buf, 256);
    //printf("city: %s\n", buf);
    name = X509_get_subject_name(x);
    if(!add_cert_ctx(name, ctx, CONTEXT_MAX_NUM))
    {
        printf("create_ca_signed_crt, add entry failed!");
        goto err;
    }
    if(!X509_sign(x, xca_key, EVP_sha1()))
    {
        printf("create_ca_signed_crt, sign cert failed!");
        goto err;
    }
    *pkey = pk;
    *x509p = x;
    return 1;
err:
    if(x)
        X509_free(x);
    if(pk)
        EVP_PKEY_free(pk);
    
    return 0;
}
/**
* 描  述: 创建P12证书
* 参  数: @param[IN] p12_file     p12
    @param[IN] p12_passwd   p12密码
    @param[IN] ca_file      CA
    @param[IN] ca_key_file   CA密钥
    @param[IN] serial      序列号
          @param[IN] days        过期时长
* 返回值: 1: 成功 0: 失败
*/
int create_p12_cert(char* p12_file, char* p12_passwd, 
            const char* ca_file, const char* ca_key_file, const char* user, const int serial, const int days)
{
    int ret = 0;
    PKCS12* p12 = NULL;
    X509* cert = NULL;
    EVP_PKEY* pkey = NULL;
 FILE *fp = NULL;
 BIO *mem = NULL;
 char *mem_out = NULL;
 long len = 0;
    SSLeay_add_all_algorithms();
    if(!create_ca_signed_crt(&cert, &pkey, ca_file, ca_key_file, user, serial, days))
    {
        printf("create_p12_cert, create signed cert failed!");
        goto err;
    }
    p12 = PKCS12_create(p12_passwd, NULL, pkey, cert, NULL, 0,0,0,0,0);
    if(!p12)
    {
        printf("create_p12_cert, create p12 object failed!");
        goto err;
    }
 /*
    fp = fopen(p12_file, "wb");
    if(!fp)
    {
        printf("create_p12_cert, open/create p12 file failed!");
        goto err;
    }
    if(!i2d_PKCS12_fp(fp, p12))
    {
        printf("create_p12_cert, put p12 file failed!");
        goto err;
    }
 */
 
 fp = fopen(p12_file, "wb");
    if(!fp)
    {
        printf("create_p12_cert, open/create p12 file failed!");
        goto err;
    }
 
 mem = BIO_new(BIO_s_mem());
 if(!mem)
 {
  printf("create_p12_cert, BIO_new failed!");
        goto err;
 }
 
 i2d_PKCS12_bio(mem, p12);
 len = BIO_get_mem_data(mem, &mem_out);
 fwrite(mem_out, sizeof(char), len, fp);
    ret = 1;
err:
    if(cert)
        X509_free(cert);
    if(pkey)
        EVP_PKEY_free(pkey);
    if (p12)
        PKCS12_free(p12);
 if (mem)
  BIO_free(mem);
    if(fp)
        fclose(fp);
    
    EVP_cleanup();
    return ret;
}
//openssl smime -sign -in unsign.mc -out signed.mc -signer ssl.crt -inkey ssl.key -certfile server.crt -outform der -nodetach
int sign_mobile_config(const char *inmc, int inlen, char **outmc, int *outlen,
 char *certfile, char *signerfile, char *keyfile)
{
    X509 *signer = NULL;
    EVP_PKEY *key = NULL;
    PKCS7 *p7 = NULL;
    X509 *cert = NULL;
    BIO *in = NULL;
    BIO *out = NULL;
    STACK_OF(X509) * other = NULL;
    
    int mclen = 0;
    char *mc = NULL;
    char *tmp = NULL;
    SSLeay_add_all_algorithms();
    
    // in 
    in = BIO_new_mem_buf((char*)inmc, inlen); // BIO_write
    if (!in)
    {
        return -1;
    }
   cert = read_public_cert(certfile);
   
   other = sk_X509_new_null();
   sk_X509_push(other, cert);

    signer = read_public_cert(signerfile);
    key = read_private_key(keyfile);
    if (!X509_check_private_key(signer, key))
    {
        printf("x509 check failed!\n");
        return -1;
    }
    
    p7 = PKCS7_sign(signer, key, other, in, 0);
    if (!p7)
     goto end;
     // out
    out = BIO_new(BIO_s_mem());
    i2d_PKCS7_bio(out, p7);
    mclen = BIO_get_mem_data(out, &tmp);// BIO_read
    mc = (char*)malloc(mclen);
    memcpy(mc, tmp, mclen);
    *outmc = mc;
    *outlen = mclen;
        
end:
    sk_X509_pop_free(other, X509_free);
    X509_free(signer);
    EVP_PKEY_free(key);
    PKCS7_free(p7);
    BIO_free(in);
    BIO_free_all(out);
    return 0;
}
 
int main()
{
 create_p12_cert("/root/out.p12", "1234", "/root/server_mdm.crt", "/root/server_mdm.key", "test", 0, 3650);
 return 0;
}
gcc -o test cert_openssl.c -L. -lcrypto














                #include<stdio.h> 
			
				#include<stdlib.h>
			
				#include<string.h>
			
				#include<openssl/rsa.h>
			
				#include<openssl/pem.h>
			
				#include<openssl/err.h>
			
			
				void hexprint(char *str,int len)
			
				{
			
				    int i=0;
			
				    for(i=0;i<len;i++){
			
				        printf("%s%02x%s",((i%16==0?"|":"")),*((unsigned char*)str+i),(((i+1)%16==0)?"|\n":" "));
			
				    }
			
				    if(i%16!=0)
			
				        printf("|\n");
			
				}
			
				
			
				static int do_operation(RSA* rsa_ctx,char *instr,char* path_key,int inlen,char** outstr,int type)
			
				{
			
				    if(rsa_ctx == NULL || instr == NULL || path_key == NULL)
			
				    {
			
				        perror("input elems error,please check them!");
			
				        return -1;
			
				    }
			
				    int rsa_len,num;
			
				    rsa_len=RSA_size(rsa_ctx);
			
				    *outstr=(unsigned char *)malloc(rsa_len+1);
			
				    memset(*outstr,0,rsa_len+1);
			
				    switch(type){
			
				        case 1: //pub enc
			
				        if(inlen == 0){
			
				            perror("input str len is zero!");
			
				            goto err;
			
				        }
			
				        num = RSA_public_encrypt(inlen,(unsigned char *)instr,(unsigned char*)*outstr,rsa_ctx,RSA_PKCS1_OAEP_PADDING);
			
				        break;
			
				        case 2: //prv dec
			
				        num = RSA_private_decrypt(inlen,(unsigned char *)instr,(unsigned char*)*outstr,rsa_ctx,RSA_PKCS1_OAEP_PADDING);        
			
				        default:
			
				        break;
			
				    }
			
				
			
				    if(num == -1)
			
				    {
			
				        printf("Got error on enc/dec!\n");
			
				err:
			
				        free(*outstr);
			
				        *outstr = NULL;
			
				        num = -1;
			
				    }
			
				    return num;
			
				}
			
				 
			
			
				int rsa_pub_encrypt(char *str,char *path_key,char** outstr){
			
				    RSA *p_rsa;
			
				    FILE *file;
			
				    int flen,rsa_len,num;
			
				    if((file=fopen(path_key,"r"))==NULL){
			
				        perror("open key file error");
			
				        return -1; 
			
				    } 
			
				#ifdef RSAPUBKEY
			
				    if((p_rsa=PEM_read_RSA_PUBKEY(file,NULL,NULL,NULL))==NULL){
			
				#else
			
				    if((p_rsa=PEM_read_RSAPublicKey(file,NULL,NULL,NULL))==NULL){
			
				#endif
			
				        ERR_print_errors_fp(stdout);
			
				        return -1;
			
				    } 
			
				
			
				    num = do_operation(p_rsa,str,path_key,strlen(str),outstr,1);
			
				    RSA_free(p_rsa);
			
				    fclose(file);
			
				    return num;
			
				}
			
				
			
				int rsa_prv_decrypt(char *str,char *path_key,int inlen,char** outstr){    
			
				    RSA *p_rsa;
			
				    FILE *file;
			
				    int rsa_len,num;
			
				        
			
				    if((file=fopen(path_key,"r"))==NULL){
			
				        perror("open key file error");
			
				        return -1;
			
				    }
			
				    if((p_rsa=PEM_read_RSAPrivateKey(file,NULL,NULL,NULL))==NULL){
			
				        ERR_print_errors_fp(stdout);
			
				        return -1;
			
				    }    
			
				    num = do_operation(p_rsa,str,path_key,inlen,outstr,2);
			
				    RSA_free(p_rsa);
			
				    fclose(file);
			
				    return num;
			
				}
			
				
			
				int main(int argc,char** argv){ 
			
				    char *ptr_en,*ptr_de;
			
				    int len;
			
				   
			
				    printf("source is    :%s\n",argv[1]);
			
				    len=rsa_pub_encrypt(argv[1],argv[2],&ptr_en);
			
				    printf("pubkey encrypt:\n");
			
				    hexprint(ptr_en,len);
			
				    
			
				    rsa_prv_decrypt(ptr_en,argv[3],len,&ptr_de);
			
				    printf("prvkey decrypt:%s\n",ptr_de==NULL?"NULL":ptr_de);
			
				    
			
				    if(ptr_en!=NULL){
			
				        free(ptr_en);
			
				    } 
			
				    if(ptr_de!=NULL){
			
				        free(ptr_de);
			
				    } 
			
				    
			
				    return 0;
			
				}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值