windows、vs2017编译64位openssl-1.1.1v及使用

一、环境准备

ActivePerl    -    ActivePerl-5.26.3.2603-MSWin32-x64-a95bce075.exe

nasm    -    nasm-2.14.02-installer-x64.exe

以上两个下载地址:【免费】windows、vs2017编译64位openssl-1.1.1v所需要用到的ActivePerl和nasm资源-CSDN文库

以上两个工具都全部默认安装即可;

如上,需确保两个工具的路径存在于环境变量中,如没有,请手动添加;

如上,管理员身份使用vs2017的命令行工具分别执行perl -v和nasm -v,得到版本信息则两个工具的环境已经正常;

二、编译

依然以管理员身份使用vs2017的命令行工具进入到openssl的源码目录:

配置编译:

编译动态库:

perl configure VC-WIN64A --prefix=D:\lib\OpenSSL\x64

编译静态库:

perl configure no-shared VC-WIN64A --prefix=D:\lib\OpenSSL\x64

此阶段可能会出现如下报错:Can't open perl script "configure": No such file or directory

这时候检查下你的目录是否正确,一般会是cd进入的目录有误导致

编译:nmake

安装到目录:nmake install

三、使用

测试源码如下:

#include <string>

/** 基于openssl对字符串进行base64编码:c_original-原始字符串,i_len-原始字符串长度 */
std::string string_encode_openssl_base64(const char *c_original, int i_len);
/** 基于openssl对字符串进行base64解码:ss_base64-base64字符串,c_original-原始字符串,s_len-原始字符串长度 */
void string_decode_openssl_base64(const std::string &ss_base64, char *c_original, size_t &s_len);
/** 基于openssl的des加密算法以cfb64模式对字符串进行加密(加密前后长度一致,不存在补'\0'情况):c_original-原始字符串,i_len-原始字符串长度,c_encrypt-加密字符串,ss_key_1-密匙1,ss_key_2-密匙2,ss_key_3-密匙3 */
void string_encrypt_openssl_des_cfb64(char *c_original, int i_len, char *c_encrypt, const std::string &ss_key_1 = "", const std::string &ss_key_2 = "", const std::string &ss_key_3 = "");
/** 基于openssl的des解密算法以cfb64模式对字符串进行解密(解密前后长度一致,不存在补'\0'情况):c_encrypt-加密字符串,i_len-加密字符串长度,c_encrypt-原始字符串,ss_key_1-密匙1,ss_key_2-密匙2,ss_key_3-密匙3 */
void string_decrypt_openssl_des_cfb64(char *c_encrypt, int i_len, char *c_original, const std::string &ss_key_1 = "", const std::string &ss_key_2 = "", const std::string &ss_key_3 = "");
/** 基于openssl的des加密算法以cbc模式对字符串进行加密:ss_original-原始字符串(必须使用确定不会出现'\0'的字符串,否则在解密阶段处理结尾恰好为'\0'的字符串会丢失内容),ss_key-密匙 */
std::string string_encrypt_openssl_des_cbc(const std::string &ss_original, const std::string &ss_key = "");
/** 基于openssl的des解密算法以cbc模式对字符串进行解密:ss_encrypt-加密字符串,ss_key-密匙 */
std::string string_decrypt_openssl_des_cbc(const std::string &ss_encrypt, const std::string &ss_key = "");
/** 基于openssl的des加密算法以ecb模式对字符串进行加密:ss_original-原始字符串(必须使用确定不会出现'\0'的字符串,否则在解密阶段处理结尾恰好为'\0'的字符串会丢失内容),ss_key-密匙 */
std::string string_encrypt_openssl_des_ecb(const std::string &ss_original, const std::string &ss_key = "");
/** 基于openssl的des解密算法以ecb模式对字符串进行解密:ss_encrypt-加密字符串,ss_key-密匙 */
std::string string_decrypt_openssl_des_ecb(const std::string &ss_encrypt, const std::string &ss_key = "");

#include "OpensslCommon.h"
#include "openssl/bio.h"
#include "openssl/evp.h"
#include "openssl/buffer.h"
#include "openssl/des.h"
#include <vector>

#pragma warning(disable:4996)

