ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

OpenSSL 1.1.1w Windows 源码编译指南:x64/x86 双架构完整教程

2026/9/8 13:45:19 拓冰建站 浏览量
OpenSSL 1.1.1w Windows 源码编译指南:x64/x86 双架构完整教程 简介openssl1.1.1w是应用广泛的开源加密库支持SSL/TLS协议以及RSA、AES、DES、SHA等常见加密算法。该资源面向Windows平台开发者同时提供x64和x86两套可直接使用的编译库与对应源码包省去自行搭建msys2、手工编译的繁琐过程适合需要快速为客户端/服务器、物联网通信等场景加入加密能力的项目。压缩包共120个文件大小约17.25MB主要包含104个头文件、8个静态库、4个DLL动态库、3个pkg-config配置和1个源码压缩包分别用于接口声明、静态链接、动态加载、构建环境识别及源码查阅整体结构清晰。已有58人学习浏览对个人开发者和团队均有参考价值。借助源码可以了解openssl1.1.1w相对旧版在安全性与稳定性方面的修复编译好的x64/x86库则可直接嵌入Visual Studio、MinGW等常用工程省去底层加密实现细节缩短安全通信功能的集成时间。 客户现场给我发来一个截图程序启动时报openssl version mismatch. built against 30000070, you have 30500050。排查到最后既不是他们代码写错也不是我给的SDK有问题而是客户机器上某个第三方软件往 System32 里塞了一份版本完全不同的 OpenSSL DLL程序启动时优先加载到了它结果和编译时的头文件/导入库对不上直接罢工。打那以后我就形成了一个习惯能用自己从源码编译的版本绝不用来路不明的预编译包一定要让头文件、导入库、DLL 三者同源同版本并且把这一套流程沉淀成标准化操作。这篇就把 OpenSSL 1.1.1w 源码在 Windows 下编译 x64、x86 两套库的完整过程写清楚给正准备在 Windows 上把 OpenSSL 编进 C/C 项目的同学一个可以直接抄作业的参考。1. 编译这套库之前先想清楚三件事1.1 为什么锁定 1.1.1w而不是直接上 3.x先说结论如果你是新项目我建议你直接看 OpenSSL 3.x如果你是在维护存量项目1.1.1w 是一个非常值得锁定的版本。1.1.1w 是 OpenSSL 1.1.1 系列的最后一个版本也是这个系列生命周期结束前的最终修复版。官方对它的定位就是“不再新增功能只修安全漏洞然后彻底停止维护”。为什么很多团队宁可停在这个“已经被官方宣判死刑”的版本上因为 1.1.1 和 3.x 之间的 API 不是简单的向下兼容很多老代码用到的SSL_CTX、SSL_new、BIO这一套调用虽然大体还在但 3.x 引入了 Provider 架构、默认安全级别调整、证书验证行为更严格程序跑起来的行为会和 1.1.1 有明显差异。对于一个已经上线几年的业务系统为了升 OpenSSL 而重新验证整个 TLS 握手流程、证书链校验逻辑、各种密码套件的兼容性成本是相当高的。所以现实情况是新项目可以用 3.x但存量项目里大量团队选择停留在 1.1.1w把它当作 1.1.1 时代的稳定终点。这也是为什么到现在还有那么多人在搜“openssl 1.1.1w 源码编译”——网上能找到的编译教程大多过时或不全真正能直接跑通双架构的很少。1.2 动态库还是静态库动手之前先选好编译 OpenSSL 之前一定要想清楚你要动态链接还是静态链接因为这直接决定 Configure 参数和后面接入 VS 工程时的配置方式改起来挺麻烦。动态库方案的好处是exe 体积小后续 OpenSSL 升级只需要替换 DLL 文件不用重新编译整个工程缺点是发布时要带上两个 DLL而且要处理 DLL 加载顺序、版本污染这些运行时问题文章开头的版本不匹配事故就是典型的反面教材。静态库方案的好处是libssl_static.lib和libcrypto_static.lib直接编进 exe部署最干净拷一个 exe 就能跑缺点是链接出来的文件体积会大不少而且如果同一台机器上有多个程序都用了 OpenSSL每个程序里都塞一份静态库磁盘和内存都有浪费。我的经验是给客户交付需要频繁更新安全补丁的场景优先动态库内部工具、辅助程序、对部署目录有洁癖的项目用静态库。本文默认流程会同时产出动态库和静态库你按需挑。另外要注意OpenSSL 1.1.1w 在 Windows 上编译时动态库方案和静态库方案的输出文件命名完全不同后面第三章第三节我把清单列出来。1.3 x64 和 x86 双架构不是简单地编译两遍这个标题里的“windows x64、x86”其实是两个目标架构很多做 SDK 的团队会深有体会客户环境什么架构都有宿主程序可能是 64 位也可能是 32 位你交付的库必须两个架构都覆盖。最容易踩的坑是在同一份源码目录里先跑一遍perl Configure VC-WIN64A编完 x64 后再跑一遍perl Configure VC-WIN32想让 Configure 帮你切换架构。但 OpenSSL 的 Configure 不是一个干净的切换器它会在源码目录里生成makefile、修改include/openssl/opensslconf.h、写出一堆中间产物。你第二次 Configure 时上一轮的东西并不会全部清除最后编出来可能出现“配置的是 x86编出来的库在 x64 下也能加载”这种说不清道不明的结果或者在 nmake 阶段出现各种诡异报错。正确做法是准备两份完全独立的源码解压目录一份编 x64一份编 x86互不干扰。x64 编完不会碰 x86 的产物x86 那边也不会残留 x64 的配置这才是省心的路。2. 环境准备Perl、NASM 和 VS 命令提示符缺一个都会白忙2.1 Strawberry Perl 和 NASM 的安装与验证OpenSSL 的 Configure 脚本是用 Perl 写的Windows 不自带 Perl所以第一步就是装 Perl。我推荐 Strawberry Perl5.32 以上的新版本都行。安装时记得勾选把 perl 加入到 PATH不然接下来每个命令都要写全路径很痛苦。NASM 是汇编器。OpenSSL 在 x86/x64 平台上的很多核心加密算法都有汇编优化版本像 AES-NI、SHA 相关运算性能比纯 C 版本快非常多。NASM 就是用来把这些.asm汇编源文件编译成目标文件的。版本不用太新2.15 以上足够 1.1.1w 用了。装完把 nasm.exe 的目录加到 PATH。注意一个细节Perl 和 NASM 都要求能在命令行里直接敲命令找到所以装完之后先验证perl -v nasm -v两个命令都有版本信息输出才说明环境 OK。2.2 用对 VS 命令提示符Native Tools 是什么东西很多人第一次编 OpenSSL 失败问题不在 OpenSSL 本身而是打开了普通的“命令提示符”或 PowerShell 就敲nmake结果系统提示找不到 nmake 或者找不到 cl。原因是 MSVC 编译器不是全局命令需要先加载对应的环境变量。Visual Studio 安装之后开始菜单里会有一组入口名字大致是x64 Native Tools Command Prompt for VS 2022x86 Native Tools Command Prompt for VS 2022这里的“Native Tools”含义是打开这个提示符之后里面的 cl 编译器目标架构就是对应的架构。x64 Native Tools 打开后你的 cl 编出来就是 x64 目标x86 Native Tools 打开后cl 编出来就是 x86 目标。打开错了后面你的 OpenSSL 不管怎么 Configure 都可能产出不匹配的编译器产物。一个很容易出错的操作是编 x64 库时打开了普通的 Developer Command Prompt它的默认目标架构是 x86然后 Configure 选的又是VC-WIN64A工具链和 Configure 目标不匹配编译器生成的代码架构和 OpenSSL 汇编输入的架构对不上轻则编译性能低下重则直接报错。其实你还可以用 vcvarsall.bat 手动切换架构但没必要自找麻烦直接用开始菜单对应架构的入口最简单。2.3 三行命令确认环境就绪开始 Configure 之前我习惯先做一次环境体检在对应架构的 VS 命令提示符里依次执行where perl where nasm clwhere perl能找到你刚装的 Strawberry Perlwhere nasm能找到 nasm.exe并且能看到它的实际路径cl会输出几行 MSVC 编译器版本信息。如果where命令找不到某个工具说明 PATH 没配好或者你打开的不是 VS 的环境。环境问题我建议在编译前一次性排查干净因为 Configure 往往能过但 nmake 会挂在各种奇怪的环节到时候再回头排查环境就慢了。3. Configure 到 nmake installx64 与 x86 双架构完整编译流程3.1 Configure 参数逐一拆解别再把两个架构名记反OpenSSL 在 Windows 上编译的标准流程是perl Configure 目标平台 --prefix安装目录 --openssldir配置目录 nmake nmake install其中目标平台参数最关键也是最容易混淆的编 x64用VC-WIN64A。WIN64 很好理解指 64 位 WindowsA 指 x86_64 架构也就是 AMD64 / Intel 64。这里要注意x86_64 架构的缩写是 A不是因为 64 位必须叫 A而是 OpenSSL 官方 target 里用它代表 AMD64 体系。编 x8632 位用VC-WIN32。这里的 WIN32 指 Win32 API 程序目标芯片架构是 x86不是说只能跑在 32 位系统上。64 位 Windows 完全能运行 32 位程序。如果你选反了把VC-WIN32用在 x64 Native Tools 里或者把VC-WIN64A用在 x86 Native Tools 里后面 nmake 阶段大概率会报汇编源文件格式不匹配的错误。--prefix 是安装根目录。install 之后头文件、库文件、工具都会按标准目录结构放在这个目录下非常干净。--openssldir 是 OpenSSL 运行时找配置文件、默认证书的目录我一般用 prefix 下的 ssl 子目录这样的路径结构最直观。有一点需要说明OpenSSL 1.1.1w 的 Configure 对参数的容错性有限参数写错了不会自动帮你纠正而是直接生成一份不正确的 makefile。所以输入命令时一定要仔细尤其是这几个参数。3.2 x64 编译完整步骤以我本机为例源码解压在D:\thirdparty\openssl-1.1.1w目标安装到D:\thirdparty\openssl\x64。先打开“x64 Native Tools Command Prompt for VS 2022”然后依次执行cd /d D:\thirdparty\openssl-1.1.1w perl Configure VC-WIN64A --prefixD:\thirdparty\openssl\x64 --openssldirD:\thirdparty\openssl\x64\ssl nmake nmake install第一步cd进源码目录第二步 Configure 生成 makefile 和必要的头文件第三步 nmake 开始实际编译1.1.1w 全量编译在我的机器上大概需要几分钟到十几分钟取决于 CPU 性能第四步 nmake install 把所有产物复制到D:\thirdparty\openssl\x64目录下。nmake 过程中如果报错不要慌先看错误信息最后几行绝大多数 Windows 下编译失败的原因集中在三处没有加载 VS 环境、找不到 perl/nasm、源码目录路径含中文或空格。路径含空格的问题尤其阴险Configure 可能不直接报错但 nmake 会在某个环节因为路径解析错误而失败所以我上面示例里的路径故意都用纯英文无空格。3.3 x86 编译另一个架构源码树必须隔离x86 的编译流程和 x64 几乎一样但有一个最重要的区别源码目录必须和 x64 那份分开。我建议你重新解压一份源码放到类似D:\thirdparty\openssl-1.1.1w-x86的目录。然后打开“x86 Native Tools Command Prompt for VS 2022”执行cd /d D:\thirdparty\openssl-1.1.1w-x86 perl Configure VC-WIN32 --prefixD:\thirdparty\openssl\x86 --openssldirD:\thirdparty\openssl\x86\ssl nmake nmake install为什么要隔离目录我用一个真实的教训说明有一次我偷懒在同一份源码树里编完 x64 后直接nmake clean再 Configure 成 VC-WIN32编完后把库发给同事他拿去在 32 位工程里链接编译倒是过了跑起来却报内存访问异常。后来我查了两个多小时发现问题是 Configure 虽然生成了新的 makefile但源码目录里一些自动生成的头文件还带着 x64 的配置残留导致部分代码按 64 位路径编译最终产出了一个不伦不类的东西。从那以后我再也不在同一个源码树里交叉编译两个架构了。多解压一份源码也就占几十 MB 磁盘换来的是一份放心。3.4 编译产物清单你最终拿到哪些文件分别干什么用install 完成之后产物目录结构大致是这样的bin目录openssl.exe 命令行工具以及动态库方案下的 DLL 文件include\openssl目录所有头文件编译自己程序时要用lib目录导入库/静态库文件ssl目录openssl.cnf 默认配置目录。库文件的命名有一个很容易踩坑的地方我列个表文件x64 动态库方案x86 动态库方案静态库方案两架构通用规律DLLlibssl-1_1-x64.dll、libcrypto-1_1-x64.dlllibssl-1_1.dll、libcrypto-1_1.dll无 DLL链接用的库libssl.lib、libcrypto.liblibssl.lib、libcrypto.liblibssl_static.lib、libcrypto_static.lib头文件include\openssl*.hinclude\openssl*.h相同注意看表格里的两个细节。第一动态库方案里x64 的 DLL 名字带-x64后缀x86 的 DLL 名字不带你拿到一个libssl-1_1.dll要知道这是 32 位的不能拿去给 x64 程序用。第二即使你编译的是动态库方案lib 目录下也会同时产出静态库文件libssl_static.lib、libcrypto_static.lib。所以接入项目时选哪一个必须想清楚链接错了导入库运行时会出各种匪夷所思的问题。4. 接进 VS 工程附加目录、库名、运行库和 DLL 分发4.1 最小配置三步走OpenSSL 库编好之后接入自己的 VS 工程只需要在项目属性页配三处。第一处C/C - 常规 - 附加包含目录填D:\thirdparty\openssl\x64\include。第二处链接器 - 常规 - 附加库目录填D:\thirdparty\openssl\x64\lib。第三处链接器 - 输入 - 附加依赖项填libssl.lib;libcrypto.lib。这三处填好之后代码里#include openssl/ssl.h就能找到头文件SSL 相关的函数也能链接上。如果只配了头文件目录但没配附加依赖项或者库名写错会在链接阶段报LNK2019 unresolved external symbol。这种报错几乎都是附加依赖项的问题优先排查这里。另外注意 x86 工程要指向D:\thirdparty\openssl\x86那套目录而不是 x64 的这一步很容易在交接时搞混建议在工程备注里写上用的是哪个架构的库。4.2 静态版连接的一个隐藏条件OPENSSL_STATIC用静态库libssl_static.lib和libcrypto_static.lib时有一个条件非常容易被忽略我在这里单独拿出来讲除了附加依赖项改成这两个名字外还要在C/C - 预处理器 - 预处理器定义里添加OPENSSL_STATIC。原因是 OpenSSL 的头文件里针对 Windows 动态链接场景默认加了dllimport导出声明。静态链接时不加这个宏头文件声明和实际链接方式会对不上轻则编译器按 dllimport 生成低效代码重则链接时报错。这个问题藏得很深因为它的报错信息不一定直接提到 OpenSSL更多时候表现为某个莫名其妙的 unresolved external排查起来相当费时间。动态库方案不需要这个宏。所以你在网上搜到有人说“加 OPENSSL_STATIC”有人说“不加”其实都对关键看你是静态链接还是动态链接。4.3 /MT 和 /MDOpenSSL 库跟你的项目“血型不合”怎么办MSVC 的运行时库分动态/MD和静态/MT两种形态。OpenSSL 在 Windows 上用 nmake 编译时默认走的是 /MD也就是动态 CRT和 VS 默认新建项目的运行时库一致。所以大多数人编译完直接接入默认工程不会觉得有什么问题。但如果你因为某些原因把项目改成了 /MT比如希望程序不依赖 VCRUNTIME140.dll链接时就会见到LNK2038这类运行时库不匹配的报错。解决办法是让 OpenSSL 也改成 /MT 编译流程如下编译完 OpenSSL已经执行过 Configure 和 nmake后用文本编辑器打开源码目录下生成的 makefile把CFLAG里所有的/MD替换成/MT然后执行nmake clean再重新nmake最后再nmake install。这个操作我只建议在确实需要静态 CRT 时才做。如果你只是默认工程保持 OpenSSL 默认的 /MD 即可。改 makefile 的时候注意你是 x64 的源码树就改 x64 那份x86 的源码树就改 x86 那份别改串了。4.4 用生成后事件自动把 DLL 送到 exe 旁边动态库方案下程序运行时必须在 exe 能搜索到的位置找到 DLL。开发调试阶段最省心的办法是在 VS 的生成事件 - 生成后事件命令行里加两行 copycopy /Y D:\thirdparty\openssl\x64\bin\libssl-1_1-x64.dll $(OutDir) copy /Y D:\thirdparty\openssl\x64\bin\libcrypto-1_1-x64.dll $(OutDir)这样每次编译完成后 DLL 都会自动拷贝到输出目录不用每次都手动去 bin 目录里翻。注意 DLL 文件名要和你实际编译的产品一致x64 是-1_1-x64后缀x86 没有 x64 后缀。文件名里的-1_1是 1.1.x 系列的标记不是随便起的。5. 最容易翻车的运行时问题版本不匹配和证书验证5.1 version mismatch 到底在报什么文章开头那个openssl version mismatch. built against 30000070, you have 30500050就是典型的运行时版本不一致。这里30000070和30500050是 OpenSSL 版本号的内部数字编码前一段built against表示程序编译时用的头文件版本后一段you have表示程序运行时实际加载到的 DLL 版本。1.1.1 和 3.x 之间的 ABI 差异很大头文件里结构体布局、导出函数签名都有变化加载错版本轻则警告重则崩溃。我见过最隐蔽的情况是程序自己目录里放了正确的 1.1.1w DLL但客户机器上另一个软件把它的 OpenSSL DLL 装到了 System32 目录由于 DLL 搜索顺序问题exe 优先加载了系统目录里的错误版本。排查思路其实不复杂用dumpbin /dependents your.exe看 exe 依赖的 DLL 文件名再用工具确认运行时实际加载的 DLL 路径确保 exe 同目录下的 DLL 和编译时用的头文件是同一个版本。这个问题的根源就是“不可控的依赖来源”这也是我一直强调自己从源码编一份、随程序分发的原因每次都要确认 exe 目录下的 DLL 和编译时的头文件同源。5.2 运行目录里的 DLL 和头文件版本必须同源把版本不匹配再往前推一步哪怕都是 1.1.1也要尽可能保持同一个编译来源。如果头文件、导入库、DLL 分别来自不同机器、不同时间编译的 1.1.1 小版本大多数情况下能跑但这种不一致会在将来某次替换 DLL 或切换机器时埋雷。我的习惯是把 install 之后的整个目录include、lib、bin、ssl打成一个压缩包按openssl-1.1.1w-win-x64.zip、openssl-1.1.1w-win-x86.zip这种规则命名归档。项目里引用哪个压缩包就记录到项目说明里。之后同事接手或者 CI 构建机要重建环境直接解压同一个包出来的产物必然是一致的。这套做法成本极低但能省掉很多未来对版本的扯皮。5.3 顺手用好 openssl verify -CAfile编出 openssl.exe 之后除了加解密、生成密钥最常用的场景就是证书验证。排查证书链问题时一个高频率命令是openssl verify -CAfile ca.pem server.pem-CAfile指定你信任的根证书/CA 证书集合server.pem是待验证的服务器证书。这个命令会告诉你证书链是否完整、证书是否过期、CA 是否匹配。1.1.1w 和 3.x 的 verify 参数基本一致但证书链校验的严格程度略有差异3.x 默认更挑剔。如果你在 3.x 下验证不通过的证书在 1.1.1 下可能能过反过来也成立。遇到这种跨版本验证行为差异优先确认目标服务端实际支持的 OpenSSL 行为再据此决定证书链怎么补全不要盲目判断“哪一边是对的”。我在实际项目里的做法是x64 动态库给主程序用x86 静态库给一个 32 位辅助工具用。编译本身不复杂环境对了、Configure 目标没选错、源码树隔离清楚基本一次能过。真正容易卡人的是后面接入阶段的细枝末节——链接了错误的导入库、忘了 OPENSSL_STATIC、运行库血型不合、DLL 被系统目录里的同名文件覆盖。如果你正打算在 Windows 上把 OpenSSL 1.1.1w 编进自己的程序按照这篇的顺序走一遍应该能少走不少弯路。最后再分享一个小习惯不要把编译出来的整个 install 目录随便乱扔每个版本、每个架构打一个带版本号的压缩包归档几个月后你会感谢当初这个决定。本文还有配套的精品资源点击获取