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.服务器端代码要求输入密码,请使用生成秘钥时的密码


相关文章
|
1月前
|
数据安全/隐私保护 Windows
安装 Windows Server 2019
安装 Windows Server 2019
|
1月前
|
Windows
安装 Windows Server 2003
安装 Windows Server 2003
|
1月前
|
NoSQL Shell MongoDB
Windows 平台安装 MongoDB
10月更文挑战第10天
39 0
Windows 平台安装 MongoDB
|
1月前
|
Windows Python
Windows安装dlib,遇到问题汇总解决
Windows安装dlib,遇到问题汇总解决
31 4
|
1月前
|
Oracle 关系型数据库 MySQL
Mysql(1)—简介及Windows环境下载安装
MySQL 是一个流行的关系型数据库管理系统(RDBMS),基于 SQL 进行操作。它由瑞典 MySQL AB 公司开发,后被 Sun Microsystems 收购,现为 Oracle 产品。MySQL 是最广泛使用的开源数据库之一,适用于 Web 应用程序、数据仓库和企业应用。
53 2
|
22天前
|
Linux 网络安全 虚拟化
适用于Linux的Windows子系统(WSL1)的安装与使用记录
并放到启动文件夹,就可以开机自动启动了。
27 0
|
1月前
|
Windows
安装Windows XP系统
安装Windows XP系统
|
Windows Perl C++
如何在Windows下编译OpenSSL?
   如何在Windows下编译OpenSSL? yanqing-wang (Intel) 于 星期日, 22/12/2013 - 23:48 提交 OpenSSL是一个开源的第三方库,它实现了SSL(Secure SocketLayer)和TLS(Transport Layer Security)协议,被广泛企业应用所采用。
1466 0
|
3天前
|
监控 安全 网络安全
Windows Server管理:配置与管理技巧
Windows Server管理:配置与管理技巧
19 3
|
7天前
|
存储 安全 网络安全
Windows Server 本地安全策略
由于广泛使用及历史上存在的漏洞,Windows服务器成为黑客和恶意行为者的主要攻击目标。这些系统通常存储敏感数据并支持关键服务,因此组织需优先缓解风险,保障业务的完整性和连续性。常见的威胁包括勒索软件、拒绝服务攻击、内部威胁、恶意软件感染等。本地安全策略是Windows操作系统中用于管理计算机本地安全性设置的工具,主要包括用户账户策略、安全选项、安全设置等。实施强大的安全措施,如定期补丁更新、网络分段、入侵检测系统、数据加密等,对于加固Windows服务器至关重要。