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


相关文章
|
6天前
|
Linux 虚拟化 Docker
Windows12安装Docker
Windows12安装Docker
31 2
|
1月前
|
数据安全/隐私保护 虚拟化 Windows
如何在 VM 虚拟机中安装 Windows Server 2012 操作系统保姆级教程(附链接)
如何在 VM 虚拟机中安装 Windows Server 2012 操作系统保姆级教程(附链接)
77 0
|
1月前
|
数据安全/隐私保护 虚拟化 Windows
如何在 VM 虚拟机中安装 Windows Server 2003 操作系统保姆级教程(附链接)
如何在 VM 虚拟机中安装 Windows Server 2003 操作系统保姆级教程(附链接)
57 0
|
1月前
|
数据安全/隐私保护 虚拟化 Windows
如何在 VM 虚拟机中安装 Windows 7 操作系统保姆级教程(附链接)
如何在 VM 虚拟机中安装 Windows 7 操作系统保姆级教程(附链接)
92 0
如何在 VM 虚拟机中安装 Windows 7 操作系统保姆级教程(附链接)
|
1月前
|
数据安全/隐私保护 虚拟化 Windows
如何在 VM 虚拟机中安装 Windows XP 操作系统保姆级教程(附链接)
如何在 VM 虚拟机中安装 Windows XP 操作系统保姆级教程(附链接)
120 0
|
1月前
|
数据可视化 Python Windows
使用 Python 代码在 windows 控制台打印正弦三角函数
使用 Python 代码在 windows 控制台打印正弦三角函数
18 0
|
23天前
|
安全 Windows
安装MyEclipse遇到错误提示 Failed to find a Main Class in “C:Windows\Temp\“时的解决方案
安装MyEclipse遇到错误提示 Failed to find a Main Class in “C:Windows\Temp\“时的解决方案
24 1
|
1天前
|
SQL 数据管理 关系型数据库
如何在 Windows 上安装 SQL Server,保姆级教程来了!
在Windows上安装SQL Server的详细步骤包括:从官方下载安装程序(如Developer版),选择自定义安装,指定安装位置(非C盘),接受许可条款,选中Microsoft更新,忽略警告,取消“适用于SQL Server的Azure”选项,仅勾选必要功能(不包括Analysis Services)并更改实例目录至非C盘,选择默认实例和Windows身份验证模式,添加当前用户,最后点击安装并等待完成。安装成功后关闭窗口。后续文章将介绍SSMS的安装。
4 0
|
2天前
|
5G Python
Windows11搭建Python环境(Anaconda安装与使用)
Windows11搭建Python环境(Anaconda安装与使用)
13 0
|
2天前
|
关系型数据库 MySQL Windows
windows安装MySQL5.7教程
windows安装MySQL5.7教程
8 0