Open ssl 简介
构成部分
用途
openssl生成csr的程序方法
将openssl如何生成CSR写了一上DEMO,支持扩展属性,同时增加了通过DN字符串转X509_NAME的方法。
[cpp]
#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.trustauth.cn”;
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.trustauth.cn/O=Beijing Jinhill Inc./C=CN”;
char chCSR[2048] = {0};
int rv = GenCSR(chDN, strlen(chDN), chCSR, sizeof(chCSR));
printf(“CSR:\n%s”, chCSR);
}
GDCA(数安时代)拥有国内自主签发的SSL证书以及是国际知名品牌:GlobalSign、Symantec、GeoTrust SSL证书国内金牌代理商,满足各种用户对SSL的各种要求,广大用户可根据自身的需求向GDCA申请合适的SSL证书,GDCA的专业团队将会为您提供最佳的HTTPS解决方案。