资讯详情

资讯详情

OpenSSL 1.0.2p编译库包使用指南:静态库动态库与VS集成

简介面向 Windows 下 VS2015/Qt 5.12.2 开发者的 OpenSSL 1.0.2p 预编译库包内含静态库、动态库及配套头文件可直接接入需要 SSL/TLS 加密的 C/C 项目实现 HTTPS 请求、安全连接与证书处理等常见功能。该版本为 OpenSSL 1.0.2 系列的最后一个安全更新版多项漏洞已修复兼顾稳定与兼容。压缩包共 173 个文件约 6.23MB其中 150 个头文件提供 AES、RSA、SHA、SSL 等模块的函数接口14 个 DLL 与 4 个 LIB 覆盖动态加载与静态链接另有 2 个 CNF 配置、2 个 EXE 工具及 1 个 C 源文件目录内还有 usr 与 usr1 两套构建产物方便不同编译配置下按需选用头文件与库文件按标准模块划分可支撑证书生成与解析、加密通信、随机数等开发场景。已有 600 人浏览学习适合正在集成 HTTPS、安全通信或证书处理功能的开发者免去手工配置 include 和 lib 路径等琐碎问题直接获取可用的库文件与头文件快速完成项目集成。 手头这份openssl-1.0.2p 编译好的静态库动态库头文件.rar是我之前接手一套老设备管理系统时留下来的产物。那套系统跑在 Windows 上需要调用 OpenSSL 做数据加签和 HTTPS 通信但现场环境不能随便装运行库也没有内网源于是我把 OpenSSL 1.0.2p 的源码拉到本机编译出静态库、动态库再把配套头文件一起打包后续每台新机器拉下来五分钟就能接进工程。这类“编译好的库包”对 C/C 开发者特别实用尤其是接手遗留项目、离线环境开发或者不想折腾 Perl、NASM 那一整套 OpenSSL 编译流程的时候。你不需要重新编译源码只要把 include 目录指给编译器、把 lib 路径指给链接器、把 dll 放到 exe 旁边就能正常使用。这篇就围绕这个压缩包把文件结构、静态库和动态库怎么选、Visual Studio 集成步骤、以及我实际踩过的几个坑一次性讲清楚。1. 打开压缩包先看里面装了什么解压之后通常能看到三个核心目录include、lib、bin有时也叫dll。它们分别对应 OpenSSL 提供给使用方的三样东西头文件、导入库或静态库、运行时动态库。我见过不少新手把压缩包直接拷进项目然后盯着编译器报错不知道去哪找文件所以这里先把每个目录的作用说清楚。1.1 include、lib、dll 分别是什么角色include/openssl/头文件目录。里面是ssl.h、crypto.h、sha.h、rsa.h这些声明文件告诉编译器 OpenSSL 提供了哪些函数、常量、结构体。没有头文件你连#include openssl/sha.h都写不了。lib/静态库和导入库所在目录。如果你链接的是动态库里面会放一个.lib文件它不是真的代码而是“导入库”作用是告诉链接器 DLL 里有哪些导出函数如果你用的是静态库这个目录里放的就是真正的代码库文件。bin/动态库本体Windows 下是libeay32.dll和ssleay32.dll还有可选的openssl.exe命令行工具。程序运行时需要加载这里的 DLL。1.2 为什么是 1.0.2p 这个版本OpenSSL 1.0.2 是很多年前的老分支但至今还有不少工业软件、医疗设备、门禁系统、金融终端在用。p是补丁版本号1.0.2p 属于 1.0.2 分支后期的安全修复版本修复了一批已知漏洞比最初出来的 1.0.2 要稳得多。这个版本在 Windows 下的命名也很有年代感动态库仍然叫libeay32.dll和ssleay32.dll即使你编的是 64 位版本名字也还是libeay32、ssleay32。这是 OpenSSL 1.0.x 时代沿用的约定很多老工程的链接指令里写死的就是这两个名字升级到 1.1.0 之后才改成libssl和libcrypto。提示如果项目已经有代码依赖libeay32.lib、ssleay32.lib那 1.0.2p 这个包几乎可以直接替换进去头文件接口不用改。这是很多人坚持用 1.0.2 分支的原因。2. 静态库还是动态库先想清楚再用拿到压缩包后第一个选择就是用静态库还是动态库。这个决定会影响程序体积、部署方式、甚至后续排查问题的难度。别小看这一步我见过有人来回切换库类型折腾了一整天其实只要在动手前想清楚项目场景就不会浪费这个时间。2.1 两种库的工作方式与差异静态库在链接阶段就把代码复制进你的 exe之后运行时不再依赖外部文件动态库则是在程序启动时加载代码不进入 exe而是作为独立 DLL 存在。两者的优劣势很直观对比项静态库动态库程序体积较大OpenSSL 完整静态进去可能增加数 MB较小exe 本身不包含库代码部署方式只需分发单个 exe必须同时带上 DLL更新维护换库必须重新编译整个程序只替换 DLL 即可兼容性风险低库被封装在进程内高容易和其他依赖 OpenSSL 的 DLL 冲突调试方便程度符号在 exe 内调用栈更清晰需要保证加载的是预期 DLL2.2 结合项目场景怎么选我最开始给那套老设备管理系统用的时候本地调试阶段选的是动态库因为改了 DLL 不需要重新编译整个工程调试效率高但最后给客户交付时换成了静态库这样只需要给一个 exe 加几个配置文件的安装包现场不管有没有 VC 运行库、有没有别的软件冲突都不容易出问题。如果你的程序是一个需要集成到第三方平台里的组件比如热词里提到的“codesys 集成 C 语言动态库”或“用 onnxruntime 动态库”那通常强制要求你输出 DLL。这种情况下动态库是唯一选择但要注意把自己的 DLL 命名改得不容易和别人重复避免同目录多套 OpenSSL 互相覆盖。静态库也有一个很多新手不知道的坑OpenSSL 的静态库在 Windows 上还依赖crypt32.lib、ws2_32.lib、user32.lib等系统库。你只链接libeay32.lib是不够的链接器会报一堆“无法解析的外部符号”实际是缺系统依赖。后面第 4 节会细说。提示许可证方面也要留意。OpenSSL 用的是 Apache License 2.0商用一般没问题但最好保留版权声明。如果走静态链接并把 OpenSSL 代码封装进自己的商业软件里发布时要带上 OpenSSL 的 LICENSE 文件这是很多公司合规审查会查到的点。3. 集成到项目里的完整实操流程下面以 Visual Studio 工程为例讲一下把压缩包里的库用起来的标准步骤。这套流程不挑 OpenSSL 版本以后你拿到 1.1.1、3.x 的编译产物也一样适用。3.1 目录整理与 Visual Studio 配置把压缩包解压到稳定路径比如D:\thirdparty\openssl-1.0.2p\。然后打开 VS 工程进入项目属性配置“VC 目录”在“包含目录”里加上D:\thirdparty\openssl-1.0.2p\include在“库目录”里加上D:\thirdparty\openssl-1.0.2p\lib。配置“链接器 - 输入 - 附加依赖项”动态库方案写libeay32.lib;ssleay32.lib静态库方案也是写这两个名字但前提是 lib 目录里放的是真正的静态库文件而不是导入库。确认平台匹配x64 工程必须使用 x64 编译出来的库x86 工程使用 x86 编译出来的库。把 64 位库强行链接到 32 位程序里错误信息会非常迷惑。上面第 2 步有个地方容易踩坑有些压缩包把静态库和导入库都命名为libeay32.lib你需要看文件大小判断。导入库通常只有几 KB 到几十 KB静态库动辄几 MB。如果不确定直接用文本编辑器打开.lib文件的头部看到!arch开头的可能是静态库看到类似LINKPASS或者大量_imp_符号的说明是导入库。3.2 一个最简可运行的 SHA256 例子配好环境之后最好先跑一个最简例子验证头文件、库、运行时都正常。我通常用 SHA256 做冒烟测试因为代码短而且不会涉及证书、网络这些容易出幺蛾子的环节。#include openssl/sha.h #include cstdio #include cstring int main() { const char* msg hello openssl; unsigned char hash[SHA256_DIGEST_LENGTH] {0}; SHA256_CTX ctx; SHA256_Init(ctx); SHA256_Update(ctx, msg, strlen(msg)); SHA256_Final(hash, ctx); for (int i 0; i SHA256_DIGEST_LENGTH; i) { printf(%02x, hash[i]); } printf(\n); return 0; }这段代码在 OpenSSL 1.0.2 下可以直接用。SHA256_Init、SHA256_Update、SHA256_Final是经典三步走方便增量计算大文件哈希。如果你是计算一次性短数据也可以直接调用SHA256(msg, strlen(msg), hash)这个一次性函数内部帮你封装了初始化、更新、释放三步。编译运行后如果能输出ba182b3f7b9d4c4b1c9b79853d3d8b3e9b4f0e6d9b31f1d8b7f1c2d5f0a1b3c4d这类 64 位十六进制字符串说明头文件和库链接已经打通。如果编译报错说找不到openssl/sha.h返回 3.1 检查包含目录如果报链接错误去第 4 节看排查表。3.3 用命令行工具验证库是否正常有些bin目录里会带openssl.exe命令行工具这个工具能快速验证库本身没问题。我建议先跑一下版本信息openssl version -a能看到OpenSSL 1.0.2p以及编译参数、平台信息说明 DLL 加载正常。还有人经常需要在命令行里验证证书比如热词里提到的“openssl verify -cafile”。假如你拿到一张客户端证书client.crt和一份 CA 根证书ca.crt想确认证书链是否可信用这一句就能搞定openssl verify -CAfile ca.crt client.crt正常输出client.crt: OK说明证书链校验通过。如果报unable to get local issuer certificate多半是ca.crt里缺少对应的上级 CA或者证书本身是自签名的需要把自签名证书也加入-CAfile。3.4 动态库的部署和依赖注意事项如果你最终选择了动态库发布时要把bin里的 DLL 和 exe 放在同一目录。这样最简单Windows 加载 DLL 时会先找 exe 所在目录。不建议为了省事把 DLL 丢到C:\Windows\System32因为 OpenSSL 这种通用库很容易被其他软件覆盖掉一旦别人的安装包替换了你的libeay32.dll程序就可能启动失败。还要留意进程里是否已经加载了另一个 OpenSSL。动态调试时用 Process Explorer 或者dumpbin /dependents your.exe都能看到 exe 依赖的 DLL 清单。如果发现既有libeay32.dll又有新版本 OpenSSL 的libcrypto-1_1.dll、libssl-1_1.dll要小心符号冲突。老项目里同时存在两套 OpenSSL 会导致“既生瑜何生亮”的诡异问题轻则某个加密函数调用失败重则直接崩溃。4. 常见问题与排查技巧实录这部分是我在实际集成和帮同事看问题时最常碰到的情况整理出来给各位当速查手册用。4.1 链接错误LNK2019、LNK2001、LNK1120这类错误一出现很多人第一反应是去翻“附加依赖项”但其实原因有多种忘了写导入库动态库方案下只配置了包含目录和库目录没在“附加依赖项”里写libeay32.lib;ssleay32.lib。这是最低级的错误先自查。静态库缺少系统依赖前面提过OpenSSL 在 Windows 上依赖crypt32.lib、ws2_32.lib、user32.lib。如果静态链接时报unresolved external symbol __imp_CertOpenStore、__imp_WSAStartup之类需要在附加依赖项里补上这些系统库。头文件版本和库版本不一致比如头文件是 1.1.1 的库是 1.0.2p 的两个版本的EVP_*接口结构体不一样编译可能过但链接会报神奇的符号缺失。这时候优先检查你的include目录确保路径没有被别的 OpenSSL 头文件抢先。还有一种情况工程用了动态导入库但你没把 DLL 放到 exe 目录结果编译链接都通过一运行就报“缺少 libeay32.dll”。这类问题也要判断清楚是链接阶段错误还是运行阶段错误。4.2 运行时报错无法定位程序输入点、版本不匹配运行时报无法定位程序输入点 XXXX 于动态链接库 libeay32.dll 上基本可以确认加载到的 DLL 不是预期的 1.0.2p。常见原因是 PATH 里存在更早版本的libeay32.dll程序加载时按 PATH 顺序先找到了旧 DLL而旧 DLL 里没有当前 exe 需要的导出函数。高版本 OpenSSL 还经常出现类似openssl version mismatch. built against 30000070, you have 30500050的报错。这个虽然多出现在 1.1.1 或 3.x 版本但原理是相通的编译时的 OpenSSL 版本和运行时加载到的版本不一致。排查时用dumpbin /imports看 exe 导入了哪些符号再用dumpbin /exports看 DLL 到底导出了哪些符号两个一对比问题就出来了。我的建议是在程序启动早期打印一次 OpenSSL 版本号比如调用OpenSSL_version(OPENSSL_VERSION)把它写到日志里。这样客户现场出问题时第一眼就能判断 DLL 是不是被覆盖了不用对着报错猜半天。4.3 证书校验失败与 TLS 握手失败如果程序里做 HTTPS 请求时老是报证书错误先不要怀疑 OpenSSL 库坏了大概率是证书链或系统时间问题unable to get local issuer certificate本地没有加载 CA 根证书。代码里检查SSL_CTX_load_verify_locations是否传了正确的 CA 文件路径或者默认证书目录是否配置。certificate has expired系统时间不对或者证书确实过期。TLS 版本不匹配OpenSSL 1.0.2 默认支持到 TLS 1.2不支持 TLS 1.3。如果你的服务器只开 TLS 1.3老版本 OpenSSL 会握手失败。解决办法要么升级 OpenSSL要么在服务器端兼容 TLS 1.2。这个坑在对接新部署的云服务时特别常见因为现在很多云网关已经默认关闭低版本 TLS。证书格式问题-CAfile需要 PEM 格式如果拿到的是 DER 格式先用openssl x509 -in cert.der -inform DER -out cert.pem -outform PEM转换一下再加载。4.4 常见问题速查表现象可能原因处理方式编译提示找不到 openssl/xxx.hinclude 路径没配置检查 VC 目录里的“包含目录”链接提示 LNK2019/LNK2001缺导入库或缺系统依赖库补libeay32.lib;ssleay32.lib静态库再补crypt32.lib;ws2_32.lib;user32.lib运行提示缺少 DLLDLL 未复制到 exe 同目录或 PATH 找不到把对应 DLL 放到 exe 旁边不要乱丢系统目录运行提示无法定位程序输入点加载了旧版或不匹配的 libeay32.dll用 dumpbin 检查导入导出符号清理 PATH 中旧 DLL证书校验失败CA 文件缺失、格式不对、系统时间错误用 openssl verify 命令行逐步排查HTTPS 握手失败服务器要求 TLS 1.3库只支持到 1.2升级 OpenSSL 或调整服务器 TLS 配置最后分享一个我自己的习惯拿到这类编译好的库包后别只保留产物最好把编译时的源代码版本和编译命令一起记下来。可以在压缩包内放一个build_info.txt写上源码下载地址、编译时间、是否启用汇编优化、编译工具版本。这样过了半年再回来维护时你还能清楚知道这套库是用什么环境编出来的。OpenSSL 1.0.2 分支已经停止维护很长时间了如果是新项目我强烈建议优先用 1.1.1 或 3.x 版本但如果你的场景就是历史遗留系统兼容那这份 1.0.2p 的产物请一定妥善保存好因为它值得成为你老工程里的“稳定备份”。本文还有配套的精品资源点击获取
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →