WIN10系统在VS2015配置OpenSSL

小学期要求做一个通信保密系统,安装配置OpenSSL遇到一些大坑,做一下笔记给自己吧。

下载OpenSSL

这里有很大的坑,官网下载的OpenSSL是没编译的,编译的过程极其繁琐;要下载编译好的OpenSSL才能使用直接使用,怎么办呢?还好有一个网站可以下载编译好的OpenSSL库:http://slproweb.com/products/Win32OpenSSL222.html

(下载好的OpenSSL在运用的时候会有一些小问题,后面会说。)

                                   WIN10系统在VS2015配置OpenSSL

                                                                                    下载网页截图

在VS2015中配置OpenSSL

如果你直接把引用到OpenSSL库的代码复制到源文件中,会有红色的标释提醒代码错误。

所以不仅仅要安装OpenSSL,还要在VS2015软件中配置一下才能用。关于配置的理解,我认为就是将OpenSSL文件的链接写清楚,以至于VS2015能够检测到OpenSSL中的函数。

话不多说,开始配置:

依次点击:项目—>属性—>配置属性—>VC++目录—>包含目录库—>编辑,

然后将OpenSSL的include文件位置填入。

WIN10系统在VS2015配置OpenSSL

 include文件位置

WIN10系统在VS2015配置OpenSSL

配置 

完成这一步再去编译代码,如果你能过了,应该就成功了。

不过的话,请看下面的错误解决办法

遇到的问题和解决方法

1,代码的问题

#pragma comment(lib,"libeay32.lib")

#pragma comment(lib,"ssleay32.lib")

原来找到的代码,给的lib链接是这样写的;出现下面的错误:

WIN10系统在VS2015配置OpenSSL

要改为具体的文件位置,比如我的libeay32.lib在 C:\\Program Files (x86)\\OpenSSL-Win64\\lib\\libeay32.lib中,所以要改为以下代码:

#pragma comment(lib,"C:\\Program Files (x86)\\OpenSSL-Win64\\lib\\libeay32.lib")

#pragma comment(lib,"C:\\Program Files (x86)\\OpenSSL-Win64\\lib\\ssleay32.lib")

fopen函数提示错误:

打开属性,点击C/C++,编辑预处理器定义,添加_CRT_SECURE_NO_WARNINGS

 2,其他的问题

库计算机类型和目标计算机类型冲突:

目标计算机类型:

WIN10系统在VS2015配置OpenSSL

 库计算机:

WIN10系统在VS2015配置OpenSSL

解决办法:都调为x64 

还有一个问题是用到关于RSA的公私钥文件pem的时候回出现的问题:函数PEM_read_bio_PUBKEY等;

编译的时候没有错误,运行的时候窗口会一闪而过。通过单步调试才发现是pem类型的函数出现错误

查了资料说是要在本机编译OpenSSL才能解决,好像要改变引用的指针类型(比如BIO)也可以 解决。

https://blog.****.net/zuoyefeng1990/article/details/51578781(这篇博客有提到这种问题)

 测试代码:

#include <stdio.h>  
#include <string.h>  
#include <openssl/evp.h>  
#include <openssl/x509.h>  
#include <iostream>

using namespace std;

#pragma comment(lib,"C:\\Program Files (x86)\\OpenSSL-Win64\\lib\\libeay32.lib")
#pragma comment(lib,"C:\\Program Files (x86)\\OpenSSL-Win64\\lib\\ssleay32.lib")

void tSign()
{
    unsigned char sign_value[1024]; //保存签名值的数组  
    int sign_len;           //签名值长度  
    EVP_MD_CTX mdctx;       //摘要算法上下文变量  
    char mess1[] = "xxh";       //待签名的消息  
    RSA *rsa = NULL;          //RSA结构体变量  
    EVP_PKEY *evpKey = NULL;      //EVP KEY结构体变量  
    int i;

    printf("正在产生RSA**...");
    rsa = RSA_generate_key(1024, RSA_F4, NULL, NULL);//产生一个1024位的RSA**//printf ("bits: %d\n", BN_num_bits (rsa->n));//返回n的二进制位数!1024!  
    if (rsa == NULL)
    {
        printf("gen rsa err\n");
        return;
    }
    printf(" 成功.\n");
    //cout << "rsa **为:" << rsa << endl;
    evpKey = EVP_PKEY_new();//新建一个EVP_PKEY变量  
    if (evpKey == NULL)
    {
        printf("EVP_PKEY_new err\n");
        RSA_free(rsa);
        return;
    }
    if (EVP_PKEY_set1_RSA(evpKey, rsa) != 1)  //保存RSA结构体到EVP_PKEY结构体  
    {
        printf("EVP_PKEY_set1_RSA err\n");
        RSA_free(rsa);
        EVP_PKEY_free(evpKey);
        return;
    }
    //以下是计算签名代码  
    EVP_MD_CTX_init(&mdctx);//初始化摘要上下文  
    if (!EVP_SignInit_ex(&mdctx, EVP_md5(), NULL))//签名初始化,设置摘要算法,本例为MD5  
    {
        printf("err\n");
        EVP_PKEY_free(evpKey);
        RSA_free(rsa);
        return;
    }
    if (!EVP_SignUpdate(&mdctx, mess1, strlen(mess1)))//计算签名(摘要)Update  
    {
        printf("err\n");
        EVP_PKEY_free(evpKey);
        RSA_free(rsa);
        return;
    }
    //cout << "摘要为:" << &mdctx << endl;
    if (!EVP_SignFinal(&mdctx, sign_value, (unsigned int *)&sign_len, evpKey))  //签名输出  
    {
        printf("err\n");
        EVP_PKEY_free(evpKey);
        RSA_free(rsa);
        return;
    }
    printf("消息\"%s\"的签名值是: \n", mess1);
    for (i = 0; i < sign_len; i++)
    {
        if (i % 16 == 0)
            printf("\n%08xH: ", i);
        printf("%02x ", sign_value[i]);
    }
    printf("\n");
    EVP_MD_CTX_cleanup(&mdctx);

    printf("\n正在验证签名...\n");
    //以下是验证签名代码  
    EVP_MD_CTX_init(&mdctx);//初始化摘要上下文  
    if (!EVP_VerifyInit_ex(&mdctx, EVP_md5(), NULL))//验证初始化,设置摘要算法,一定要和签名一致。  
    {
        printf("EVP_VerifyInit_ex err\n");
        EVP_PKEY_free(evpKey);
        RSA_free(rsa);
        return;
    }
    if (!EVP_VerifyUpdate(&mdctx, mess1, strlen(mess1)))//验证签名(摘要)Update  
    {
        printf("err\n");
        EVP_PKEY_free(evpKey);
        RSA_free(rsa);
        return;
    }
    if (!EVP_VerifyFinal(&mdctx, sign_value, sign_len, evpKey))//验证签名  
    {
        printf("verify err\n");
        EVP_PKEY_free(evpKey);
        RSA_free(rsa);
        return;
    }
    else
    {
        printf("验证签名正确.\n");
    }
    //释放内存  
    EVP_PKEY_free(evpKey);
    RSA_free(rsa);
    EVP_MD_CTX_cleanup(&mdctx);

}
int main()
{
    OpenSSL_add_all_algorithms();
    tSign();
    system("pause");
    return 0;
}

参考博客:

https://blog.****.net/ljttianqin/article/details/72991125(配置OpenSSL)

https://blog.****.net/gpltoken/article/details/53011068(文章末尾有AES对文件进行加解密的程序,有任务的同学可以看一下)