std::string string_encode_openssl_base64(const char *c_original, int i_len)
{
    std::string ss_base64 = "";
    if (c_original != nullptr && i_len > 0)
    {
        BIO *base64_bio = BIO_new(BIO_f_base64());//base64过滤器:编解码操作的bio接口
        if (base64_bio != nullptr)
        {
            BIO_set_flags(base64_bio, BIO_FLAGS_BASE64_NO_NL);//去掉所有换行符
            BIO *mem_bio = BIO_new(BIO_s_mem());//内存读写操作的bio接口
            if (mem_bio != nullptr)
            {
                BIO_push(base64_bio, mem_bio);
                if (BIO_write(base64_bio, c_original, i_len) > 0)
                {
                    BIO_flush(base64_bio);
                    BUF_MEM *p_data = nullptr;
                    BIO_get_mem_ptr(base64_bio, &p_data);
                    if (p_data != nullptr)
                    {
                        ss_base64 = std::string(p_data->data, p_data->length);
                    }
                }
            }
            BIO_free_all(base64_bio);
        }
    }
    return ss_base64;
}

void string_decode_openssl_base64(const std::string &ss_base64, char *c_original, size_t &s_len)
{
    s_len = 0;
    if (c_original == nullptr)
    {
        return;
    }

    BIO *base64_bio = BIO_new(BIO_f_base64());
    if (base64_bio == nullptr)
    {
        return;
    }

    BIO_set_flags(base64_bio, BIO_FLAGS_BASE64_NO_NL);
    BIO *mem_bio = BIO_new_mem_buf(ss_base64.c_str(), ss_base64.length());
    if (mem_bio == nullptr)
    {
        BIO_free_all(base64_bio);
        return;
    }

    BIO_push(base64_bio, mem_bio);
    BIO_read_ex(base64_bio, c_original, ss_base64.length() + 1, &s_len);
    if (s_len <= 0)
    {
        BIO_free_all(base64_bio);
        return;
    }

    BIO_free_all(base64_bio);
}

void string_encrypt_openssl_des_cfb64(char *c_original, int i_len, char *c_encrypt, const std::string &ss_key_1, const std::string &ss_key_2, const std::string &ss_key_3)
{
    if (c_original == nullptr || i_len <= 0 || c_encrypt == nullptr)
    {
        return;
    }

    DES_cblock key;
    memset(key, 0, sizeof(DES_cblock));
    memcpy(key, ss_key_1.c_str(), ss_key_1.length() <= 8 ? ss_key_1.length() : 8);
    DES_key_schedule key_schedule_1 = {};
    DES_set_key_unchecked(&key, &key_schedule_1);
    memset(key, 0, sizeof(DES_cblock));
    memcpy(key, ss_key_2.c_str(), ss_key_2.length() <= 8 ? ss_key_2.length() : 8);
    DES_key_schedule key_schedule_2 = {};
    DES_set_key_unchecked(&key, &key_schedule_2);
    memset(key, 0, sizeof(DES_cblock));
    memcpy(key, ss_key_3.c_str(), ss_key_3.length() <= 8 ? ss_key_3.length() : 8);
    DES_key_schedule key_schedule_3 = {};
    DES_set_key_unchecked(&key, &key_schedule_3);
    DES_cblock ivec = {};
    int num = 0;
    DES_ede3_cfb64_encrypt((const unsigned char *)c_original, (unsigned char *)c_encrypt, i_len, &key_schedule_1, &key_schedule_2, &key_schedule_3, &ivec, &num, DES_ENCRYPT);
}

void string_decrypt_openssl_des_cfb64(char *c_encrypt, int i_len, char *c_original, const std::string &ss_key_1, const std::string &ss_key_2, const std::string &ss_key_3)
{
    if (c_encrypt == nullptr || i_len <= 0 || c_original == nullptr)
    {
        return;
    }

    DES_cblock key;
    memset(key, 0, sizeof(DES_cblock));
    memcpy(key, ss_key_1.c_str(), ss_key_1.length() <= 8 ? ss_key_1.length() : 8);
    DES_key_schedule key_schedule_1 = {};
    DES_set_key_unchecked(&key, &key_schedule_1);
    memset(key, 0, sizeof(DES_cblock));
    memcpy(key, ss_key_2.c_str(), ss_key_2.length() <= 8 ? ss_key_2.length() : 8);
    DES_key_schedule key_schedule_2 = {};
    DES_set_key_unchecked(&key, &key_schedule_2);
    memset(key, 0, sizeof(DES_cblock));
    memcpy(key, ss_key_3.c_str(), ss_key_3.length() <= 8 ? ss_key_3.length() : 8);
    DES_key_schedule key_schedule_3 = {};
    DES_set_key_unchecked(&key, &key_schedule_3);
    DES_cblock ivec = {};
    int num = 0;
    DES_ede3_cfb64_encrypt((const unsigned char *)c_encrypt, (unsigned char *)c_original, i_len, &key_schedule_1, &key_schedule_2, &key_schedule_3, &ivec, &num, DES_DECRYPT);
}

