openssl engine在tls中的应用

2023-10-26

openssl engine的实现和原理在上一篇文章

https://blog.csdn.net/liu942947766/article/details/128837041?spm=1001.2014.3001.5502

openssl engine的加密套件协商应用

首先使用openssl engine引擎机制将算法替换为自己想要使用的第三方加密算法,然后使用openssl engine进行安全通信,不是所有的算法openssl都会支持(不支持则不会调用),可以通过查看当前版本openssl支持的加密套件有哪些,例如ECDHE-RSA-AES256-GCM-SHA384,分别对应密钥交换算法-数字签名算法-数据加密算法-摘要算法。只有openssl所支持的加密套件中的算法才支持进行安全通信,比如openssl engine利用第三方加密算法替换了openssl中rsa的算法,在ssl安全通信的时候选择加密套件协商使用ECDHE-RSA-AES256-GCM-SHA384组件后,会在ssl握手环节中使用engine中的算法进行证书验证。

如果engine替换的算法为aes,那么同理ssl握手环节中使用engine中的算法进行数据加密。

openssl engine引擎第三方算法替换原生算法是通过结构体绑定NID,例如要用引擎替换openssl协议库中的算法SHA256,那么引擎中算法结构体的NID 项应该填写“NID_sha256。

SSL_CTX_set_cipher_list 函数可以觉得选择使用的加密套件。

static const EVP_MD e_md5={
    NID_sha256,       //该引擎替换sha256算法 
    NID_md5WithRSAEncryption,
    SHA_DIGEST_LENGTH,
    EVP_MD_FLAG_DIGALGID_ABSENT,
    md5_init,
    md5_update,
    md5_final,
    NULL,
    NULL,
    SHA_CBLOCK,
    sizeof(EVP_MD *) + sizeof(MD5_CTX)
};

客户端代码

/*client.c*/
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <errno.h>
#include <sys/types.h>
#include "md5_engine.h"
#include <sys/socket.h>
#include <arpa/inet.h>

#include "openssl/rsa.h"      
#include "openssl/crypto.h"
#include "openssl/x509.h"
#include "openssl/pem.h"
#include "openssl/ssl.h"
#include "openssl/err.h"
#include "openssl/rand.h"

/*所有需要的参数信息都在此处以#define的形式提供*/
#define CERTF  "../key/client.crt"  /*客户端的证书(需经CA签名)*/
#define KEYF  "../key/client.key"   /*客户端的私钥(建议加密存储)*/
#define CACERT "../key/ca.crt"      /*CA 的证书*/

#define PORT   20001          /*服务端的端口*/
#define SERVER_ADDR "0"  /*服务段的IP地址*/

#define CHK_NULL(x) if ((x)==NULL) exit (-1)
#define CHK_ERR(err,s) if ((err)==-1) { perror(s); exit(-2); }
#define CHK_SSL(err) if ((err)==-1) { ERR_print_errors_fp(stderr); exit(-3); }

