c语言利用openssl实现简单客户端和服务端(观察记录层最大长度)

文章目录

  • 前言
  • 一、客户端实现
  • 二、服务端实现
  • 总结


前言

本文是使用openssl111w实现的简单客户端和服务端,主要用于观察openssl一个记录层数据包的大小。


一、客户端实现

#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  
#include <unistd.h>  
#include <sys/types.h>   
#include <sys/socket.h>  
#include <netinet/in.h>  
#include <arpa/inet.h>  
#include <openssl/ssl.h>  
#include <openssl/err.h>  
#define PORT 8000
#define SERVER_IP "127.0.0.1"
#define SERVER_KEY "./rsa_cert/serverkey.pem"
#define SERVER_CERT "./rsa_cert/servercert.pem"
#define CA_CERT "./rsa_cert/cacert.pem"
// 初始化OpenSSL库 
void init_openssl() {  
    SSL_load_error_strings();  
    OpenSSL_add_all_algorithms();  
    SSL_library_init();  
}  
//创建原始套接字
int create_connect_fd()
{
    struct sockaddr_in serv_addr;
    int client_fd;
    
    // 创建socket
    if ((client_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        printf("\n Socket creation error \n");
        return -1;
    }
    
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(PORT);
    
    // 使用inet_pton转换IP字符串为网络字节序
    if(inet_pton(AF_INET, SERVER_IP, &serv_addr.sin_addr)<=0)
    {
        printf("\nInvalid address/ Address not supported \n");
        return -1;
    }
    
    // 连接服务器
    if (connect(client_fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
    {
        printf("\nConnection Failed \n");
        return -1;
    }
    return client_fd;
}
//创建ssl上下文
SSL_CTX* create_ssl_ctx() {  
    const SSL_METHOD *method;  
    SSL_CTX *ctx;  
  
    method = TLSv1_2_client_method();  
    ctx = SSL_CTX_new(method);  
    if (!ctx) {  
        printf("Unable to create SSL context");  
        ERR_print_errors_fp(stderr);  
        return NULL;
    } 
        // 加载服务器证书和私钥  
    if (SSL_CTX_use_certificate_file(ctx, SERVER_CERT, SSL_FILETYPE_PEM) <= 0) {  
        ERR_print_errors_fp(stderr); 
        printf("load server cert failed\n"); 
        return NULL;  
    }  
  
    if (SSL_CTX_use_PrivateKey_file(ctx, SERVER_KEY, SSL_FILETYPE_PEM) <= 0) {  
        ERR_print_errors_fp(stderr);  
        printf("load server key failed\n");
        return NULL;
    }  
  
    // 检查私钥和证书是否匹配  
    if (!SSL_CTX_check_private_key(ctx)) {  
        printf("cert and key mismatch\n");
        return NULL;
    }   
	//加载CA证书
    if (!SSL_CTX_load_verify_locations(ctx, CA_CERT, NULL)) {  
        printf("load ca cert failed\n");
        return NULL; 
    }  
      //必须验证服务端证书,不设置则不验证
    SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);  
    return ctx;  
}  


int main()
{
    SSL_CTX *ctx;
    SSL *ssl;
    int client_fd,send_len;
    char buf[102400] = {0};

    /* 初始化SSL库 */
    init_openssl();

    /* 创建SSL_CTX结构体 */
    ctx = create_ssl_ctx();  
    if(ctx == NULL)
    {
        printf("create ssl ctx failed\n");
        return -1;
    }
    /* TCP协议连接到服务器 */
    client_fd = create_connect_fd(); 
    if(client_fd < 0)
    {
        printf("create client fd failed\n");
        return -1;
    }
    //创建ssl对象
    ssl = SSL_new(ctx);
    SSL_set_fd(ssl, client_fd);
	//ssl握手
    if (SSL_connect(ssl) == -1) {
        ERR_print_errors_fp(stderr);
        return -1;
    }

    printf("Connected with %s encryption\n", SSL_get_cipher(ssl));

    /* 发送数据 */
    send_len = SSL_write(ssl, buf, sizeof(buf));
    if(send_len < 0)
    {
        printf("SSL_write failed\n");
    }
    else
    {
        printf("write len:%d\n", send_len);
    }
    SSL_shutdown(ssl);
    SSL_free(ssl);
    close(client_fd);
    SSL_CTX_free(ctx);
    return 0;
}

二、服务端实现

#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  
#include <unistd.h>  
#include <sys/types.h>   
#include <sys/socket.h>  
#include <netinet/in.h>  
#include <arpa/inet.h>  
#include <openssl/ssl.h>  
#include <openssl/err.h>  
#define PORT 8000
#define SERVER_KEY "./rsa_cert/serverkey.pem"
#define SERVER_CERT "./rsa_cert/servercert.pem"
#define CA_CERT "./rsa_cert/cacert.pem"
// 初始化OpenSSL库  
void init_openssl() {  
    SSL_load_error_strings();  
    OpenSSL_add_all_algorithms();  
    SSL_library_init();  
}  
   
// 创建ssl上下文 
SSL_CTX* create_ssl_ctx() {  
    const SSL_METHOD *method;  
    SSL_CTX *ctx;  
  
    OpenSSL_add_ssl_algorithms();  
    method = TLSv1_2_server_method();  
    ctx = SSL_CTX_new(method);  
    if (!ctx) {  
        printf("Unable to create SSL context");  
        ERR_print_errors_fp(stderr);  
        return NULL;
    }  
    // 加载服务器证书和私钥  
    if (SSL_CTX_use_certificate_file(ctx, SERVER_CERT, SSL_FILETYPE_PEM) <= 0) {  
        ERR_print_errors_fp(stderr); 
        printf("load server cert failed\n"); 
        return NULL;  
    }  
  
    if (SSL_CTX_use_PrivateKey_file(ctx, SERVER_KEY, SSL_FILETYPE_PEM) <= 0) {  
        ERR_print_errors_fp(stderr);  
        printf("load server key failed\n");
        return NULL;
    }  
  
    // 检查私钥和证书是否匹配  
    if (!SSL_CTX_check_private_key(ctx)) {  
        printf("cert and key mismatch\n");
        return NULL;
    }  

    if (!SSL_CTX_load_verify_locations(ctx, CA_CERT, NULL)) {  
        printf("load ca cert failed\n");
        return NULL; 
    }  
    //必须验证服务端证书,不设置则不验证
    SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);  
  
    return ctx;  
}  
//创建监听套接字
int create_listenfd()
{
    int listen_fd;
    struct sockaddr_in server_addr;
    int opt = 1;
    if ((listen_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0)
    {
        printf("socket failed\n");
        return -1;
    }
    
    // 设置socket选项,允许重复使用地址
    if (setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR,&opt, sizeof(opt)))
    {
        printf("setsockopt failed\n");
        return -1;
    }
    
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = INADDR_ANY;
    server_addr.sin_port = htons(PORT);
    
    // 绑定socket到指定地址和端口
    if (bind(listen_fd, (struct sockaddr *)&server_addr, 
                                sizeof(server_addr))<0)
    {
        printf("bind failed\n");
        return -1;
    }
    // 开始监听,最大等待队列长度为5
    if (listen(listen_fd, 5) < 0)
    {
        printf("listen failed\n");
        return -1;
    }
    return listen_fd;
}
  

int main() {  
    int listen_fd,con_fd,recv_len;
    char buf[20480] = {0};
    init_openssl();  
    //创建ssl上下文
    SSL_CTX *ctx = create_ssl_ctx();  
    if(ctx == NULL)
    {
        printf("create ssl ctx failed\n");
        return -1;
    }
    //创建监听套接字
    listen_fd = create_listenfd();
    if(listen_fd < 0)
    {
        printf("create listen fd failed\n");
        return -1;
    }

    while(1) {
        struct sockaddr_in client_addr;
        socklen_t len = sizeof(client_addr);
        SSL *ssl;
        //等待客户端发起tcp链接
        con_fd = accept(listen_fd, (struct sockaddr*)&client_addr, &len);
        if(con_fd < 0)
        {
            printf("create connetct fd failed\n");
            return -1;
        }
        printf("create connect fd success\n");

        ssl = SSL_new(ctx);
        SSL_set_fd(ssl, con_fd);
        //等待ssl握手
        if (SSL_accept(ssl) == -1) {
            ERR_print_errors_fp(stderr);
            return -1;
        } 
        printf("SSL Connection established\n");
        for (;;) {
          //读取ssl数据
            recv_len = SSL_read(ssl, buf, sizeof(buf));
            if (recv_len > 0)
                printf("Received_len:%d \n", recv_len);
            else {
                ERR_print_errors_fp(stderr);
                break;
            }
        }
        SSL_shutdown(ssl);
        SSL_free(ssl);
        close(con_fd);
    }

    SSL_CTX_free(ctx);
    close(listen_fd);
    return 0;  
}

总结

服务端ssl_read能够接受的最大数据包是16384(2^14)字节,也就是一个记录层的最大数据。
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/706519.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

搜维尔科技:Movella旗下的Xsens在人形机器人开发中得到广泛应用

人形机器人的发展正在全球范围内受到广泛关注。作为机器人领域的重要分支&#xff0c;人形机器人因其具备高度仿真的外观和动作&#xff0c;以及更贴近人类的行为模式&#xff0c;有望逐渐成为人们日常生活和工业生产中的得力助手。在中国&#xff0c;这一领域的发展尤为引人注…

湘江早报专访惟客数据李柯辰:湖南伢子返湘玩转“AI+金融”

来源 |《湘江早报》 记者 | 黄荣佳 ​ 随着数字化浪潮的到来&#xff0c;AI的风吹遍了各行各业&#xff0c;金融作为对新兴技术最敏感的行业&#xff0c;前沿技术的赋能&#xff0c;让金融科技成为行业发展的“新赛点”。作为一家以大数据和AI人工智能技术驱动的新一代数字化…

MYSQL六、存储引擎的认识

一、存储引擎 1、MySQL体系结构 连接层&#xff1a;最上层是一些客户端和链接服务&#xff0c;包含本地sock 通信和大多数基于客户端/服务端工具实现的类似于TCP/IP的通信。主要完成一些类似于连接处理、授权认证、及相关的安全方案。在该层上引入了线程池的概念&#xff0c;为…

使用大模型进行时间序列预测

今天想聊聊这周一篇关于使用语言模型进行时间序列预测的工作&#xff0c;这个工作的主要亮点有四个: 首先提出的Chronos框架将时间序列通过缩放和量化转换为token序列&#xff0c;从而可以直接使用语言模型架构(如T5, GPT-2等)来建模时间序列&#xff0c;不需要对模型架构做任…

Word菜谱制作教程

原始文本&#xff1a; 打开标尺 选中文字右键-段落&#xff0c; 制表位&#xff0c;选好字符和引导符 在文字和价格之间按下Tab 效果 参考资料好看视频-轻松有收获 Phrase&#xff1a;我觉等还是有点麻烦&#xff0c;可以插入表格&#xff0c;再把表格调整为无表框即可

60行代码加速20倍: NEON实现深度学习OD任务后处理绘框

【前言】 本文版权属于GiantPandaCV&#xff0c;未经允许&#xff0c;请勿转载&#xff01; 最近在学neon汇编加速&#xff0c;由于此前OD任务发现在检测后处理部分使用OpenCV较为占用资源且耗时&#xff0c;遂尝试使用NEON做后处理绘框&#xff0c;以达到加速并降低CPU资源消耗…

PHP简约轻型聊天室留言源码

无名轻聊是一款phptxt的轻型聊天室。 无名轻聊特点&#xff1a; 自适应电脑/手机 数据使用txt存放&#xff0c;默认显示近50条聊天记录 采用jqueryajax轮询方式&#xff0c;适合小型聊天环境。 访问地址加?zhi进入管理模式&#xff0c;发送 clear 清空聊天记录。 修改在…

品质卓越为你打造App UI 风格

品质卓越为你打造App UI 风格

【ElasticSearch】ElasticSearch基本概念

ES 是一个开源的高扩展的分布式全文检索引擎&#xff0c;它是对开源库 Luence 的封装&#xff0c;提供 REST API 接口 MySQL 更适合数据的存储和关系管理&#xff0c;即 CRUD&#xff1b;而 ES 更适合做海量数据的检索和分析&#xff0c;它可以秒级地从数据库中检索出我们感兴…

【论文复现|智能算法改进】基于改进鲸鱼优化算法的移动机器人多目标点路径规划

目录 1.算法原理2.数学模型3.改进点4.结果展示5.参考文献6.代码获取 1.算法原理 SCI二区|鲸鱼优化算法&#xff08;WOA&#xff09;原理及实现【附完整Matlab代码】 2.数学模型 使用 A* 算法生成所有目标点之间的距离矩阵U: U [ d 1 − 1 d 1 − 2 d 1 − 3 ⋯ d 1 − i d…

关于python下安装selenium以及使用

&#x1f4d1;打牌 &#xff1a; da pai ge的个人主页 &#x1f324;️个人专栏 &#xff1a; da pai ge的博客专栏 ☁️宝剑锋从磨砺出&#xff0c;梅花香自苦寒来 目录 1、win10安装python环境 2、…

深入理解指针(二)

目录 1. 数组名的理解 2. 使用指针访问数组 3. ⼀维数组传参的本质 4. 冒泡排序 5. 二级指针 6. 指针数组 7. 指针数组模拟二维数组 1. 数组名的理解 有下面一段代码: #include <stdio.h> int main() {int arr[10] { 1,2,3,4,5,6,7,8,9,10 };int* p &arr[…

本地无法连接linux上的MariaDB数据库

使用mysql -u root -p 输入密码&#xff1a; 进去之后没有user表&#xff0c;无法改user、host等信息。

Blender帧动画

时间线窗口Timeline用于定义帧动画 -视图&#xff1a;方法&#xff0c;平移&#xff0c;框显全部 -帧范围&#xff1a;可以调整动画共多少帧 -当前帧&#xff1a;可以拖动或手工指定 默认每秒24帧 定义一个帧动画类似unity的Timeline&#xff0c;只需定义关键帧&#xff0c…

【太原理工大学】软件安全技术—书本重点梳理、带背

收回我上一篇的话&#xff0c;这科挂人还是挺狠的&#xff0c;去年好像挂了四十号人 ( 老师没有划重点&#xff0c;这篇是我自己根据之前的博主的和课本总结的一些重点&#xff0c;本篇为理解性带背。(&#xff61; _ &#xff61;) ### 第一章&#xff1a;软件安全基础 - **零…

Flask快速入门(路由、CBV、请求和响应、session)

Flask快速入门&#xff08;路由、CBV、请求和响应、session&#xff09; 目录 Flask快速入门&#xff08;路由、CBV、请求和响应、session&#xff09;安装创建页面Debug模式快速使用Werkzeug介绍watchdog介绍快速体验 路由系统源码分析手动配置路由动态路由-转换器 Flask的CBV…

青书学堂 看视频 耍课时

1. 获取课程节点id ( /nynzy/Student/Course/GetStudyRecordAndScore ) 接口地址 2. 把所有的nodeId 保存下来 保存到 old.txt 格式 课程id 与 nodeId 用 | 隔开 3. 然后创建 test.php 注意把 cookie 换成自己的 <?php$oldFilename ./old.txt; $newFilename ./new.…

使用MySQL全文索引实现高效搜索功能

MySQL全文索引是MySQL提供的一种高效的搜索功能&#xff0c;可以快速地搜索文本内容。全文索引可以用于搜索大量文本数据&#xff0c;通常应用在文章、博客、论坛等需要搜索的场景中。 什么是MySQL全文索引 MySQL全文索引是一种用于快速搜索文本内容的索引技术。它可以在存储和…

vue+elementplus模拟“山野愚人居”简单实现个人博客

目录 一、项目介绍 二、项目截图 1.项目结构图 2.项目首页 3.文章详情 4.留言 5.读者 三、源码实现 1.项目依赖package.json 2.项目启动 3.读者页面源码 四、总结 一、项目介绍 模仿原博客&#xff1a;山野愚人居 - 记录我的生活、所见、所闻、所想…… 本项目参考以…

联邦学习权重聚合,联邦学习权重更新

目录 联邦学习权重聚合 model.state_dict() 保存模型参数 加载模型参数 注意事项 联邦学习权重更新 联邦学习权重聚合 model.state_dict() 在PyTorch框架中,model.state_dict() 是一个非常重要的方法,它用于获取模型的参数(即权重和偏置)作为一个有序字典(Order…