std::string string_encrypt_openssl_des_cbc(const std::string &ss_original, const std::string &ss_key)
{
    size_t s_len = (ss_original.length() + 7) / 8 * 8;
    unsigned char *output = nullptr;
    try
    {
        output = new unsigned char[s_len + 1];
    }
    catch (const std::exception &e)
    {
        return "";
    }

    DES_cblock key = {};
    memcpy(key, ss_key.c_str(), ss_key.length() <= 8 ? ss_key.length() : 8);
    DES_key_schedule key_schedule = {};
    DES_set_key_unchecked(&key, &key_schedule);
    DES_cblock ivec = {};
    DES_ncbc_encrypt((const unsigned char *)ss_original.c_str(), output, ss_original.length(), &key_schedule, &ivec, DES_ENCRYPT);
    std::string ss_encrypt = std::string((char *)output, s_len);
    delete output;
    output = nullptr;
    return ss_encrypt;
}

std::string string_decrypt_openssl_des_cbc(const std::string &ss_encrypt, const std::string &ss_key)
{
    size_t s_len = ss_encrypt.length();
    unsigned char *output = nullptr;
    try
    {
        output = new unsigned char[s_len + 1];
    }
    catch (const std::exception &e)
    {
        return "";
    }

    DES_cblock key = {};
    memcpy(key, ss_key.c_str(), ss_key.length() <= 8 ? ss_key.length() : 8);
    DES_key_schedule key_schedule = {};
    DES_set_key_unchecked(&key, &key_schedule);
    DES_cblock ivec = {};
    DES_ncbc_encrypt((const unsigned char *)ss_encrypt.c_str(), output, s_len, &key_schedule, &ivec, DES_DECRYPT);
    for (size_t i = s_len - 1; i >= 0; i--)
    {
        if(*(output+i) != '\0')
        {
            break;
        }

        s_len--;
    }
    std::string ss_decrypt = std::string((char *)output, s_len);
    delete output;
    output = nullptr;
    return ss_decrypt;
}

std::string string_encrypt_openssl_des_ecb(const std::string &ss_original, const std::string &ss_key)
{
    DES_cblock key = {};//密钥
    memcpy(key, ss_key.c_str(), ss_key.length() <= 8 ? ss_key.length() : 8);
    DES_key_schedule key_schedule = {};//存放密钥的结构体
    DES_set_key_unchecked(&key, &key_schedule);
    const_DES_cblock input = {};//需要加密的数据
    DES_cblock output = {};//加密后的数据
    unsigned char tmp[8] = {};
    std::vector<unsigned char> svuc_encrypt = {};
    for (int i = 0; i < ss_original.length() / 8; i++)//8字节循环加密
    {
        memcpy(input, ss_original.c_str() + i * 8, 8);
        DES_ecb_encrypt(&input, &output, &key_schedule, DES_ENCRYPT);
        memcpy(tmp, output, 8);
        for (int j = 0; j < 8; j++)
        {
            svuc_encrypt.push_back(tmp[j]);
        }
    }
    if (ss_original.length() % 8 != 0)//超过8的倍数的部分的字节依然8字节循环加密
    {
        int tmp1 = ss_original.length() / 8 * 8;
        int tmp2 = ss_original.length() - tmp1;
        memset(input, 0, 8);//全部置为'\0',这样因长度不足而被补充的字节在解密的阶段解析出来也是'\0',解密阶段去掉结尾的'\0'即可
        memcpy(input, ss_original.c_str() + tmp1, tmp2);
        DES_ecb_encrypt(&input, &output, &key_schedule, DES_ENCRYPT);
        memcpy(tmp, output, 8);
        for (int j = 0; j < 8; j++)
        {
            svuc_encrypt.push_back(tmp[j]);
        }
    }
    std::string ss_encrypt = "";
    ss_encrypt.assign(svuc_encrypt.begin(), svuc_encrypt.end());
    return ss_encrypt;
}