int main ()
{
#if 1
  ENGINE_load_rsapp(); //加载引擎
  ENGINE *rsa_st = NULL;
  rsa_st = ENGINE_by_id("emd5");//通过id返回engine对象
	if(rsa_st == NULL)
	{
		printf("get pkcs11 engine Error\n");
		return 0;
	}
  printf("name:%s\n",ENGINE_get_name(rsa_st));
	ENGINE_register_all_digests(rsa_st);
	ENGINE_set_default(rsa_st,ENGINE_METHOD_ALL);
	printf("test end.\n");
#endif

  int            err;
  int            sd;
  struct sockaddr_in sa;
  SSL_CTX*       ctx;
  SSL*           ssl;
  X509*          server_cert;
  char*          str;
  char           buf1[4096];
  SSL_METHOD    *meth;
  int            seed_int[100]; /*存放随机序列*/


  /* 初始化OpenSSL */
  SSL_library_init();
  /*加载算法库 */
  OpenSSL_add_ssl_algorithms();
  /*加载错误处理信息 */
  SSL_load_error_strings ();
  /*采用什么协议(SSLv2/SSLv3/TLSv1)在此指定*/
  meth = (SSL_METHOD *) TLSv1_2_client_method ();
  /* 创建SSL会话环境 */
  ctx = SSL_CTX_new (meth);                    
  CHK_NULL(ctx);
  
  /*验证与否,是否要验证对方*/
  SSL_CTX_set_verify(ctx,SSL_VERIFY_PEER,NULL);   
  /*若验证对方,则放置CA证书*/
  SSL_CTX_load_verify_locations(ctx,CACERT,NULL); 

  /*加载自己的证书*/
  if (SSL_CTX_use_certificate_file(ctx, CERTF, SSL_FILETYPE_PEM) <= 0) 
  {
    ERR_print_errors_fp(stderr);
    exit(-2);
  }
  /*加载自己的私钥,以用于签名*/
  if (SSL_CTX_use_PrivateKey_file(ctx, KEYF, SSL_FILETYPE_PEM) <= 0) 
  {
    ERR_print_errors_fp(stderr);
    exit(-3);
  }
  /*调用了以上两个函数后,检验一下自己的证书与私钥是否配对*/
  if (!SSL_CTX_check_private_key(ctx)) 
  {
    printf("Private key does not match the certificate public key\n");
    exit(-4);
  } 

  /*构建随机数生成机制,WIN32平台必需*/
  srand( (unsigned)time( NULL ) );
  for( int i = 0;   i < 100;i++ )
        seed_int[i] = rand();
  RAND_seed(seed_int, sizeof(seed_int));

  /* 指定加密器类型 */
  SSL_CTX_set_cipher_list (ctx, "SHA256");
  SSL_CTX_set_mode (ctx, SSL_MODE_AUTO_RETRY);


  /*以下是正常的TCP socket建立过程 .............................. */
  printf("Begin tcp socket...\n");
  sd = socket (AF_INET, SOCK_STREAM, 0);       
  CHK_ERR(sd, "socket");

  memset (&sa, 0, sizeof(sa));
  sa.sin_family      = AF_INET;
  sa.sin_addr.s_addr = inet_addr (SERVER_ADDR);   /* Server IP */
  sa.sin_port        = htons     (PORT);          /* Server Port number */

  err = connect(sd, (struct sockaddr*) &sa, sizeof(sa)); 
  CHK_ERR(err, "connect");

  /* TCP 链接已建立.开始 SSL 握手过程.......................... */
  printf("Begin SSL negotiation \n");

  /*申请一个SSL套接字*/
  ssl = SSL_new (ctx);                        
  CHK_NULL(ssl);

  /*绑定读写套接字*/
  SSL_set_fd (ssl, sd);
  err = SSL_connect (ssl);
  printf("链接已建立.开始 SSL 握手过程 \n");
  CHK_SSL(err);

  /*打印所有加密算法的信息(可选)*/
  printf ("SSL connection using %s\n", SSL_get_cipher (ssl));

  /*得到服务端的证书并打印些信息(可选) */
  server_cert = SSL_get_peer_certificate (ssl);      
  CHK_NULL(server_cert);
  printf ("Server certificate:\n");

  str = X509_NAME_oneline (X509_get_subject_name (server_cert),0,0);
  CHK_NULL(str);
  printf ("/t subject: %s\n", str);
  free (str);

  str = X509_NAME_oneline (X509_get_issuer_name  (server_cert),0,0);
  CHK_NULL(str);
  printf ("/t issuer: %s\n", str);
  free (str);

  X509_free (server_cert);  /*如不再需要,需将证书释放 */

  /* 数据交换开始,用SSL_write,SSL_read代替write,read */
  printf("Begin SSL data exchange\n");

  err = SSL_write (ssl, "Hello World!", strlen("Hello World!")); 
  CHK_SSL(err);

  err = SSL_read (ssl, buf1, sizeof(buf1) - 1); 
  CHK_SSL(err);

  buf1[err] = '\0';
  printf ("Got %d chars:'%s'\n", err, buf1);
  SSL_shutdown (ssl);  /* send SSL/TLS close_notify */

  /* 收尾工作 */
  shutdown (sd,2);
  SSL_free (ssl);
  SSL_CTX_free (ctx);

  return 0;
}

