0


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

概述

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

OPENSSL安装

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

秘钥key和公钥的生成

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

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

网上有很多生成秘钥和公钥的文章,不过都没成功,最后在stackoverflow找到了可以用的方法,原文地址为:openssl秘钥和公钥的生成,以下是截图
在这里插入图片描述
Enter PEM pass phrase:提示输入pem文件的密码,注意,后面要用到这个密码,可以使用自己常用的密码,输入后会再次确认密码,然后就是一些基本信息,可以默认为空。截图如下,基本上这时候就得到了秘钥key.pem和公钥cert.pem,后面要用到这2个文件。,生成的位置为当前目录,比如我的就是在C:\Users\86138,即控制台的显示目录
在这里插入图片描述

项目设置

使用VS创建一个控制台项目,创建一个客户端和服务器项目,由于我下载的是64位,openssl3.0版本。因此我项目也是64位的。
在这里插入图片描述
项目的配置,服务器端和客户端都是相同配置,这里我就只说一个即可,主要是设置openssl的lib和头文件的路径,这和使用任外部库都是一样的。截图如下,注意我的openssl安装位置为D:\Program Files\OpenSSL-Win64,请选择你安装位置即可。
在这里插入图片描述
预处理器里添加2个定义:CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;
在这里插入图片描述
附加依赖项:libssl.lib;openssl.lib;libcrypto.lib;liblegacy.lib;
在这里插入图片描述
最后将前面生成的cert.pem和key.pem放到exe目录下,为什么放到这个目录,是因为下面的代码用到的这2个文件是当前目录,不管怎么样,只要能找到这2个文件即可。
在这里插入图片描述
配置很简单,就上面几步,基本上就可以了。

代码部分

客户端代码

#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>#defineFAIL-1#pragmacomment(lib,"Ws2_32.lib")//Added the LoadCertificates how in the server-side makes.    intOpenConnection(constchar* hostname,int port){
    SOCKET sd;structhostent* host;structsockaddr_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);return1;}

    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,(structsockaddr*)&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;}voidShowCerts(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 */}elseprintf("No certificates.\n");}intmain(int count,char* strings[]){
    SSL_CTX* ctx;
    SOCKET server;
    SSL* ssl;char buf[1024];int bytes;charconst*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();return0;}

服务器端代码

#include<errno.h>#include<malloc.h>#include<string.h>#include<winsock2.h>#include<ws2tcpip.h>#include"openssl/ssl.h"#include"openssl/err.h"#ifdef__cplusplusextern"C"{#endif#include"openssl/applink.c"#ifdef__cplusplus}#endif#defineFAIL-1#pragmacomment(lib,"Ws2_32.lib")intOpenListener(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);return1;}

    m_socket =socket(AF_INET, SOCK_STREAM,0);if(m_socket == INVALID_SOCKET){printf("Error at socket(): %ld\n",WSAGetLastError());WSACleanup();return0;}structsockaddr_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,(structsockaddr*)&sain,sizeof(structsockaddr_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;#ifOPENSSL_VERSION_NUMBER >=0x10000000Lconst SSL_METHOD* method;#else
    SSL_METHOD* method;#endifSSL_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;}voidLoadCertificates(SSL_CTX* ctx,char* CertFile,char* KeyFile){//New linesint 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");}voidShowCerts(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);}elseprintf("No certificates.\n");}voidServlet(SSL* ssl, SOCKET client)/* Serve the connection -- threadable */{char buf[1024];char reply[1024];int sd, bytes;constchar* 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);}intmain(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){structsockaddr_in addr;socklen_t len =sizeof(addr);
        SSL* ssl;

        SOCKET client =accept(server,(structsockaddr*)&addr,&len);/* accept connection   as usual */socklen_t len1;structsockaddr_storage addr1;//add1.sin_family = AF_INET;char ipstr[INET6_ADDRSTRLEN];int port;

        len1 =sizeof addr;int r;

        r =getpeername(client,(structsockaddr*)&addr1,&len1);// deal with both IPv4 and IPv6:if(addr1.ss_family == AF_INET){structsockaddr_in* s =(structsockaddr_in*)&addr1;
            port =ntohs(s->sin_port);inet_ntop(AF_INET,&s->sin_addr, ipstr,sizeof ipstr);}else{// AF_INET6structsockaddr_in6* s =(structsockaddr_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.服务器端代码要求输入密码,请使用生成秘钥时的密码

标签: windows C openssl

本文转载自: https://blog.csdn.net/abcd552191868/article/details/126985198
版权归原作者 abcd552191868 所有, 如有侵权,请联系我们删除。

“windows openssl安装和基本使用(代码演示)”的评论:

还没有评论