openssl之C++实现带中文的DN生成证书请求

编程入门 行业动态 更新时间:2024-10-07 13:17:19

openssl之C++实现带<a href=https://www.elefans.com/category/jswz/34/1769975.html style=中文的DN生成证书请求"/>

openssl之C++实现带中文的DN生成证书请求

文章目录

  • 示例
    • 1.DN示例
    • 2.证书请求csr示例字符串
    • 3.实现代码生成X509_REQ
    • 4.证书请求结构体转换格式PEM/CER
    • 5.转码相关方法
    • 6.命令行实现

示例

  • 在线校验CSR文件

1.DN示例

  • CN=必填_小路人,O=小路人_O,OU=小路人_OU,ST=小路人_ST,L=小路人_L,C=CN

2.证书请求csr示例字符串

  • pem格式的
-----BEGIN CERTIFICATE REQUEST-----
MIIDVTCCAj0CAQMwgYIxGTAXBgNVBAMMEOW/heWhq1/lsI/ot6/kuroxFDASBgNV
BAoMC+Wwj+i3r+S6ul9PMRUwEwYDVQQLDAzlsI/ot6/kurpfT1UxFTATBgNVBAgM
DOWwj+i3r+S6ul9TVDEUMBIGA1UEBwwL5bCP6Lev5Lq6X0wxCzAJBgNVBAYMAkNO
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz/KrG130UOvir2dD+JJg
MadkXWDqTwcSVWTgQLgerYiqNLvWDzdjAJ8BZcj2kMC7goGyXeuBMR6sJ466dgow
agu5Wpazzzp6DOOIV3M1runOLPZatojQDq2Bw9dIh3YqWksXDpO+R8iSuM1IvDD+
iKUMXcP6m+uX6etzhB/8ShcFkhzySKkRKxSZaJi3AHj95DyP+jX2MCv4dXIZB40T
I1JMzCLahxxvehG/rGVrqXp8qkMDVbDqpJQkIzeuxyCd2OYOx/CkWDIfYDkxCBkU
oH6LClbvJG/37VwjKybzGVQ2s4gitKtZyai7/ajh5Ao//kSuoNR2xf4X4tuZqVzT
wQIDAQABoIGMMBwGA1UdETEVDBNETlM6d3d3Lmd1c2h1YWkuZnVuMB8GA1UdJTEY
DBZzZXJ2ZXJBdXRoLCBjbGllbnRBdXRoMCAGCWCGSAGG+EIBDTETDBFDcmVhdGUg
YnkgZ3VzaHVhaTApBgNVHQ8xIgwgZGlnaXRhbFNpZ25hdHVyZSwgbm9uUmVwdWRp
YXRpb24wDQYJKoZIhvcNAQELBQADggEBAC9o3276iqkQSwMtPXAzWWeMPeKY7KRm
FoTW1z/YR5oVz6Yp1kcQSZe0fFZVv8qsqP+7n4lMbh7zJCrvvyFP1d9mkRLWA12x
fJTPOW8Pkm69QkiQaRuN5wQEfW5rw1AMd0sVIvl1WWKKc/R4dYT0H8bbH9Hjk/dd
nkhxzCQylFWzcz+gEi9AMOWjuEBMkcWgfl2IIccwkqsKlOsarmY5A9pq1yNuKm4r
TIAxTX5NZ+FN1oNalHrLbily38dijl+5Pwus8LMJvz1GG1S4clPaGjxLpskOWP5E
vb9banS9LLXjvi31D8Gntkm+5LbTVwnDATHfT+ZBq3Lj4LtsieCLPwU=
-----END CERTIFICATE REQUEST-----
  • der格式用base64字符串编码
MIIDVTCCAj0CAQMwgYIxGTAXBgNVBAMMEOW/heWhq1/lsI/ot6/kuroxFDASBgNVBAoMC+Wwj+i3r+S6ul9PMRUwEwYDVQQLDAzlsI/ot6/kurpfT1UxFTATBgNVBAgMDOWwj+i3r+S6ul9TVDEUMBIGA1UEBwwL5bCP6Lev5Lq6X0wxCzAJBgNVBAYMAkNOMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz/KrG130UOvir2dD+JJgMadkXWDqTwcSVWTgQLgerYiqNLvWDzdjAJ8BZcj2kMC7goGyXeuBMR6sJ466dgowagu5Wpazzzp6DOOIV3M1runOLPZatojQDq2Bw9dIh3YqWksXDpO+R8iSuM1IvDD+iKUMXcP6m+uX6etzhB/8ShcFkhzySKkRKxSZaJi3AHj95DyP+jX2MCv4dXIZB40TI1JMzCLahxxvehG/rGVrqXp8qkMDVbDqpJQkIzeuxyCd2OYOx/CkWDIfYDkxCBkUoH6LClbvJG/37VwjKybzGVQ2s4gitKtZyai7/ajh5Ao//kSuoNR2xf4X4tuZqVzTwQIDAQABoIGMMBwGA1UdETEVDBNETlM6d3d3Lmd1c2h1YWkuZnVuMB8GA1UdJTEYDBZzZXJ2ZXJBdXRoLCBjbGllbnRBdXRoMCAGCWCGSAGG+EIBDTETDBFDcmVhdGUgYnkgZ3VzaHVhaTApBgNVHQ8xIgwgZGlnaXRhbFNpZ25hdHVyZSwgbm9uUmVwdWRpYXRpb24wDQYJKoZIhvcNAQELBQADggEBAC9o3276iqkQSwMtPXAzWWeMPeKY7KRmFoTW1z/YR5oVz6Yp1kcQSZe0f

