openssl 生成CSR

openssl 生成CSR

 分类:
 

将openssl如何生成CSR写了一上DEMO,支持扩展属性,同时增加了通过DN字符串转X509_NAME的方法。

 

[cpp] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. #include <string.h>  
  2. #include <openssl/x509.h>  
  3. #include <openssl/rsa.h>  
  4. #pragma comment(lib, "libeay32.lib")  
  5.   
  6. /* 
  7. * subject is expected to be in the format /type0=value0/type1=value1/type2=... 
  8. * where characters may be escaped by \ 
  9. */  
  10. X509_NAME *parse_name(char *subject, long chtype, int multirdn)  
  11. {  
  12.     size_t buflen = strlen(subject)+1; /* to copy the types and values into. due to escaping, the copy can only become shorter */  
  13.     char *buf = OPENSSL_malloc(buflen);  
  14.     size_t max_ne = buflen / 2 + 1; /* maximum number of name elements */  
  15.     char **ne_types = OPENSSL_malloc(max_ne * sizeof (char *));  
  16.     char **ne_values = OPENSSL_malloc(max_ne * sizeof (char *));  
  17.     int *mval = OPENSSL_malloc (max_ne * sizeof (int));  
  18.       
  19.     char *sp = subject, *bp = buf;  
  20.     int i, ne_num = 0;  
  21.       
  22.     X509_NAME *n = NULL;  
  23.     int nid;  
  24.       
  25.     if (!buf || !ne_types || !ne_values || !mval)  
  26.     {  
  27.         //BIO_printf(bio_err, "malloc error\n");  
  28.         goto error;  
  29.     }     
  30.       
  31.     if (*subject != '/')  
  32.     {  
  33.         //BIO_printf(bio_err, "Subject does not start with '/'.\n");  
  34.         goto error;  
  35.     }  
  36.     sp++; /* skip leading / */  
  37.       
  38.     /* no multivalued RDN by default */  
  39.     mval[ne_num] = 0;  
  40.       
  41.     while (*sp)  
  42.     {  
  43.         /* collect type */  
  44.         ne_types[ne_num] = bp;  
  45.         while (*sp)  
  46.         {  
  47.             if (*sp == '\\') /* is there anything to escape in the type...? */  
  48.             {  
  49.                 if (*++sp)  
  50.                     *bp++ = *sp++;  
  51.                 else      
  52.                 {  
  53.                     //BIO_printf(bio_err, "escape character at end of string\n");  
  54.                     goto error;  
  55.                 }  
  56.             }     
  57.             else if (*sp == '=')  
  58.             {  
  59.                 sp++;  
  60.                 *bp++ = '\0';  
  61.                 break;  
  62.             }  
  63.             else  
  64.                 *bp++ = *sp++;  
  65.         }  
  66.         if (!*sp)  
  67.         {  
  68.             //BIO_printf(bio_err, "end of string encountered while processing type of subject name element #%d\n", ne_num);  
  69.             goto error;  
  70.         }  
  71.         ne_values[ne_num] = bp;  
  72.         while (*sp)  
  73.         {  
  74.             if (*sp == '\\')  
  75.             {  
  76.                 if (*++sp)  
  77.                     *bp++ = *sp++;  
  78.                 else  
  79.                 {  
  80.                     //BIO_printf(bio_err, "escape character at end of string\n");  
  81.                     goto error;  
  82.                 }  
  83.             }  
  84.             else if (*sp == '/')  
  85.             {  
  86.                 sp++;  
  87.                 /* no multivalued RDN by default */  
  88.                 mval[ne_num+1] = 0;  
  89.                 break;  
  90.             }  
  91.             else if (*sp == '+' && multirdn)  
  92.             {  
  93.                 /* a not escaped + signals a mutlivalued RDN */  
  94.                 sp++;  
  95.                 mval[ne_num+1] = -1;  
  96.                 break;  
  97.             }  
  98.             else  
  99.                 *bp++ = *sp++;  
  100.         }  
  101.         *bp++ = '\0';  
  102.         ne_num++;  
  103.     }     
  104.       
  105.     if (!(n = X509_NAME_new()))  
  106.         goto error;  
  107.       
  108.     for (i = 0; i < ne_num; i++)  
  109.     {  
  110.         if ((nid=OBJ_txt2nid(ne_types[i])) == NID_undef)  
  111.         {  
  112.             //BIO_printf(bio_err, "Subject Attribute %s has no known NID, skipped\n", ne_types[i]);  
  113.             continue;  
  114.         }  
  115.           
  116.         if (!*ne_values[i])  
  117.         {  
  118.             //BIO_printf(bio_err, "No value provided for Subject Attribute %s, skipped\n", ne_types[i]);  
  119.             continue;  
  120.         }  
  121.           
  122.         if (!X509_NAME_add_entry_by_NID(n, nid, chtype, (unsigned char*)ne_values[i], -1,-1,mval[i]))  
  123.             goto error;  
  124.     }  
  125.       
  126.     OPENSSL_free(ne_values);  
  127.     OPENSSL_free(ne_types);  
  128.     OPENSSL_free(buf);  
  129.     OPENSSL_free(mval);  
  130.     return n;  
  131.       
  132. error:  
  133.     X509_NAME_free(n);  
  134.     if (ne_values)  
  135.         OPENSSL_free(ne_values);  
  136.     if (ne_types)  
  137.         OPENSSL_free(ne_types);  
  138.     if (mval)  
  139.         OPENSSL_free(mval);  
  140.     if (buf)  
  141.         OPENSSL_free(buf);  
  142.     return NULL;  
  143. }  
  144.   
  145. X509_NAME *CreateDN(char *pbEmail, char *pbCN, char *pbOU, char *pbO, char *pbL, char *pbST, char *pbC)  
  146. {  
  147.     X509_NAME *pX509Name = NULL;  
  148.     if(pbCN == NULL)  
  149.     {  
  150.         return NULL;  
  151.     }  
  152.       
  153.     if (!(pX509Name = X509_NAME_new()))  
  154.     {  
  155.         return NULL;  
  156.     }  
  157.     X509_NAME_add_entry_by_txt(pX509Name, "emailAddress", V_ASN1_UTF8STRING, pbEmail, -1, -1, 0);  
  158.     X509_NAME_add_entry_by_txt(pX509Name, "CN", V_ASN1_UTF8STRING, pbCN, -1, -1, 0);  
  159.     X509_NAME_add_entry_by_txt(pX509Name, "OU", V_ASN1_UTF8STRING, pbOU, -1, -1, 0);  
  160.     X509_NAME_add_entry_by_txt(pX509Name, "O", V_ASN1_UTF8STRING, pbO, -1, -1, 0);  
  161.     X509_NAME_add_entry_by_txt(pX509Name, "L", V_ASN1_UTF8STRING, pbL, -1, -1, 0);  
  162.     X509_NAME_add_entry_by_txt(pX509Name, "ST", V_ASN1_UTF8STRING, pbST, -1, -1, 0);  
  163.     X509_NAME_add_entry_by_txt(pX509Name, "C", V_ASN1_UTF8STRING, pbC, -1, -1, 0);  
  164.     return pX509Name;  
  165. }  
  166.   
  167. int GenCSR(char *pbDN, int nDNLen, char *pCSR, size_t nCSRSize)  
  168. {  
  169.     char szAltName[] = "DNS:www.jinhill.com";  
  170.     char szComment[] = "Create by Jinhill";  
  171.     char szKeyUsage[] = "digitalSignature, nonRepudiation";  
  172.     char szExKeyUsage[] = "serverAuth, clientAuth";  
  173.       
  174.     X509_REQ        *pX509Req = NULL;  
  175.     int             iRV = 0;  
  176.     long            lVer = 3;  
  177.     X509_NAME       *pX509DN = NULL;  
  178.     EVP_PKEY        *pEVPKey = NULL;  
  179.     RSA             *pRSA = NULL;  
  180.     X509_NAME_ENTRY *pX509Entry = NULL;  
  181.     char            szBuf[255] = {0};  
  182.     char            mdout[20];  
  183.     int             nLen, nModLen;  
  184.     int             bits = 2048;  
  185.     unsigned long   E = RSA_3;  
  186.     unsigned char   *pDer = NULL;  
  187.     unsigned char   *p = NULL;  
  188.     FILE            *fp = NULL;  
  189.     const EVP_MD    *md = NULL;  
  190.     X509            *pX509 = NULL;  
  191.     BIO             *pBIO = NULL;  
  192.     BIO             *pPemBIO = NULL;  
  193.     BUF_MEM         *pBMem = NULL;  
  194.       
  195.     //STACK_OF(X509_EXTENSION) *pX509Ext;  
  196.       
  197.     if(pbDN == NULL)  
  198.     {  
  199.         return -1;  
  200.     }  
  201.     pX509DN = parse_name(pbDN, V_ASN1_UTF8STRING, 0);  
  202.       
  203.     pX509Req = X509_REQ_new();  
  204.       
  205.     iRV = X509_REQ_set_version(pX509Req, lVer);  
  206.       
  207.     // subject pX509Name   
  208.     iRV = X509_REQ_set_subject_name(pX509Req, pX509DN);  
  209.       
  210.     /* pub key */  
  211.     pEVPKey = EVP_PKEY_new();  
  212.     pRSA = RSA_generate_key(bits, E, NULL, NULL);  
  213.     EVP_PKEY_assign_RSA(pEVPKey, pRSA);  
  214.     iRV = X509_REQ_set_pubkey(pX509Req, pEVPKey);  
  215.       
  216.     /* attribute */  
  217.     strcpy(szBuf, szAltName);  
  218.     nLen = strlen(szBuf);  
  219.     iRV = X509_REQ_add1_attr_by_txt(pX509Req, "subjectAltName", V_ASN1_UTF8STRING, szBuf, nLen);  
  220.       
  221.     strcpy(szBuf, szKeyUsage);  
  222.     nLen = strlen(szBuf);  
  223.     iRV = X509_REQ_add1_attr_by_txt(pX509Req, "keyUsage", V_ASN1_UTF8STRING, szBuf, nLen);  
  224.       
  225.       
  226.     strcpy(szBuf, szExKeyUsage);  
  227.     nLen = strlen(szBuf);  
  228.     iRV = X509_REQ_add1_attr_by_txt(pX509Req, "extendedKeyUsage", V_ASN1_UTF8STRING, szBuf, nLen);  
  229.       
  230.       
  231.     strcpy(szBuf, szComment);  
  232.     nLen = strlen(szBuf);  
  233.     iRV = X509_REQ_add1_attr_by_txt(pX509Req, "nsComment", V_ASN1_UTF8STRING, szBuf, nLen);  
  234.       
  235.       
  236.     md = EVP_sha1();  
  237.     iRV = X509_REQ_digest(pX509Req, md, mdout, &nModLen);  
  238.     iRV = X509_REQ_sign(pX509Req, pEVPKey, md);  
  239.     if(!iRV)  
  240.     {  
  241.         printf("sign err!\n");  
  242.         X509_REQ_free(pX509Req);  
  243.         return -1;  
  244.     }  
  245.       
  246.     // 写入文件PEM格式   
  247.     //  pBIO = BIO_new_file("certreq.txt", "w");  
  248.     //  PEM_write_bio_X509_REQ(pBIO, pX509Req, NULL, NULL);  
  249.     //  BIO_free(pBIO);  
  250.       
  251.     //返回PEM字符  
  252.     pPemBIO = BIO_new(BIO_s_mem());  
  253.     PEM_write_bio_X509_REQ(pPemBIO, pX509Req, NULL, NULL);  
  254.     BIO_get_mem_ptr(pPemBIO,&pBMem);  
  255.     if(pBMem->length <= nCSRSize)  
  256.     {  
  257.         memcpy(pCSR, pBMem->data, pBMem->length);  
  258.     }  
  259.     BIO_free(pPemBIO);  
  260.       
  261.     /* DER编码 */  
  262.     //nLen = i2d_X509_REQ(pX509Req, NULL);  
  263.     //pDer = (unsigned char *)malloc(nLen);  
  264.     //p = pDer;  
  265.     //nLen = i2d_X509_REQ(pX509Req, &p);  
  266.     //free(pDer);  
  267.       
  268.     //  验证CSR  
  269.     OpenSSL_add_all_algorithms();  
  270.     iRV = X509_REQ_verify(pX509Req, pEVPKey);  
  271.     if(iRV<0)  
  272.     {  
  273.         printf("verify err.\n");  
  274.     }  
  275.       
  276.     X509_REQ_free(pX509Req);  
  277.     return nCSRSize;  
  278. }  
  279.   
  280.   
  281. int main()  
  282. {  
  283.     char chDN[255] = "/CN=www.jinhill.com/O=Beijing Jinhill Inc./C=CN";  
  284.     char chCSR[2048] = {0};  
  285.     int rv = GenCSR(chDN, strlen(chDN), chCSR, sizeof(chCSR));  
  286.     printf("CSR:\n%s", chCSR);  
  287. }  
posted @ 2017-01-10 09:43  吃饭了吗  阅读(927)  评论(0编辑  收藏  举报