openssl 生成CSR
C/C++(105) 
版权声明:本文为博主原创文章,未经博主允许不得转载。
将openssl如何生成CSR写了一上DEMO,支持扩展属性,同时增加了通过DN字符串转X509_NAME的方法。
- #include <string.h>
- #include <openssl/x509.h>
- #include <openssl/rsa.h>
- #pragma comment(lib, "libeay32.lib")
- /*
- * subject is expected to be in the format /type0=value0/type1=value1/type2=...
- * where characters may be escaped by \
- */
- X509_NAME *parse_name(char *subject, long chtype, int multirdn)
- {
- size_t buflen = strlen(subject)+1; /* to copy the types and values into. due to escaping, the copy can only become shorter */
- char *buf = OPENSSL_malloc(buflen);
- size_t max_ne = buflen / 2 + 1; /* maximum number of name elements */
- char **ne_types = OPENSSL_malloc(max_ne * sizeof (char *));
- char **ne_values = OPENSSL_malloc(max_ne * sizeof (char *));
- int *mval = OPENSSL_malloc (max_ne * sizeof (int));
- char *sp = subject, *bp = buf;
- int i, ne_num = 0;
- X509_NAME *n = NULL;
- int nid;
- if (!buf || !ne_types || !ne_values || !mval)
- {
- //BIO_printf(bio_err, "malloc error\n");
- goto error;
- }
- if (*subject != '/')
- {
- //BIO_printf(bio_err, "Subject does not start with '/'.\n");
- goto error;
- }
- sp++; /* skip leading / */
- /* no multivalued RDN by default */
- mval[ne_num] = 0;
- while (*sp)
- {
- /* collect type */
- ne_types[ne_num] = bp;
- while (*sp)
- {
- if (*sp == '\\') /* is there anything to escape in the type...? */
- {
- if (*++sp)
- *bp++ = *sp++;
- else
- {
- //BIO_printf(bio_err, "escape character at end of string\n");
- goto error;
- }
- }
- else if (*sp == '=')
- {
- sp++;
- *bp++ = '\0';
- break;
- }
- else
- *bp++ = *sp++;
- }
- if (!*sp)
- {
- //BIO_printf(bio_err, "end of string encountered while processing type of subject name element #%d\n", ne_num);
- goto error;
- }
- ne_values[ne_num] = bp;
- while (*sp)
- {
- if (*sp == '\\')
- {
- if (*++sp)
- *bp++ = *sp++;
- else
- {
- //BIO_printf(bio_err, "escape character at end of string\n");
- goto error;
- }
- }
- else if (*sp == '/')
- {
- sp++;
- /* no multivalued RDN by default */
- mval[ne_num+1] = 0;
- break;
- }
- else if (*sp == '+' && multirdn)
- {
- /* a not escaped + signals a mutlivalued RDN */
- sp++;
- mval[ne_num+1] = -1;
- break;
- }
- else
- *bp++ = *sp++;
- }
- *bp++ = '\0';
- ne_num++;
- }
- if (!(n = X509_NAME_new()))
- goto error;
- for (i = 0; i < ne_num; i++)
- {
- if ((nid=OBJ_txt2nid(ne_types[i])) == NID_undef)
- {
- //BIO_printf(bio_err, "Subject Attribute %s has no known NID, skipped\n", ne_types[i]);
- continue;
- }
- if (!*ne_values[i])
- {
- //BIO_printf(bio_err, "No value provided for Subject Attribute %s, skipped\n", ne_types[i]);
- continue;
- }
- if (!X509_NAME_add_entry_by_NID(n, nid, chtype, (unsigned char*)ne_values[i], -1,-1,mval[i]))
- goto error;
- }
- OPENSSL_free(ne_values);
- OPENSSL_free(ne_types);
- OPENSSL_free(buf);
- OPENSSL_free(mval);
- return n;
- error:
- X509_NAME_free(n);
- if (ne_values)
- OPENSSL_free(ne_values);
- if (ne_types)
- OPENSSL_free(ne_types);
- if (mval)
- OPENSSL_free(mval);
- if (buf)
- OPENSSL_free(buf);
- return NULL;
- }
- X509_NAME *CreateDN(char *pbEmail, char *pbCN, char *pbOU, char *pbO, char *pbL, char *pbST, char *pbC)
- {
- X509_NAME *pX509Name = NULL;
- if(pbCN == NULL)
- {
- return NULL;
- }
- if (!(pX509Name = X509_NAME_new()))
- {
- return NULL;
- }
- X509_NAME_add_entry_by_txt(pX509Name, "emailAddress", V_ASN1_UTF8STRING, pbEmail, -1, -1, 0);
- X509_NAME_add_entry_by_txt(pX509Name, "CN", V_ASN1_UTF8STRING, pbCN, -1, -1, 0);
- X509_NAME_add_entry_by_txt(pX509Name, "OU", V_ASN1_UTF8STRING, pbOU, -1, -1, 0);
- X509_NAME_add_entry_by_txt(pX509Name, "O", V_ASN1_UTF8STRING, pbO, -1, -1, 0);
- X509_NAME_add_entry_by_txt(pX509Name, "L", V_ASN1_UTF8STRING, pbL, -1, -1, 0);
- X509_NAME_add_entry_by_txt(pX509Name, "ST", V_ASN1_UTF8STRING, pbST, -1, -1, 0);
- X509_NAME_add_entry_by_txt(pX509Name, "C", V_ASN1_UTF8STRING, pbC, -1, -1, 0);
- return pX509Name;
- }
- int GenCSR(char *pbDN, int nDNLen, char *pCSR, size_t nCSRSize)
- {
- char szAltName[] = "DNS:www.jinhill.com";
- char szComment[] = "Create by Jinhill";
- char szKeyUsage[] = "digitalSignature, nonRepudiation";
- char szExKeyUsage[] = "serverAuth, clientAuth";
- X509_REQ *pX509Req = NULL;
- int iRV = 0;
- long lVer = 3;
- X509_NAME *pX509DN = NULL;
- EVP_PKEY *pEVPKey = NULL;
- RSA *pRSA = NULL;
- X509_NAME_ENTRY *pX509Entry = NULL;
- char szBuf[255] = {0};
- char mdout[20];
- int nLen, nModLen;
- int bits = 2048;
- unsigned long E = RSA_3;
- unsigned char *pDer = NULL;
- unsigned char *p = NULL;
- FILE *fp = NULL;
- const EVP_MD *md = NULL;
- X509 *pX509 = NULL;
- BIO *pBIO = NULL;
- BIO *pPemBIO = NULL;
- BUF_MEM *pBMem = NULL;
- //STACK_OF(X509_EXTENSION) *pX509Ext;
- if(pbDN == NULL)
- {
- return -1;
- }
- pX509DN = parse_name(pbDN, V_ASN1_UTF8STRING, 0);
- pX509Req = X509_REQ_new();
- iRV = X509_REQ_set_version(pX509Req, lVer);
- // subject pX509Name
- iRV = X509_REQ_set_subject_name(pX509Req, pX509DN);
- /* pub key */
- pEVPKey = EVP_PKEY_new();
- pRSA = RSA_generate_key(bits, E, NULL, NULL);
- EVP_PKEY_assign_RSA(pEVPKey, pRSA);
- 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, szBuf, nLen);
- strcpy(szBuf, szKeyUsage);
- nLen = strlen(szBuf);
- iRV = X509_REQ_add1_attr_by_txt(pX509Req, "keyUsage", V_ASN1_UTF8STRING, szBuf, nLen);
- strcpy(szBuf, szExKeyUsage);
- nLen = strlen(szBuf);
- iRV = X509_REQ_add1_attr_by_txt(pX509Req, "extendedKeyUsage", V_ASN1_UTF8STRING, szBuf, nLen);
- strcpy(szBuf, szComment);
- nLen = strlen(szBuf);
- iRV = X509_REQ_add1_attr_by_txt(pX509Req, "nsComment", V_ASN1_UTF8STRING, szBuf, nLen);
- md = EVP_sha1();
- iRV = X509_REQ_digest(pX509Req, md, mdout, &nModLen);
- iRV = X509_REQ_sign(pX509Req, pEVPKey, md);
- if(!iRV)
- {
- printf("sign err!\n");
- X509_REQ_free(pX509Req);
- return -1;
- }
- // 写入文件PEM格式
- // pBIO = BIO_new_file("certreq.txt", "w");
- // PEM_write_bio_X509_REQ(pBIO, pX509Req, NULL, NULL);
- // BIO_free(pBIO);
- //返回PEM字符
- pPemBIO = BIO_new(BIO_s_mem());
- PEM_write_bio_X509_REQ(pPemBIO, pX509Req, NULL, NULL);
- BIO_get_mem_ptr(pPemBIO,&pBMem);
- if(pBMem->length <= nCSRSize)
- {
- memcpy(pCSR, pBMem->data, pBMem->length);
- }
- BIO_free(pPemBIO);
- /* DER编码 */
- //nLen = i2d_X509_REQ(pX509Req, NULL);
- //pDer = (unsigned char *)malloc(nLen);
- //p = pDer;
- //nLen = i2d_X509_REQ(pX509Req, &p);
- //free(pDer);
- // 验证CSR
- OpenSSL_add_all_algorithms();
- iRV = X509_REQ_verify(pX509Req, pEVPKey);
- if(iRV<0)
- {
- printf("verify err.\n");
- }
- X509_REQ_free(pX509Req);
- return nCSRSize;
- }
- int main()
- {
- char chDN[255] = "/CN=www.jinhill.com/O=Beijing Jinhill Inc./C=CN";
- char chCSR[2048] = {0};
- int rv = GenCSR(chDN, strlen(chDN), chCSR, sizeof(chCSR));
- printf("CSR:\n%s", chCSR);
- }
openssl 生成CSR的更多相关文章
- 使用OpenSSL生成CSR文件,并申请全球通用SSL证书
http://www.openssl.org 上只有OpenSSL的原代码下载,为了方便Windows用户使用OpenSSL,我们特地为您准备了OpenSSL 0.9.8.a for win32的可执 ...
- linux下使用openssl生成 csr crt CA证书
证书文件生成:一.服务器端1.生成服务器端 私钥(key文件);openssl genrsa -des3 -out server.key 1024运行时会提示输入密码,此密码用于加密key文件( ...
- C++ OpenSSL 之三:生成CSR文件
1.等同于使用: openssl req -new -key "key_path" -out "save_path" -subj "/emailAdd ...
- 对称、非对称加密算,openssl生成证书(笔记)
对称加密算法 1.密钥只有一个,加密和解密都需要同一个密钥2.DES,IDEA,AES3.明文+密钥=密文, 密文+密钥=明文4.加密速度快,系统开销小,适用大量数据的加密 非对称加密算法1.密钥由公 ...
- 使用 openssl 生成证书
一.openssl 简介 目前最流行的 SSL 密码库工具官网:https://www.openssl.org/source/ 构成部分 密码算法库 密钥和证书封装管理功能 SSL通信API接口 用途 ...
- openssl生成ssl证书
openssl生成ssl证书 x509证书一般会用到三类文,key,csr,crt. Key 是私用密钥openssl格,通常是rsa算法. Csr 是证书请求文件,用于申请证书.在制作csr文件的时 ...
- CentOS6系统openssl生成证书和自签证书
CentOS6系统openssl生成证书和自签证书的过程,记录一下,本文基于CentOS 6 64bit.$ yum install openssl openssl-devel 1,生成服务器端的私钥 ...
- 用Keytool和OpenSSL生成和签发数字证书
一)keytool生成私钥文件(.key)和签名请求文件(.csr),openssl签发数字证书 J2SDK在目录%JAVA_HOME%/bin提供了密钥库管理工具Keytool,用于管理密 ...
- 使用OpenSSL生成证书
使用OpenSSL生成证书 下载安装openssl,进入/bin/下面,执行命令(把ssl目录下的openssl.cnf 拷贝到bin目录下)1.首先要生成服务器端的私钥(key文件):openssl ...
随机推荐
- JAX-WS 学习一:基于java的最简单的WebService服务
JAVA 1.6 之后,自带的JAX-WS API,这使得我们可以很方便的开发一个基于Java的WebService服务. 基于JAVA的WebService 服务 1.创建服务端WebService ...
- hdu 5675 ztr loves math(数学技巧)
Problem Description ztr loves research Math.One day,He thought about the "Lower Edition" o ...
- 如何实现 iOS 自定义状态栏
给大家介绍如何实现 iOS 自定义状态栏 Sample Code: 01 UIWindow * statusWindow = [[UIWindow alloc] initWithFrame:[UIAp ...
- Gradle Tips#1-tasks
原文链接 以这篇博客開始,我将写一系列关于Gradle的文章,用来记录接触Gradle构建脚本以来我所理解的Gradle. 今天要讲的就是Gradle tasks以及task的配置和运行.可能有的读者 ...
- 男同胞爱小秘籍--作为爱他的女朋友了几天C规划
各位男同胞,不知道你的女朋友没有在过去的一问天,你这个问题~~ 场景重现: 女友:"今天天气不错." 你们:"对" 女友:"今天是我们知道它的最初几天 ...
- 为github帐号添加SSH keys
为github帐号添加SSH keys 2012-05-26 00:05 34279人阅读 评论(6) 收藏 举报 ssh文本编辑gitvim工具up 使用git clone命令从github上同步g ...
- EffectiveC#1--尽可能的使用属性(property),而不是数据成员(field)
1.属性可以进行数据绑定 2.可以做数据安全校验.在对数据检测时,如果发现数据不满足条件,最好以抛出异常的形式来解决 如下代码不可取 public string Name { get { if(thi ...
- 前端--关于CSS盒模型
CSS样式规则的学习是很繁琐和枯燥的,因为它不像物理.数学或者其他编程语言一样有一些基本概念.有一些基本公理或者规则,其他所有的表现都是概念在这些公里或者规则之下的逻辑游戏,CSS是有一些基本概念,但 ...
- solr group分组查询
如:http://localhost:8080/solr/test_core/select?q=*:*&wt=json&indent=true&group=true&g ...
- A Bit Of Knowledge
iOS推崇使用png格式的图片,说这样不会失帧 imageNamed 和 imageWithContentOfFile的区别 imageNamed会使用系统缓存,对重复加载的图片速度会快一些,效果好. ...