3.实现代码生成X509_REQ

  • 重点X509_NAME_add_entry_by_txt要用V_ASN1_UTF8STRING,需要先将gbk转为utf8
  • 主方法
    • DN->X509_NAME结构->X509_REQ结构
int rsaLib::genRsaCsr(const char * DN, char * csr,int *csrLen)
{X509_REQ        *pX509Req = NULL;int             iRV = 0;X509_NAME       *pX509DN = NULL;EVP_PKEY        *pEVPKey = NULL;RSA             *pRSA = NULL;X509_NAME_ENTRY *pX509Entry = NULL;int             bits = 2048;unsigned long   E = RSA_F4;if (DN == NULL){return -1;}if (!(pX509DN = X509_NAME_new())){return -1;}/*用DN生成X509_NAME结构*/	iRV = genX509NAME(DN, pX509DN);if (iRV != 0){ZF_LOGE("genCsr genX509NAME error");return iRV;}pRSA = RSA_generate_key(bits, E, NULL, NULL);pEVPKey = EVP_PKEY_new();EVP_PKEY_assign_RSA(pEVPKey, pRSA);/*用公钥及刚刚生成的X509_NAME生成证书请求*/pX509Req = X509_REQ_new();iRV = genX509REQ(pX509DN, pEVPKey, pX509Req);if (iRV != 0){ZF_LOGE("genCsr genX509REQ error");return iRV;}//可将X509_REQ转换为DER编码格式或者PEM格式// toFormatCsr(pX509Req, csr, csrLen);X509_REQ_free(pX509Req);RSA_free(pRSA);return 0;
}

4.证书请求结构体转换格式PEM/CER

  • X509_REQ结构->PEM/DER(字符串/文件)
toFormatCsr(X509_REQ  *pX509Req,char * csr,int * csr_len){/* DER编码 pri*/BUF_MEM         *pBMem = NULL;BIO             *pBIO = NULL;int             nLen,baseLen= 0;unsigned char   *pDer = NULL;unsigned char   *p = NULL;/*字符串 DER编码 pkcs10*/nLen = i2d_X509_REQ(pX509Req, NULL);pDer = (unsigned char *)malloc(nLen);p = pDer;nLen = i2d_X509_REQ(pX509Req, &p);baseLen = getEncodeLen(nLen, pDer);//编码后的字符串长度memcpy(csr, base64_encode(nLen,pDer), baseLen);*csrLen = baseLen;free(pDer);printf("der\t%s\n", csr);/*字符串 PEM编码 证书请求*/pBIO = BIO_new(BIO_s_mem());if (PEM_write_bio_X509_REQ(pBIO, pX509Req) != 1) {ZF_LOGE("X509_REQ error");goto free_all;}BIO_get_mem_ptr(pBIO, &pBMem);if (csr){memcpy(csr, pBMem->data, pBMem->length);}*csrLen = pBMem->length;BIO_free(pBIO);printf("pem\t%s\n", csr);/*生成文件 DER编码 证书请求*//* 生成的是无效文件,需要添加公钥生成x509证书才是有效的cer文件*/pBIO = BIO_new_file("pkcs10.der", "w");if (!pBIO){ZF_LOGE("pkcs10.der pBIO error");goto free_all;}iRV = i2d_X509_REQ_bio(pBIO, pX509Req);// 功能与i2d_X509_REQ_fp相同if (iRV != 1){ZF_LOGE("pkcs10.der error");goto free_all;}BIO_free(pBIO);/*生成文件 PEM编码 证书请求*/pBIO = BIO_new_file("pkcs10.pem", "w");if (!pBIO){ZF_LOGE("pkcs10.pem pBIO error");goto free_all;}if (PEM_write_bio_X509_REQ(pBIO, pX509Req) != 1) {ZF_LOGE("X509_REQ error");goto free_all;}
free_all:BIO_free(pBIO);return 0;
}

5.转码相关方法

  • 依赖的头文件
