windows openssl安装和基本使用(代码演示)

简介: 本文主要讲到了openssl的基本使用方法,开发环境为windows,开发工具为VS2019.本文主要是说明openssl如何使用,不介绍任何理论知识,如果有不懂的,请自行百度。个人建议下一个everything查询工具,真的很好用,比window自带的查询快了很多,可以查询自己想要的文件

概述

本文主要讲到了openssl的基本使用方法,开发环境为windows,开发工具为VS2019.本文主要是说明openssl如何使用,不介绍任何理论知识,如果有不懂的,请自行百度。个人建议下一个everything查询工具,真的很好用,比window自带的查询快了很多,可以查询自己想要的文件


OPENSSL安装

安装过程网上有很多,OPENSSL安装,注意你安装的OPENSSL的版本以及位数(32位或者64位),假如我安装的是64位的openssl,安装目录为D:\Program Files\OpenSSL-Win64,你可以自行选择你的安装目录,安装完成后,查看安装的openssl版本,使用控制台输入openssl version即可

90bf5aca557a553b10e384817bc4a590_bbb47abc79db4cd89e83194a3c7cf04d.png

秘钥key和公钥的生成

在控制命令行中输入以下命令:

openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -sha256 -days 365

网上有很多生成秘钥和公钥的文章,不过都没成功,最后在stackoverflow找到了可以用的方法,原文地址为:openssl秘钥和公钥的生成,以下是截图

7cdbeaa91ca44b9bb7575722ee974820_c299e4e01bc2470e9c63a795bbda5f01.png

Enter PEM pass phrase:提示输入pem文件的密码,注意,后面要用到这个密码,可以使用自己常用的密码,输入后会再次确认密码,然后就是一些基本信息,可以默认为空。截图如下,基本上这时候就得到了秘钥key.pem和公钥cert.pem,后面要用到这2个文件。,生成的位置为当前目录,比如我的就是在C:\Users\86138,即控制台的显示目录。

4dcaa86a0636316fecb18147517aef04_98b7b9a2ead441e3a07f48d52f440942.png


项目设置

使用VS创建一个控制台项目,创建一个客户端和服务器项目,由于我下载的是64位,openssl3.0版本。因此我项目也是64位的。

c154fe99c7d1bafec2e9e37f0864c736_00cfbb133c824eec9e10661ae4571096.png

项目的配置,服务器端和客户端都是相同配置,这里我就只说一个即可,主要是设置openssl的lib和头文件的路径,这和使用任外部库都是一样的。截图如下,注意我的openssl安装位置为D:\Program Files\OpenSSL-Win64,请选择你安装位置即可。

f3e490df14ccc376eba6da341777691e_953a368415a64d399f91eefd9adffb0b.png

预处理器里添加2个定义:CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;

286a42f9a6233ebcdc258a9cb12dcc41_472c27db7999437faac8c5c07923e703.png

附加依赖项:libssl.lib;openssl.lib;libcrypto.lib;liblegacy.lib;

d014a7d7b55f0f75974835bcb4afac52_56651b9ae7cc4af9a7fb9ea6b0ccc9de.png

最后将前面生成的cert.pem和key.pem放到exe目录下,为什么放到这个目录,是因为下面的代码用到的这2个文件是当前目录,不管怎么样,只要能找到这2个文件即可。

37d75ce6ddfe3b1d94253129cc1d1061_94351b622c21467d97119fe6de3a8209.png

配置很简单,就上面几步,基本上就可以了。


代码部分

客户端代码

