https图解:
1、客户端向服务端发送SSL协议版本号、加密算法种类、随机数等信息。
2、服务端给客户端返回SSL协议版本号、加密算法种类、随机数等信息,同时也返回服务器端的证书,即公钥证书
3、客户端使用服务端返回的信息验证服务器的合法性,包括:
证书是否过期
发型服务器证书的CA是否可靠
返回的公钥是否能正确解开返回证书中的数字签名
服务器证书上的域名是否和服务器的实际域名相匹配
验证通过后,将继续进行通信,否则,终止通信
4、客户端向服务端发送自己所能支持的对称加密方案,供服务器端进行选择
5、服务器端在客户端提供的加密方案中选择加密程度最高的加密方式。
6、服务器将选择好的加密方案通过明文方式返回给客户端
7、客户端接收到服务端返回的加密方式后,使用该加密方式生成产生随机码,用作通信过程中对称加密的密钥,使用服务端返回的公钥进行加密,将加密后的随机码发送至服务器
8、服务器收到客户端返回的加密信息后,使用自己的私钥进行解密,获取对称加密密钥。 在接下来的会话中,服务器和客户端将会使用该密码进行对称加密,保证通信过程中信息的安全。
libcurl库:
libcurl是一个跨平台的网络协议库,支持http, https, ftp, gopher, telnet, dict, file, 和ldap 协议。libcurl同样支持HTTPS证书授权,HTTP POST, HTTP PUT, FTP 上传, HTTP基本表单上传,代理,cookies,和用户认证。文档地址https://curl.haxx.se/libcurl/c/libcurl.html
libcurl和curl命令的区别:
相同点
curl和libcurl都可以利用多种多样的协议来传输文件,包括HTTP, HTTPS, FTP, FTPS, GOPHER, LDAP, DICT, TELNET and FILE等。
都支持支持SSL证书,HTTP POST, HTTP PUT,FTP上传,基于表单的HTTP上传,代理(proxies)、cookies、用户名/密码认证(Basic, Digest, NTLM等)、下载文件断点续传,上载文件断点续传(file transfer resume),http代理服务器管道(proxy tunneling)等
不同点
curl是命令行工具,可以通过shell或脚本来运行curl。curl底层所使用的库是libcurl。
libcurl是一个库,通常与别的程序绑定在一起使用,如命令行工具curl就是封装了libcurl库。所以我们也可以在你自己的程序或项目中使用libcurl以获得类似CURL的强大功能。
实例:
1获取
#include <stdio.h> #include <curl/curl.h> #include <stdlib.h> int main(int argc, char *argv[]) { CURL *curl; //定义CURL类型的指针 CURLcode res; //定义CURLcode类型的变量,保存返回状态码 if(argc!=2) { printf("Usage : file <url>; "); exit(1); } curl = curl_easy_init(); //初始化一个CURL类型的指针 if(curl!=NULL) { //设置curl选项. 其中CURLOPT_URL是让用户指 定url. argv[1]中存放的命令行传进来的网址 curl_easy_setopt(curl, CURLOPT_URL, argv[1]); //调用curl_easy_perform 执行我们的设置.并进行相关的操作. 在这 里只在屏幕上显示出来. res = curl_easy_perform(curl); //清除curl操作. curl_easy_cleanup(curl); } return 0; }
编译:
gcc http1.c -o http1 –lcurl
执行:
./http1 www.baidu.com
本例只引入了libcurl的函数库,
调用curl_global_init()初始化libcurl
调用curl_easy_init()函数得到 easy interface型指针
调用curl_easy_setopt()设置传输选项
根据curl_easy_setopt()设置的传输选项,实现回调函数以完成用户特定任务
调用curl_easy_perform()函数完成传输任务
调用curl_easy_cleanup()释放内存
在整个过程中设置curl_easy_setopt()参数是最关键的,几乎所有的libcurl程序都要使用它。
实例2:进行ssl验证
/* <DESC> * 一个简单的https get ,输出网页并验证 * </DESC> */ #include <stdio.h> #include <stdlib.h> #include <curl/curl.h> int main(int argc, char *argv[]) { CURL *curl; //定义CURL类型的指针 CURLcode res; //定义CURLcode类型的变量,保存返回状态码 /* if(argc!=2) { printf("Usage : file <url>; "); exit(1); } */ //初始化SSL and Win32运行环境 curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init(); //初始化一个CURL类型的指针 if(curl!=NULL) { //设置curl选项. 其中CURLOPT_URL是让用户指 定url. argv[1]中存放的命令行传进来的网址 curl_easy_setopt(curl, CURLOPT_URL, "https://www.baidu.com"); //curl_easy_setopt(curl, CURLOPT_URL, argv[1]); //用第三方机构颁发的CA证书解密服务器端返回的证书并验证合法性,默认1L开启检查,0L忽略检查 curl_easy_setopt(curl,CURLOPT_SSL_VERIFYPEER,1L); //验证返回的证书是否与请求的域名相同,避免被篡改证书文件,默认值2L,0L忽略检查 curl_easy_setopt(curl,CURLOPT_SSL_VERIFYHOST,2L); //curl_easy_setopt(curl,CURLOPT_CAPATH,ca_path);//ca证书路径 curl_easy_setopt(curl,CURLOPT_CAINFO,"cacert.pem");//curl官网下载的根证书 //设置curl选项,其中CURLOPT_VERBOSE是显示执行过程中的调试信息 输出到控制台 curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); //不显示进度,如果设置为0L,则显示处理的进度条 curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1L); //调用curl_easy_perform 执行我们的设置.并进行相关的操作. 在这 里只在屏幕上显示出来. res = curl_easy_perform(curl); //检查错误信息输出到控制台 if(res!=CURLE_OK){ fprintf(stderr,"curl_easy_perfrom() failed:%s ",curl_easy_strerror(res)); } //清除curl操作. curl_easy_cleanup(curl); } curl_global_cleanup(); return 0; }
(1)到 curl 官网下载证书
curl --remote-name --time-cond cacert.pem https://curl.haxx.se/ca/cacert.pem
(2)在你的程序中设置证书的路径
// 不检查证书
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
// SSL CA证书
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L); // 验证服务器证书有效性
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2L); // 检验证书中的主机名和你访问的主机名是否一致
curl_easy_setopt(curl, CURLOPT_CAPATH, "./lib/"); // 设置证书路径
//curl_easy_setopt(curl, CURLOPT_CAINFO, "./lib/cacert.pem"); // 具体的 CA 证书,和上一行效果一样,选用一个即可
(1)使用 PATH 或 INFO 设置路径前要用curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L);开启验证证书功能
(2)使用curl_easy_setopt(curl, CURLOPT_CAPATH, "./lib/");设置证书路径
或使用curl_easy_setopt(curl, CURLOPT_CAINFO, "./lib/cacert.pem");设置具体的 CA 证书