#include "strnormalize.h"
#include "base64.h"
#include <openssl/x509.h>
#include <openssl/pem.h>#include <string>
#include <vector>typedef std::string string;int split(const string& str, std::vector<string>& ret_, string sep)
{if (str.empty()){return 0;}string tmp;string::size_type pos_begin = str.find_first_not_of(sep);string::size_type comma_pos = 0;while (pos_begin != string::npos){comma_pos = str.find(sep, pos_begin);if (comma_pos != string::npos){tmp = str.substr(pos_begin, comma_pos - pos_begin);pos_begin = comma_pos + sep.length();}else{tmp = str.substr(pos_begin);pos_begin = comma_pos;}if (!tmp.empty()){ret_.push_back(tmp);tmp.clear();}}return 0;
}int genX509NAME(const char * DN, X509_NAME *pX509Name)
{if (DN == NULL){return -1;}if (pX509Name == NULL){return -1;}/*用DN生成X509_NAME结构*/int					iRV = 0;std::vector<string> vctDNs;string				stDNs = DN;uint32_t			utf8buffer_len;uint32_t			gbkbuffer_len;char				*utf8buffer = NULL;split(stDNs, vctDNs, ",");str_normalize_init();for (int i = 0; i < (int)vctDNs.size(); i++){std::vector<string> vctKVs;split(vctDNs[i], vctKVs, "=");if (vctKVs.size() != 2){continue;}gbkbuffer_len = vctKVs[1].length();utf8buffer_len = gbkbuffer_len * 2 + 1;utf8buffer = new char[utf8buffer_len];if (NULL == utf8buffer)continue;memset(utf8buffer, 0, utf8buffer_len);iRV = gbk_to_utf8(vctKVs[1].c_str(), gbkbuffer_len, &utf8buffer, &utf8buffer_len);if (iRV == -1) {delete utf8buffer;utf8buffer = NULL;continue;}iRV = X509_NAME_add_entry_by_txt(pX509Name, vctKVs[0].c_str(), V_ASN1_UTF8STRING, (const unsigned char *)utf8buffer, -1, -1, 0);}delete[]utf8buffer;utf8buffer = NULL;return 0;
}int genX509REQ(X509_NAME * pX509DN, EVP_PKEY *pEVPKey,X509_REQ  *pX509Req)
{int				iRV = 0;long            lVer = 3;const EVP_MD    *md = NULL;char szAltName[] = "DNS:www.gushuai.fun";char szComment[] = "Create by gushuai";char szKeyUsage[] = "digitalSignature, nonRepudiation";char szExKeyUsage[] = "serverAuth, clientAuth";char szBuf[255] = { 0 };unsigned char   mdout[1024];unsigned int    nLen, nModLen;iRV = X509_REQ_set_version(pX509Req, lVer);iRV = X509_REQ_set_subject_name(pX509Req, pX509DN);iRV = X509_REQ_set_pubkey(pX509Req, pEVPKey);/* attribute */strcpy(szBuf, szAltName);nLen = strlen(szBuf);iRV = X509_REQ_add1_attr_by_txt(pX509Req, "subjectAltName", V_ASN1_UTF8STRING, (const unsigned char *)szBuf, nLen);strcpy(szBuf, szKeyUsage);nLen = strlen(szBuf);iRV = X509_REQ_add1_attr_by_txt(pX509Req, "keyUsage", V_ASN1_UTF8STRING, (const unsigned char *)szBuf, nLen);strcpy(szBuf, szExKeyUsage);nLen = strlen(szBuf);iRV = X509_REQ_add1_attr_by_txt(pX509Req, "extendedKeyUsage", V_ASN1_UTF8STRING, (const unsigned char *)szBuf, nLen);strcpy(szBuf, szComment);nLen = strlen(szBuf);iRV = X509_REQ_add1_attr_by_txt(pX509Req, "nsComment", V_ASN1_UTF8STRING, (const unsigned char *)szBuf, nLen);md = EVP_sha256();iRV = X509_REQ_digest(pX509Req, md, mdout, &nModLen);iRV = X509_REQ_sign(pX509Req, pEVPKey, md);if (!iRV){printf("genX509REQ X509_REQ_sign error");return -1;}iRV = X509_REQ_verify(pX509Req, pEVPKey);if (iRV<0){printf("genX509REQ X509_REQ_verify error");return -1;}return 0;
}
  • 涉及UTF8-GBK转换及base64编码
  • strnormalize.h及strnormalize.cpp"在base_transcode
  • base64.h及base64.cpp"在base_base64

6.命令行实现

  • PEM格式的证书请求字符串转换为DER格式
openssl req -in pkcs10.pem -outform DER -out pkcs10.csr -config opensslf
  • 生成证书请求
# pri.key为私钥文件 该命令会自动取其中的公钥结合DN信息生成证书请求
openssl req -new -key pri.key -out p10.key  -subj /CN=gushuai.fun//O=linggo/OU=test/ST=GuangDong/L=GuangZhou/C=CN  -config opensslf

更多推荐

openssl之C++实现带中文的DN生成证书请求

本文发布于:2024-03-12 13:25:13,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1731615.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:中文   证书   openssl   DN

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!