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

news2025/2/28 6:33:08

文章目录

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


前言

本文是使用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)字节,也就是一个记录层的最大数据。
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【unity笔记】二、海洋系统Crest Ocean System基础

1. 创建海平面 首先确定项目中导入了HDRP插件。这里使用Crest Ocean System HDRP插件。 在场景下创建空对象&#xff0c;这里命名为Ocean。将 OceanRenderer 组件分配给Ocean。该组件将生成海洋几何图形并执行所有必需的初始化。其中Global Wind Speed 属性可以调节风浪大小。…

基于Verilog表达的FSM状态机

基于Verilog表达的FSM状态机 1 FSM1.1 Intro1.2 Why FSM?1.3 How to do 在这里聚焦基于Verilog的三段式状态机编程&#xff1b; 1 FSM 1.1 Intro 状态机是一种代码实现功能的范式&#xff1b;一切皆可状态机&#xff1b; 状态机编程四要素&#xff1a;– 1.状态State&#…

全新取图系统搭建,广泛应用,轻松解决找图难问题!

前言 在数字化高速发展的时代&#xff0c;图片已成为人们日常交流不可或缺的一部分。每个社交平台我们都需要头像、背景等去打造属于我们自己的一张名片。为了满足大众日益增长的需求&#xff0c;并创造更多的收益机会&#xff0c;搭建一款先进的取图系统真的很必要。 一、这款…

曲线拟合 | 二次B样条拟合曲线

B 样条曲线拟合实例&#xff1a;能平滑化曲线 1. 实例1 为MASS包中mcycle数据集。它测试了一系列模拟的交通车事故中&#xff0c;头部的加速度&#xff0c;以此来评估头盔的性能。times为撞击时间(ms)&#xff0c;accel为加速度&#xff08;g&#xff09;。首先导入数据&#…

阀性能试验台测控系统响应时间的计算

阀性能试验台的测控系统响应时间是衡量系统响应速度和实时性能的重要指标。响应时间的计算涉及到信号采集、处理和执行的全过程。本文提供了一种详细的方法来计算和评估测控系统的响应时间。

windows11 建立批处理bat文件来删除指定目录下的所有隐藏的文件。

今天在导入项目的时候发现之前项目中的文件夹中有很多隐藏的临时文件&#xff0c;这个文件应该是版本控制产生的&#xff0c;导致导入后文件夹上有X&#xff0c;然后里面文件是一个没有错。 我们来建立一个bat来&#xff0c;进行批量删除隐藏文件就可以了&#xff1a; echo o…

Landsat8的质量评估波段的一个应用

Landsat8一直是遥感界的热门话题。这不仅延续了自1972年以来NASA连续对地观测&#xff0c;而且这颗卫星为科学界带来了一些新的东西——质量评估波段&#xff08;the Quality Assessment (QA) Band&#xff09;。根据USGS Landsat Missions webpage&#xff0c;“QA通过标示哪个…

基于51单片机的智能恒温箱设计--数码管显示

一.硬件方案 根据恒温箱控制器的功能要求&#xff0c;并结合对51系列单片机软件编程自由度大&#xff0c;可用编程实现各种控制算法和逻辑控制。所以采用AT89C52作为电路系统的控制核心。按键将设置好的温度值传给单片机&#xff0c;通过温度显示模块显示出来。初始温度设置好…

FastAPI操作关系型数据库

FastAPI可以和任何数据库和任意样式的库配合使用&#xff0c;这里看一下使用SQLAlchemy的示例。下面的示例很容易的调整为PostgreSQL&#xff0c;MySQL&#xff0c;SQLite&#xff0c;Oracle等。当前示例中我们使用SQLite ORM对象关系映射 FastAPI可以与任何数据库在任何样式…

postman 工具下载安装使用教程_postman安装

本文讲解的是postman工具下载、Postman安装步骤、postman下载、postman安装教程。Postman是一款流行的API测试工具&#xff0c;它提供了一个用户友好的界面&#xff0c;用于发送和测试API请求&#xff0c;并且可以轻松地按需管理和组织请求。 这使得开发人员和测试人员能够更高…

Linux磁盘管理(MBR、分区表、分区、格式化)

