新闻  |   论坛  |   博客  |   在线研讨会
C语言实现Openssl+CURL+nginx 单向认证
电子禅石 | 2020-07-25 17:01:21    阅读:1941   发布文章

这段时间在做本地终端链接服务器的工作,在此记录下,以免将来忘了。

首先有一个已经搭建好的nginx服务器,并且能够实现单向认证。

然后现在服务器端生成证书请求文件。

1.用openssl创建私钥


openssl genrsa -out server.key

1

2.用私钥创建证书请求文件


openssl req -new -key server.key -out server.csr

1

CA签发证书:


CA是专门签发证书的权威机构,处于证书的最顶端。自签是用自己的私钥给证书签名,CA签发则是用CA的私钥给自己的证书签名来保证证书的可靠性。因为是要实现单向认证,所以就要有CA进行认证。因为CA认证机构是要花钱的,因此自己创建CA。

1.生成CA私钥和证书


openssl req -new -x509 -keyout ca.key -out ca.crt

1

2.生成CA签名证书


openssl ca -in server.csr -out server.crt -cert ca.crt -keyfile ca.key -config openssl.cnf

1

这里我用openssl.cnf来自定义生成ca.crt的路径。openssl.cnf默认的存放路径在/etc/pki/tls

在openssl.cnf中只修改了一行


#dir        = /etc/pki/CA  //默认地址

dir             = /home/pki/ServerCert 

certs           = $dir/certs  

1

2

3

创建完成后,本地需要的文件是ca.crt,nginx服务中需要的是server.crt。

在nginx中配置证书如下:


server {

    listen       443 ssl;

    server_name  localhost;

    ssl on;

    ssl_certificate /etc/nginx/pki/server.crt;

    ssl_certificate_key /etc/nginx/pki/server.key;

    ssl_protocols TLSv1.2;

    ssl_session_cache    shared:SSL:1m;

    ssl_session_timeout  5m;

    ssl_ciphers  HIGH:!aNULL:!MD5;

    ssl_prefer_server_ciphers  on;

   ...

   ...

   }

1

2

3

4

5

6

7

8

9

10

11

12

13

14

下一步,在本地尝试用curl工具进行链接测试。


curl -v --cacert ca.crt https://198.168.1.145

1

得到服务器的登录页面的html。

注意,不要在curl后加 -k,-k是忽略了证书的正确与否,不能保证是否实现了认证。

最后用c代码实现这个链接过程。


#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include "lic.h"

#include <curl/curl.h>


#define FILENAME    "sr.dat"

#define URL         "https://192.168.1.145"


size_t write_data(void* buffer,size_t size,size_t nmemb,void *stream)

{

    FILE *fptr = (FILE*)stream;

    fwrite(buffer,size,nmemb,fptr);

    return size*nmemb;

}


int download_license(char *UniqueID, char *OderNum)

{

    CURL *curl;

    CURLcode res;

    FILE * fptr;

    char post_parameter[4096];                              //传入的参数

    struct curl_slist *http_header = NULL;                  //定义参数头

    struct curl_slist *headers = NULL;

    char *pCaPath = "/home/pki/ca.crt";

    //char *UniqueID = arg[1];

    //char *OderNum = arg[2];


    if (! UniqueID)

    {

        fprintf(stderr,"Please enter unquieID!\n");         //没有输入UnquieID

        exit(0);

    }

    else

    {


        if (! OderNum)

        {

            fprintf(stderr,"Please enter oder num!\n");     //没有输入Oder num

            exit(0);

        }

        else

        {

            strcpy(post_parameter,"licenseID=%22");         //拼接输入的参数

            strcat(post_parameter, UniqueID);

            strcat(post_parameter, "%22&OderNumber=%22");

            strcat(post_parameter, OderNum);

            strcat(post_parameter, "%22");

        }

    }

    if ((fptr = fopen(FILENAME,"w")) == NULL)

    {

        fprintf(stderr,"fopen file error:%s\n",FILENAME);   //文件打开错误

        return -1;

    }

    headers = curl_slist_append(headers, "Host: 192.168.65.128");

    headers = curl_slist_append(headers, "User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:45.0) Gecko/20100101 Firefox/45.0");

    headers = curl_slist_append(headers, "Accept: application/json, text/javascript, */*; q=0.01");

    headers = curl_slist_append(headers, "Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3");

    headers = curl_slist_append(headers, "Accept-Encoding: gzip, deflate");

    headers = curl_slist_append(headers, "X-Requested-With: XMLHttpRequest");

    headers = curl_slist_append(headers, "Cookie: lastTimeLines=0; cipher_session=1; cipher_key=1; down=1");


    curl = curl_easy_init();

    if (!curl)

    {

        fprintf(stderr,"curl init failed\n");

        return -1;

    }

    //curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);  

    //curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);

    curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L);//openssl编译时使用curl官网或者firefox导出的第三方根证书文件 

    curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2L);

    curl_easy_setopt(curl, CURLOPT_CAINFO, pCaPath);

    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);// 改协议头

    curl_easy_setopt(curl, CURLOPT_URL, URL); //url地址

    curl_easy_setopt(curl, CURLOPT_POSTFIELDS,post_parameter); //post参数

    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION,write_data); //对返回的数据进行操作的函数地址


    curl_easy_setopt(curl, CURLOPT_WRITEDATA,fptr); //这是write_data的第四个参数值


    res = curl_easy_perform(curl);


    if (res != CURLE_OK)

    {

        switch(res)

        {

        case CURLE_UNSUPPORTED_PROTOCOL:

            fprintf(stderr,"不支持的协议,由URL的头部指定\n");

        case CURLE_COULDNT_CONNECT:

            fprintf(stderr,"不能连接到remote主机或者代理\n");

        case CURLE_HTTP_RETURNED_ERROR:

            fprintf(stderr,"http返回错误\n");

        case CURLE_READ_ERROR:

            fprintf(stderr,"读本地文件错误\n");

        default:

            fprintf(stderr,"返回值:%d\n",res);

        }

        return -1;

    }


    close(fptr);

    curl_slist_free_all(headers);

    curl_easy_cleanup(curl);

}

————————————————

原文链接:https://blog.csdn.net/wang6562009/article/details/78403258


*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。

参与讨论
登录后参与讨论
属于自己的技术积累分享,成为嵌入式系统研发高手。
推荐文章
最近访客