#include <stdio.h>
#include <errno.h>
#include <malloc.h>
#include <string.h>
# include <winsock2.h>
#include <ws2tcpip.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#define FAIL    -1
#pragma comment(lib, "Ws2_32.lib")
//Added the LoadCertificates how in the server-side makes.    
int OpenConnection(const char* hostname, int port)
{
  SOCKET sd;
  struct hostent* host;
  struct sockaddr_in addr;
  WORD wVersionRequested;
  WSADATA wsaData;
  int err;
  /* Use the MAKEWORD(lowbyte, highbyte) macro declared in Windef.h */
  wVersionRequested = MAKEWORD(2, 2);
  err = WSAStartup(wVersionRequested, &wsaData);
  if (err != 0)
  {
  /* Tell the user that we could not find a usable */
  /* Winsock DLL.                                  */
  printf("WSAStartup failed with error: %d\n", err);
  return 1;
  }
  sd = socket(PF_INET, SOCK_STREAM, 0);
  /bzero(&addr, sizeof(addr));
  addr.sin_family = AF_INET;
  addr.sin_port = htons(port);
  addr.sin_addr.s_addr = inet_addr(hostname);
  int ret = connect(sd, (struct sockaddr*)&addr, sizeof(addr));
  if ( ret != 0)
  {
  //close(sd);
  perror(hostname);
  abort();
  }
  return sd;
}
SSL_CTX* InitCTX(void)
{
  //SSL_METHOD* method;
  SSL_CTX* ctx;
  //OpenSSL_add_all_algorithms();  /* Load cryptos, et.al. */
  SSL_load_error_strings();   /* Bring in and register error messages */
  SSL_METHOD const* meth = SSLv23_client_method();  /* Create new client-method instance */
  //method = TLSv1_method();
  ctx = SSL_CTX_new(meth);   /* Create new context */
  if (ctx == NULL)
  {
  ERR_print_errors_fp(stderr);
  printf("Eroor: %s\n", stderr);
  abort();
  }
  return ctx;
}
void ShowCerts(SSL* ssl)
{
  X509* cert;
  char* line1, * line2;
  cert = SSL_get_peer_certificate(ssl); /* get the server's certificate */
  if (cert != NULL)
  {
  printf("Server certificates:\n");
  line1 = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
  printf("Subject: %s\n", line1);
  //free(line);       /* free the malloc'ed string */
  line2 = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
  printf("Issuer: %s\n", line2);
  //free(line);       /* free the malloc'ed string */
  //X509_free(cert);     /* free the malloc'ed certificate copy */
  }
  else
  printf("No certificates.\n");
}
int main(int count, char* strings[])
{
  SSL_CTX* ctx;
  SOCKET server;
  SSL* ssl;
  char buf[1024];
  int bytes;
  char const *hostname, *portnum;
  SSL_library_init();
  hostname = "127.0.0.1";
  portnum = "1030";
  ctx = InitCTX();
  server = OpenConnection(hostname, atoi(portnum));
  ssl = SSL_new(ctx);      /* create new SSL connection state */
  //SSL_set_fd(ssl, server);    /* attach the socket descriptor */
  BIO* bio = BIO_new_socket(server, BIO_NOCLOSE);
  SSL_set_bio(ssl, bio, bio);
  SSL_set_connect_state(ssl);
  if (SSL_connect(ssl) == FAIL)   /* perform the connection */
  {
  printf("Eroor: %s\n", stderr);
  ERR_print_errors_fp(stderr);
  }
  else
  {
  printf("Connected with %s encryption\n", SSL_get_cipher(ssl));
  ShowCerts(ssl);  /* get any certs */
  while (1)
  {
    char p[100];
    printf("please input sned msg: ");
    gets(p);
    printf("strlen:%d,%s\n", strlen(p), p);
    SSL_write(ssl, p, strlen(p));   /* encrypt & send message */
    bytes = SSL_read(ssl, buf, sizeof(buf)); /* get reply & decrypt */
    if (bytes >= 0)
    {
    buf[bytes] = '\0';
    printf("Received: \"%s\"\n", buf);
    }
    else 
    {
    SSL_ERROR_WANT_READ;
    int error = SSL_get_error(ssl, bytes);
    printf("error:%d\n", error);
    break;
    }
  }
  SSL_shutdown(ssl);
  SSL_free(ssl);        /* release connection state */
  }
  SSL_CTX_free(ctx);        /* release context */
  getchar();
  return 0;
}

服务器端代码