目录 1、简单介绍 2、MBR&#xff1a; 2.1、分区表&#xff1a; 2.2、注意&#xff1a; 2.3、编号问题&#xff1a; 2.4、磁盘的命名&#xff1a; 2.5、格式化分区 1、简单介绍 1.1、track&#xff1a;磁道&#xff0c;就是磁盘上同心圆&#xff0c;从外向里&#xff0c…

shell循环以及实验

循环是一种重复执行的代码结构&#xff0c;只要满足循环的条件&#xff0c;会一直执行这个代码 循环条件&#xff1a;在一定范围之内&#xff0c;按照指定次数来执行循环。 循环体&#xff1a;在指定的次数内&#xff0c;执行的命令序列&#xff0c;只要条件满足&#xff0c;…

10.GLM

智谱AI GLM 大模型家族 最强基座模型 GLM-130B GLM (General Language Model Pretraining with Autoregressive Blank Infilling) 基于自回归空白填充的通用语言模型&#xff08;GLM&#xff09;。GLM通过增加二维位置编码并允许以任意顺序预测跨度来改进空白填充预训练&…

BigDecimal的这四个大坑,你都知道吗?

BigDecimal是Java中的一个类&#xff0c;提供了更精确的数字运算&#xff0c;在金融场景中经常使用到。在使用BigDecimal的时候一定要注意&#xff0c;否则可能会付出惨重的代价。 第一&#xff1a;初始化的坑 BigDecimal a new BigDecimal(0.01); BigDecimal b new BigDec…

【源码】【Spring+SpringMVC+MyBatis】电子商城网上购物平台的设计与开发

学生成绩管理系统 系统功能开发环境开发技术前端技术后端技术 系统展示登录界面注册界面系统首页商品详情页下单界面付款界面购物车界面 源码获取↓↓↓↓&#xff1a; 源码可在后台私信联系博主或文末添加博主微信获取帮助 系统功能 登录、注册模块&#xff1a;如果用户第一次…

【智能算法应用】基于粒子群算法的多尺度Retinex图像去雾方法

目录 1.算法原理2.粒子群算法的多尺度Retinex图像去雾方法3.结果展示4.参考文献5.代码获取 1.算法原理 【智能算法】粒子群算法&#xff08;PSO&#xff09;原理及实现 多尺度Retinex算法 在Retinex算法中&#xff0c;雾化图像的形成可以总结为入射光和反射光的乘积: I ( x…

用 Python 撸一个 Web 服务器-第1章:Web 开发简介

前言 Web 开发技术一直在高速发展&#xff0c;各种新奇概念与框架层出不穷&#xff0c;尤其在 Web 前端领域&#xff0c;几年前还是 jQuery 的天下&#xff0c;而如今在 Vue、React 等框架面前也显得廉颇老矣。 不过&#xff0c;虽然各种框架技术日新月异&#xff0c;但 Web …

2024 年十大关键渗透测试发现:您需要了解的内容

编辑信息技术 (IT) 专业人员在坏人之前发现公司弱点的最有效方法之一就是渗透测试。通过模拟现实世界的网络攻击&#xff0c;渗透测试&#xff08;有时称为 pentests&#xff09;可以提供有关组织安全状况的宝贵见解&#xff0c;揭示可能导致数据泄露或其他安全事件的弱点。 自…

zerotier自建moon方法

简介 使用zerotier已经有一段时间了&#xff0c;现在偶尔会出现服务器连接不上的情况。我就想自己建个moon来试试。记录一下过程&#xff0c;用作备忘录。 准备工作 准备一个有公网IP的云主机。我用的是“三丰云”&#xff0c;速度很快同时提供"免费虚拟主机"和“免费…

docker 部署nginx多级子域名(三级四级...)映射不同web项目,访问不同路径地址

一、背景 只有一台服务器&#xff0c;一个顶级域名&#xff0c;现在需要根据不同子域名访问不同web项目&#xff0c;比如 # 管理后台 cms.biacu.com# 客户端h5 h5.biacu.com# 四级域名 h5.s.biacu.com同时&#xff0c;不同web项目放在不同位置 二、 1、在云服务器上&#x…