std::string string_decrypt_openssl_des_ecb(const std::string &ss_encrypt, const std::string &ss_key)
{
    DES_cblock key = {};
    memcpy(key, ss_key.c_str(), ss_key.length() <= 8 ? ss_key.length() : 8);
    DES_key_schedule key_schedule = {};
    DES_set_key_unchecked(&key, &key_schedule);
    const_DES_cblock input = {};
    DES_cblock output = {};
    unsigned char tmp[8] = {};
    std::vector<unsigned char> svuc_decrypt = {};
    for (int i = 0; i < ss_encrypt.length() / 8; i++)
    {
        memcpy(input, ss_encrypt.c_str() + i * 8, 8);
        DES_ecb_encrypt(&input, &output, &key_schedule, DES_DECRYPT);
        memcpy(tmp, output, 8);
        for (int j = 0; j < 8; j++)
        {
            if (i == (ss_encrypt.length() / 8 - 1))//结尾的数据
            {
                if (tmp[j] != '\0')//不要多余的'\0'
                {
                    svuc_decrypt.push_back(tmp[j]);
                }
            }
            else
            {
                svuc_decrypt.push_back(tmp[j]);
            }
        }
    }
    std::string ss_decrypt = "";
    ss_decrypt.assign(svuc_decrypt.begin(), svuc_decrypt.end());
    return ss_decrypt;
}

#include "OpensslCommon.h"

//#define openssl_base64
#define openssl_cfb64

int main(int argc, char **argv)
{
#ifdef openssl_base64
    char c_original[20] = {};
    memcpy(c_original, "this is an", 10);
    c_original[10] = '\0';
    memcpy(c_original + 11, " example", 8);
    printf("*****\n");
    for (size_t i = 0; i < 19; i++)
    {
        if (*(c_original + i) == '\0')
        {
            printf("-");
        }
        else
        {
            printf("%c", *(c_original + i));
        }
    }
    printf("\n");

    std::string ss_base64 = string_encode_openssl_base64(c_original, 19);
    printf("*****\n");
    printf("%s    -    %llu\n", ss_base64.c_str(), ss_base64.length());

    memset(c_original, 0, sizeof(c_original));
    size_t s_len = 0;
    string_decode_openssl_base64(ss_base64, c_original, s_len);
    if (s_len > 0)
    {
        printf("*****\n");
        for (size_t i = 0; i < s_len; i++)
        {
            if (*(c_original + i) == '\0')
            {
                printf("-");
            }
            else
            {
                printf("%c", *(c_original + i));
            }
        }
        printf("\n");
    }
#endif
#ifdef openssl_cfb64
    char c_original[20] = {};
    memcpy(c_original, "this is an", 10);
    c_original[10] = '\0';
    memcpy(c_original + 11, " example", 8);
    printf("*****\n");
    for (size_t i = 0; i < 19; i++)
    {
        if (*(c_original + i) == '\0')
        {
            printf("-");
        }
        else
        {
            printf("%c", *(c_original + i));
        }
    }
    printf("\n");

    char c_encrypt[20] = {};
    std::string ss_key_1 = "11111111";
    std::string ss_key_2 = "22222222";
    std::string ss_key_3 = "33333333";
    string_encrypt_openssl_des_cfb64(c_original, 19, c_encrypt, ss_key_1, ss_key_2, ss_key_3);
    printf("*****\n");
    printf("%s\n", c_encrypt);

    memset(c_original, 0, sizeof(c_original));
    string_decrypt_openssl_des_cfb64(c_encrypt, 19, c_original, ss_key_1, ss_key_2, ss_key_3);
    printf("*****\n");
    for (size_t i = 0; i < 19; i++)
    {
        if (*(c_original + i) == '\0')
        {
            printf("-");
        }
        else
        {
            printf("%c", *(c_original + i));
        }
    }
    printf("\n");
#endif

    system("pause");
    return 0;
}

使用静态库的时候,会可能遇到如下报错(使用动态库不会有该报错)

LNK2019    无法解析的外部符号 __imp_CertOpenStore,该符号在函数 capi_open_store 中被引用
该报错原因:

OpenSSL库使用了windows的一个密码学库: Crypt32

该报错解决办法:

在 项目属性 - 链接器 - 输入 - 附加依赖项 中加入: Crypt32.lib

错误:

LNK2019: 无法解析的外部符号 __imp_DeregisterEventSource,该符号在函数 OPENSSL_showfatal 中被引用

解决:

advapi32.lib

错误:

LNK2019: 无法解析的外部符号 __imp_GetProcessWindowStation,该符号在函数 OPENSSL_isservice 中被引用

解决:

user32.lib

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值