服务端代码

#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <errno.h>
#include <sys/types.h>


#include <sys/socket.h>
#include <arpa/inet.h>
#include "openssl/rsa.h"      
#include "openssl/crypto.h"
#include "openssl/x509.h"
#include "openssl/pem.h"
#include "openssl/ssl.h"
#include "openssl/err.h"

/*所有需要的参数信息都在此处以#define的形式提供*/
#define CERTF   "../key/server.crt" /*服务端的证书(需经CA签名)*/
#define KEYF   "../key/server.key"  /*服务端的私钥(建议加密存储)*/
#define CACERT "../key/ca.crt" /*CA 的证书*/


#define PORT   20001   /*准备绑定的端口*/

#define CHK_NULL(x) if ((x)==NULL) exit (1)
#define CHK_ERR(err,s) if ((err)==-1) { perror(s); exit(1); }
#define CHK_SSL(err) if ((err)==-1) { ERR_print_errors_fp(stderr); exit(2); }

int main ()
{
  int err;
  int listen_sd;
  int sd;
  struct sockaddr_in sa_serv;
  struct sockaddr_in sa_cli;
  int client_len;
  SSL_CTX* ctx;
  SSL*     ssl;
  X509*    client_cert;
  char*    str;
  char     buf [4096];
  SSL_METHOD *meth;

  /* 初始化OpenSSL */
  SSL_library_init();
  /*加载算法库 */
  OpenSSL_add_ssl_algorithms();
  /*加载错误处理信息 */
  SSL_load_error_strings ();
  /*采用什么协议(SSLv2/SSLv3/TLSv1)在此指定*/
  meth = (SSL_METHOD *) TLSv1_2_server_method ();
  /* 创建SSL会话环境 */
  ctx = SSL_CTX_new (meth);                    
  CHK_NULL(ctx);

  SSL_CTX_set_verify(ctx,SSL_VERIFY_PEER,NULL);   /*验证与否*/
  SSL_CTX_load_verify_locations(ctx,CACERT,NULL); /*若验证,则放置CA证书*/

  if (SSL_CTX_use_certificate_file(ctx, CERTF, SSL_FILETYPE_PEM) <= 0) {
    ERR_print_errors_fp(stderr);
    exit(3);
  }
  if (SSL_CTX_use_PrivateKey_file(ctx, KEYF, SSL_FILETYPE_PEM) <= 0) {
    ERR_print_errors_fp(stderr);
    exit(4);
  }
  if (!SSL_CTX_check_private_key(ctx)) {
    printf("Private key does not match the certificate public key\n");
    exit(5);
  }

   /* 指定加密器类型 */
  SSL_CTX_set_cipher_list (ctx, "SHA256");
  SSL_CTX_set_mode (ctx, SSL_MODE_AUTO_RETRY);


  /*开始正常的TCP socket过程.................................*/
  printf("Begin TCP socket.../n");

  listen_sd = socket (AF_INET, SOCK_STREAM, 0);  
  CHK_ERR(listen_sd, "socket");

  memset (&sa_serv, '\0', sizeof(sa_serv));
  sa_serv.sin_family      = AF_INET;
  sa_serv.sin_addr.s_addr = inet_addr("0");
  sa_serv.sin_port        = htons (PORT);         

    int opt = 1;
    if(setsockopt(listen_sd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0)
    {
        fprintf(stderr,"[tskIpRev]: setsockopt(SO_REUSEADDR) error\n");
        return 0;
    }
  err = bind(listen_sd, (struct sockaddr*) &sa_serv,

  sizeof (sa_serv));

  CHK_ERR(err, "bind");

  /*接受TCP链接*/
  err = listen (listen_sd, 5);                   
  CHK_ERR(err, "listen");

  client_len = sizeof(sa_cli);
  sd = accept (listen_sd, (struct sockaddr*) &sa_cli, &client_len);
  CHK_ERR(sd, "accept");

  /*TCP连接已建立,进行服务端的SSL过程. */
  printf("Begin server side SSL\n");

  ssl = SSL_new (ctx);                          
  CHK_NULL(ssl);
  SSL_set_fd (ssl, sd);
  err = SSL_accept (ssl);
  printf("SSL_accept finished\n");
  CHK_SSL(err);

  /*打印所有加密算法的信息(可选)*/
  printf ("SSL connection using %s\n", SSL_get_cipher (ssl));

  /*得到服务端的证书并打印些信息(可选) */
  client_cert = SSL_get_peer_certificate (ssl);
  if (client_cert != NULL) {
    printf ("Client certificate:\n");

    str = X509_NAME_oneline (X509_get_subject_name (client_cert), 0, 0);
    CHK_NULL(str);
    printf ("/t subject: %s\n", str);
    free (str);

    str = X509_NAME_oneline (X509_get_issuer_name  (client_cert), 0, 0);
    CHK_NULL(str);
    printf ("/t issuer: %s\n", str);
    free (str);

    X509_free (client_cert);/*如不再需要,需将证书释放 */
  }
  else
    printf ("Client does not have certificate.\n");

  /* 数据交换开始,用SSL_write,SSL_read代替write,read */
  err = SSL_read (ssl, buf, sizeof(buf) - 1);                  
  CHK_SSL(err);
  buf[err] = '\0';
  printf ("Got %d chars:'%s'\n", err, buf);

  err = SSL_write (ssl, "I hear you.", strlen("I hear you.")); 
  CHK_SSL(err);

  /* 收尾工作*/
  shutdown (sd,2);
  SSL_free (ssl);
  SSL_CTX_free (ctx);

  return 0;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

openssl engine在tls中的应用 的相关文章

随机推荐

  • GIS项目启动时手动添加依赖

    gis项目在idea下启动前需要手动安装的包 mvn install install file DgroupId org geotools jdbc DartifactId gt jdbc oracle Dversion 18 2 Dpac
  • centOs 6.5 ssh配置无密码登入

    1 安装ssh 若没安装的话 sudo apt get install ssh 2 配置为可以免密码登陆本机 2 1查看在master用户下是否存在 ssh文件夹 ssh前面有 的是隐藏文件夹 输入命令ls a home master 我的
  • omnifocus3透视 任务分类实例详解

    目录 1任务分类 2标签 任务细化的一种属性 3任务分类实例详解 4透视 上大学之前 好巧 今天9号 高考结束 我们每周的任务数量很明确 本学期几本书的学习 复习 但是步入社会之后 参与项目数量逐渐增加 需要沟通的人也越来越复杂 每日任务不
  • 认识 ESP-IDF-v4.3+工程结构(ESP32-C3应用调整示例)

    ESP32 C3 学习测试到今天 一直在使用 ESP IDF 的框架 但是还从来没有注意过工程结构 遇到复杂一点的项目 工程结构就显得太乱了 本文就来了解下 ESP IDF 工程结构 目录 前言 一 ESP IDF工程基本框架 1 1 工程
  • 数学是成就卓越开发人员的必备技能

    本文转载至 http blog jobbole com 444 编者按 原文作者Alan Skorkin是一名软件开发人员 他在博客中分享对软件开发相关的心得 其中有很多优秀的文章 本文就是其中一篇 作者认为 成为优秀的开发人员 可以没有数
  • javaEE企业级框架ssm知识点整合【思维导图】

    ssm Spring SpringMVC Mybatis 框架是轻量级javaEE应用开发最受欢迎的一种组合框架之一 使用这种框架的项目使JavaEE架构具有高度可维护性和可扩展性 同时极大地提高了项目的开发效率 降低了开发和维护的成本 而
  • webkit和webkit2的区别

    转自 http blog csdn net shunzi 1984 article details 6196483 原文地址 https trac webkit org wiki WebKit2 webkit2为了在API层支持多进程改变了
  • Linux “/“ 分区扩容

    前言 扩容是一项很简单的工作 但是有时候因为长时间没有操作过扩容 指令会比较生疏 因此写一篇扩容的文档 方便在再次失忆的情况下能快速回忆起操作流程 逻辑卷扩容的流程 创建PV gt 扩容VG gt 扩容LV 以下是扩容的详细流程 1 查看当
  • 人工智能梯度下降的优化器SGD、Momentum、AdaGrad、Adam的数学原理以及无框架实现

    系列文章目录 人工智能 梯度下降的原理和手写实现 文章目录 系列文章目录 前言 一 梯度下降优化器是什么 二 SGD优化方法 1 SGD是什么 2 SGD的数学原理 3 SGD的实现 4 SGD的缺陷 三 Momentum优化方法 1 Mo
  • 为什么公司规定所有接口都必须加上分布式锁,你知道吗?

    上一篇文章我们聊了聊Redisson这个开源框架对Redis分布式锁的实现原理 如果有不了解的兄弟可以看一下 都2022年了 出去面试连分布式锁的源码你都不会画 今天就给大家聊一个有意思的话题 每秒上千订单场景下 如何对分布式锁的并发能力进
  • 如何通过代码获取framedebugger里面的drawcall信息

    最近想做个性能工具 用来分析当前drawcall里面的具体调用 不知道unity有没有获取数据的具体接口 不过framedebugger里面的确有相关数据 这是方案一 另外一个方案是hook 理论上应该参考下renderdoc的实现应该就可
  • 使用scrapy爬取数据

    安装scrapy 使用清华镜像 打开PyCharm 安装scrapy框架 pip install i https pypi tuna tsinghua edu cn simple scrapy 新建一个名为python scrapy的项目
  • 深入浅出图解CNN-卷积神经网络

    首先 介绍一下卷积的来源 它经常用在信号处理中 用于计算信号的延迟累积 假设一个信号发生器每个时刻t产生一个信号xt 其信息的衰减率为wk 即在k 1个时间步长后 信息为原来的wk 倍 假设w1 1 w2 1 2 w3 1 4 时刻t收到的
  • linux查找目录下的所有文件中是否含有某个字符串

    Linux查找文件内容的常用命令方法 从文件内容查找匹配指定字符串的行 grep 被查找的字符串 文件名 例子 在当前目录里第一级文件夹中寻找包含指定字符串的 in文件 grep thermcontact in 从文件内容查找与正则表达式匹
  • [论文阅读]《Database Maanagement Systems》-第六章

    第六章 QUERY BY EXAMPLE QBE 查询示例 QBE P201 P216 Example is always more efficacious than precept 身教胜于言教 榜样总是比教训更有效 precept 规则
  • openGL之API学习(一七三)glsl如何设置版本version和兼容性

    version 120 version 120 core version 120 compatibility version 300 es GLSL ES 提供了一个 version 指令来指定着色器使用的GLSL ES的版本 如果不指定G
  • c++ 日志输出库 spdlog 简介

    spdlog是一个开源的 快速的 仅有头文件的C 11 日志库 它提供了向流 标准输出 文件 系统日志 调试器等目标输出日志的能力 它支持的平台包括Windows Linux Mac Android iOS 官方参考 https githu
  • 后缀自动机(SAM)——黑盒使用方案

    首先讲下后缀自动机吧 会写一下部分必要的原理 其他的原理不做解释 代码未讲解的部分希望能当做黑盒来使用 既不了解具体原理但知道其性质以及如何使用 我实在是佩服发明出AC自动机 回文自动机 后缀自动机这人 前置知识 AC自动机中的Fail树
  • 如何使用Chrome浏览器模拟弱网情况

    点击谷歌浏览器图标 打开浏览器后 按下F12键 弹出开发者工具窗口 刷新网页 页面的加载速度为597ms 在开发者工具中 点击Online 在弹出的菜单中点击Slow 3G 慢速3G网络 重新加载网站 发现页面的加载速度变慢了 变成6 5s
  • openssl engine在tls中的应用

    openssl engine的实现和原理在上一篇文章 https blog csdn net liu942947766 article details 128837041 spm 1001 2014 3001 5502 openssl en