#include <errno.h>
#include <malloc.h>
#include <string.h>
# include <winsock2.h>
# include <ws2tcpip.h>
#include "openssl/ssl.h"
#include "openssl/err.h"
#ifdef  __cplusplus
extern "C" {
#endif
#include "openssl/applink.c"
#ifdef  __cplusplus
}
#endif
#define FAIL    -1
#pragma comment(lib, "Ws2_32.lib")
int OpenListener(WORD port)
{
  SOCKET  m_socket;
  WORD wVersionRequested;
  WSADATA wsaData;
  int err;
  /* Use the MAKEWORD(lowbyte, highbyte) macro declared in Windef.h */
  wVersionRequested = MAKEWORD(2, 2);
  err = WSAStartup(wVersionRequested, &wsaData);
  if (err != 0) {
  /* Tell the user that we could not find a usable */
  /* Winsock DLL.                                  */
  printf("WSAStartup failed with error: %d\n", err);
  return 1;
  }
  m_socket = socket(AF_INET, SOCK_STREAM, 0);
  if (m_socket == INVALID_SOCKET)
  {
  printf("Error at socket(): %ld\n", WSAGetLastError());
  WSACleanup();
  return 0;
  }
  struct sockaddr_in sain;
  //bzero(&addr, sizeof(addr));
  sain.sin_family = AF_INET;
  sain.sin_port = htons(port);
  sain.sin_addr.s_addr = inet_addr("127.0.0.1");
  if (bind(m_socket, (struct sockaddr*)&sain, sizeof(struct sockaddr_in)) == SOCKET_ERROR)
  {
  perror("can't bind port");
  //abort();
  }
  if (listen(m_socket, 10) != 0)
  {
  perror("Can't configure listening port");
  //abort();
  }
  return m_socket;
}
SSL_CTX* InitServerCTX(void)
{
  SSL_CTX* ctx = NULL;
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
  const SSL_METHOD* method;
#else
  SSL_METHOD* method;
#endif
  SSL_library_init();
  //OpenSSL_add_all_algorithms();  /* load & register all cryptos, etc. */
  SSL_load_error_strings();   /* load all error messages */
  //method = SSLv23_method(); /* create new server-method instance */
  method = SSLv23_server_method();
  ctx = SSL_CTX_new(method);   /* create new context from method */
  if (ctx == NULL)
  {
  ERR_print_errors_fp(stderr);
  abort();
  }
  return ctx;
}
void LoadCertificates(SSL_CTX* ctx, char* CertFile, char* KeyFile)
{
  //New lines
  int ret = SSL_CTX_load_verify_locations(ctx, CertFile, KeyFile);
  if (ret != 1)
  ERR_print_errors_fp(stderr);
  if (SSL_CTX_set_default_verify_paths(ctx) != 1)
  ERR_print_errors_fp(stderr);
  //End new lines
  /* set the local certificate from CertFile */
  if (SSL_CTX_use_certificate_file(ctx, CertFile, SSL_FILETYPE_PEM) <= 0)
  {
  ERR_print_errors_fp(stderr);
  //abort();
  }
  /* set the private key from KeyFile (may be the same as CertFile) */
  if (SSL_CTX_use_PrivateKey_file(ctx, KeyFile, SSL_FILETYPE_PEM) <= 0)
  {
  ERR_print_errors_fp(stderr);
  abort();
  }
  /* verify private key */
  if (!SSL_CTX_check_private_key(ctx))
  {
  fprintf(stderr, "Private key does not match the public certificate\n");
  abort();
  }
  printf("LoadCertificates success\n");
}
void ShowCerts(SSL* ssl)
{
  X509* cert;
  char* line;
  cert = SSL_get_peer_certificate(ssl); /* Get certificates (if available) */
  if (cert != NULL)
  {
  printf("Server certificates:\n");
  line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
  printf("Subject: %s\n", line);
  free(line);
  line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
  printf("Issuer: %s\n", line);
  free(line);
  X509_free(cert);
  }
  else
  printf("No certificates.\n");
}
void Servlet(SSL* ssl, SOCKET client) /* Serve the connection -- threadable */
{
  char buf[1024];
  char reply[1024];
  int sd, bytes;
  const char* HTMLecho = "hello client";
  ShowCerts(ssl);        /* get any certificates */
  int ret = SSL_accept(ssl);  
  while (1)
  {
  //bytes = recv(client, buf, sizeof(buf), 0);
  bytes = SSL_read(ssl, buf, sizeof(buf)); 
  if (bytes > 0)
  {
    buf[bytes] = '\0';
    printf("Client msg: %s\n", buf);
    sprintf(reply, HTMLecho, buf);   /* construct reply */
    SSL_write(ssl, reply, strlen(reply)); /* send reply */
  }
  else //其他情况
  {
    //printf("read byte < 0\n");
  }
  }
  SSL_shutdown(ssl);
  SSL_free(ssl);
}
int main(int count, char* strings[])
{
  SSL_CTX* ctx;
  SOCKET server;
  char* portnum;
  server = OpenListener(1030);    /* create server socket */
  SSL_library_init();
  portnum = strings[1];
  ctx = InitServerCTX();        /* initialize SSL */
  LoadCertificates(ctx, (char *)"cert.pem", (char *)"key.pem");  /* load certs */
  while (1)
  {
  struct sockaddr_in addr;
  socklen_t len = sizeof(addr);
  SSL* ssl;
  SOCKET client = accept(server, (struct sockaddr*)&addr, &len);  /* accept connection   as usual */
  socklen_t len1;
  struct sockaddr_storage addr1;
  //add1.sin_family = AF_INET;
  char ipstr[INET6_ADDRSTRLEN];
  int port;
  len1 = sizeof addr;
  int r;
  r = getpeername(client, (struct sockaddr*)&addr1, &len1);
  // deal with both IPv4 and IPv6:
  if (addr1.ss_family == AF_INET)
  {
    struct sockaddr_in* s = (struct sockaddr_in*)&addr1;
    port = ntohs(s->sin_port);
    inet_ntop(AF_INET, &s->sin_addr, ipstr, sizeof ipstr);
  }
  else
  { // AF_INET6
    struct sockaddr_in6* s = (struct sockaddr_in6*)&addr1;
    port = ntohs(s->sin6_port);
    inet_ntop(AF_INET6, &s->sin6_addr, ipstr, sizeof ipstr);
  }
  printf("Peer IP address: %s,port:%d\n", ipstr,port);
  ssl = SSL_new(ctx);              /* get new SSL state with context */
  //SSL_set_fd(ssl, client);      /* set connection socket to SSL state */
  BIO* bio = BIO_new_socket(client, BIO_NOCLOSE);
  SSL_set_bio(ssl, bio, bio);
  Servlet(ssl, client);         /* service connection */
  }
  SSL_CTX_free(ctx);         /* release context */
}

总结

可能遇到的问题

1.要确保代码中applink.c文件的存在,否则服务器端代码会提示Unlink的错误

2.服务器端代码要求输入密码,请使用生成秘钥时的密码


相关文章
|
9天前
|
存储 Cloud Native Java
Windows下Minio的安装以及基本使用
MinIO 是一个开源的云原生分布式对象存储系统,兼容亚马逊S3接口,适合存储大容量非结构化数据。本文介绍Windows下MinIO的安装与基本使用:通过以上步骤,您可以在Windows环境中成功安装并使用MinIO。
70 17
|
26天前
|
关系型数据库 MySQL 数据库
【MySQL基础篇】MySQL概述、Windows下载MySQL8.0超详细图文安装教程
在这一章节,主要介绍两个部分,数据库相关概念及MySQL数据库的介绍、下载、安装、启动及连接。接着,详细描述了MySQL 8.0的版本选择与下载,推荐使用社区版(免费)。安装过程包括自定义安装路径、配置环境变量、启动和停止服务、以及客户端连接测试。此外,还提供了在同一台电脑上安装多个MySQL版本的方法及卸载步骤。最后,解释了关系型数据库(RDBMS)的特点,即基于二维表存储数据,使用SQL语言进行操作,格式统一且便于维护。通过具体的结构图展示了MySQL的数据模型,说明了数据库服务器、数据库、表和记录之间的层次关系。
【MySQL基础篇】MySQL概述、Windows下载MySQL8.0超详细图文安装教程
|
22天前
|
安全 关系型数据库 MySQL
Windows Server 安装 MySQL 8.0 详细指南
安装 MySQL 需要谨慎,特别注意安全配置和权限管理。根据实际业务需求调整配置,确保数据库的性能和安全。
113 9
|
1月前
|
机器学习/深度学习 并行计算 异构计算
WINDOWS安装eiseg遇到的问题和解决方法
通过本文的详细步骤和问题解决方法,希望能帮助你顺利在 Windows 系统上安装和运行 EISeg。
101 2
|
2月前
|
网络安全 Windows
Windows server 2012R2系统安装远程桌面服务后无法多用户同时登录是什么原因?
【11月更文挑战第15天】本文介绍了在Windows Server 2012 R2中遇到的多用户无法同时登录远程桌面的问题及其解决方法,包括许可模式限制、组策略配置问题、远程桌面服务配置错误以及网络和防火墙问题四个方面的原因分析及对应的解决方案。
147 4
|
2月前
|
NoSQL Linux PHP
如何在不同操作系统上安装 Redis 服务器,包括 Linux 和 Windows 的具体步骤
本文介绍了如何在不同操作系统上安装 Redis 服务器,包括 Linux 和 Windows 的具体步骤。接着,对比了两种常用的 PHP Redis 客户端扩展:PhpRedis 和 Predis,详细说明了它们的安装方法及优缺点。最后,提供了使用 PhpRedis 和 Predis 在 PHP 中连接 Redis 服务器及进行字符串、列表、集合和哈希等数据类型的基本操作示例。
94 4
|
3月前
|
Linux 网络安全 虚拟化
适用于Linux的Windows子系统(WSL1)的安装与使用记录
并放到启动文件夹,就可以开机自动启动了。
207 0
|
2月前
|
监控 安全 网络安全
使用EventLog Analyzer日志分析工具监测 Windows Server 安全威胁
Windows服务器面临多重威胁,包括勒索软件、DoS攻击、内部威胁、恶意软件感染、网络钓鱼、暴力破解、漏洞利用、Web应用攻击及配置错误等。这些威胁严重威胁服务器安全与业务连续性。EventLog Analyzer通过日志管理和威胁分析,有效检测并应对上述威胁,提升服务器安全性,确保服务稳定运行。
|
2月前
|
监控 安全 网络安全
Windows Server管理:配置与管理技巧
Windows Server管理:配置与管理技巧
121 3

热门文章

最新文章