准备工作
OpenSSL 源码(使用的 1.1.1k 版本)下载地址:链接
Perl for MS Windows 下载地址:链接
VS2019,自己找吧
nasm 下载地址:链接
安装编译环境
当前使用的Windows 10 x64版本,所以编译环境也都选择了x64的版本。32位的版本没做测试。
安装VS2019
步骤略。
安装 Perl
下载并运行安装包后,一路下一步,安装完成后,打开cmd
,输入perl -V
,确认是否安装成功。安装成功会输出下列信息:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| Microsoft Windows [版本 10.0.19042.928] (c) Microsoft Corporation。保留所有权利。
C:\Users\Admin>perl -V Summary of my perl5 (revision 5 version 32 subversion 1) configuration:
Platform: osname=MSWin32 osvers=10.0.19042.746 archname=MSWin32-x64-multi-thread // 省略 Built under MSWin32 Compiled at Jan 24 2021 15:05:42 @INC: C:/Strawberry/perl/site/lib C:/Strawberry/perl/vendor/lib C:/Strawberry/perl/lib
|
如果没有成功,检查系统环境变量path
是否存在下面的路径:
1 2 3
| C:\Strawberry\c\bin; C:\Strawberry\perl\site\bin; C:\Strawberry\perl\bin;
|
根据真实环境补全 perl 的所在目录。
安装 nasm
下载并运行安装包后,一路下一步,安装完成后,打开cmd
,输入nasm -v
,确认是否安装成功。安装成功会输出下列信息:
1 2 3 4 5
| Microsoft Windows [版本 10.0.19042.928] (c) Microsoft Corporation。保留所有权利。
C:\Users\Admin>nasm -v NASM version 2.15.05 compiled on Aug 28 2020
|
如果没有成功,检查系统环境变量path
是否存在下面的路径:
根据真实环境补全 nasm 的所在目录。
编译步骤
这里以编译x64版本的OpenSSL为例。
步骤1 启动编译环境
在开始菜单中找到Visual Studio 2019
目录中的x86_x64 Cross Tools Command Prompt for VS 2019
,以管理员身份运行;
cd
进入OpenSSL
源码的根目录:
1 2 3 4 5 6 7 8 9
| ********************************************************************** ** Visual Studio 2019 Developer Command Prompt v16.9.4 ** Copyright (c) 2021 Microsoft Corporation ********************************************************************** [vcvarsall.bat] Environment initialized for: 'x86_x64'
C:\Windows\System32>cd C:\Users\Admin\source\openssl-OpenSSL_1_1_1k
C:\Users\Admin\source\openssl-OpenSSL_1_1_1k>
|
步骤2 生成编译配置文件
运行命令perl Configure VC-WIN64A
,生成编译配置文件,成功后输出信息如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| C:\Users\Admin\source\openssl-OpenSSL_1_1_1k>perl Configure VC-WIN64A Configuring OpenSSL version 1.1.1k (0x101010bfL) for VC-WIN64A Using os-specific seed configuration Creating configdata.pm Creating makefile
********************************************************************** *** *** *** OpenSSL has been successfully configured *** *** *** *** If you encounter a problem while building, please open an *** *** issue on GitHub <https://github.com/openssl/openssl/issues> *** *** and include the output from the following command: *** *** *** *** perl configdata.pm --dump *** *** *** *** (If you are new to OpenSSL, you might want to consult the *** *** 'Troubleshooting' section in the INSTALL file first) *** *** *** **********************************************************************
C:\Users\Admin\source\openssl-OpenSSL_1_1_1k>
|
步骤3 开始编译
运行命令nmake
,开始编译,编译时间大约10分钟,成功后输出信息如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| cl /Zi /Fdapp.pdb /Gs0 /GF /Gy /MD /W3 /wd4090 /nologo /O2 /I "include" -D"OPENSSL_SYS_WIN32" -D"WIN32_LEAN_AND_MEAN" -D"UNICODE" -D"_UNICODE" -D"_CRT_SECURE_NO_DEPRECATE" -D"_WINSOCK_DEPRECATED_NO_WARNINGS" -D"OPENSSL_USE_APPLINK" -D"NDEBUG" /Zs /showIncludes "test\x509_time_test.c" 2>&1 > test\x509_time_test.d IF EXIST test\x509_time_test.exe.manifest DEL /F /Q test\x509_time_test.exe.manifest link /nologo /debug /subsystem:console /opt:ref /nologo /debug /out:test\x509_time_test.exe @C:\Users\Admin\AppData\Local\Temp\nmC906.tmp IF EXIST test\x509_time_test.exe.manifest mt -nologo -manifest test\x509_time_test.exe.manifest -outputresource:test\x509_time_test.exe cl /Zi /Fdapp.pdb /Gs0 /GF /Gy /MD /W3 /wd4090 /nologo /O2 /I "include" -D"OPENSSL_SYS_WIN32" -D"WIN32_LEAN_AND_MEAN" -D"UNICODE" -D"_UNICODE" -D"_CRT_SECURE_NO_DEPRECATE" -D"_WINSOCK_DEPRECATED_NO_WARNINGS" -D"OPENSSL_USE_APPLINK" -D"NDEBUG" -c /Fotest\x509aux.obj "test\x509aux.c" x509aux.c cl /Zi /Fdapp.pdb /Gs0 /GF /Gy /MD /W3 /wd4090 /nologo /O2 /I "include" -D"OPENSSL_SYS_WIN32" -D"WIN32_LEAN_AND_MEAN" -D"UNICODE" -D"_UNICODE" -D"_CRT_SECURE_NO_DEPRECATE" -D"_WINSOCK_DEPRECATED_NO_WARNINGS" -D"OPENSSL_USE_APPLINK" -D"NDEBUG" /Zs /showIncludes "test\x509aux.c" 2>&1 > test\x509aux.d IF EXIST test\x509aux.exe.manifest DEL /F /Q test\x509aux.exe.manifest link /nologo /debug /subsystem:console /opt:ref /nologo /debug /out:test\x509aux.exe @C:\Users\Admin\AppData\Local\Temp\nmCACC.tmp IF EXIST test\x509aux.exe.manifest mt -nologo -manifest test\x509aux.exe.manifest -outputresource:test\x509aux.exe "C:\Strawberry\perl\bin\perl.exe" "-I." -Mconfigdata "util\dofile.pl" "-omakefile" "apps\CA.pl.in" > "apps\CA.pl" "C:\Strawberry\perl\bin\perl.exe" "-I." -Mconfigdata "util\dofile.pl" "-omakefile" "apps\tsget.in" > "apps\tsget.pl" "C:\Strawberry\perl\bin\perl.exe" "-I." -Mconfigdata "util\dofile.pl" "-omakefile" "tools\c_rehash.in" > "tools\c_rehash.pl"
C:\Users\Admin\source\openssl-OpenSSL_1_1_1k>
|
步骤4 测试编译结果
运行命令nmake test
,测试编译结果,耗时大约10分钟,成功后输出信息如下:
1 2 3 4 5 6 7
| test\recipes\99-test_ecstress.t ................. ok test\recipes\99-test_fuzz.t ..................... ok All tests successful. Files=158, Tests=2545, 451 wallclock secs ( 1.86 usr + 0.50 sys = 2.36 CPU) Result: PASS
C:\Users\Admin\source\openssl-OpenSSL_1_1_1k>
|
步骤5 安装
运行命令nmake install
,安装文件,x64
版本默认安装到C:\Program Files\OpenSSL
,x86
版本默认安装到C:\Program Files (x86)\OpenSSL
,耗时大约3分钟,成功后输出信息如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| C:\Program Files\OpenSSL\html\man7\bio.html C:\Program Files\OpenSSL\html\man7\crypto.html C:\Program Files\OpenSSL\html\man7\ct.html C:\Program Files\OpenSSL\html\man7\des_modes.html C:\Program Files\OpenSSL\html\man7\Ed25519.html C:\Program Files\OpenSSL\html\man7\Ed448.html -> C:\Program Files\OpenSSL\html\man7\Ed25519.html C:\Program Files\OpenSSL\html\man7\evp.html C:\Program Files\OpenSSL\html\man7\ossl_store-file.html C:\Program Files\OpenSSL\html\man7\ossl_store.html C:\Program Files\OpenSSL\html\man7\passphrase-encoding.html C:\Program Files\OpenSSL\html\man7\proxy-certificates.html C:\Program Files\OpenSSL\html\man7\RAND.html C:\Program Files\OpenSSL\html\man7\RAND_DRBG.html C:\Program Files\OpenSSL\html\man7\RSA-PSS.html C:\Program Files\OpenSSL\html\man7\scrypt.html C:\Program Files\OpenSSL\html\man7\SM2.html C:\Program Files\OpenSSL\html\man7\ssl.html C:\Program Files\OpenSSL\html\man7\X25519.html C:\Program Files\OpenSSL\html\man7\X448.html -> C:\Program Files\OpenSSL\html\man7\X25519.html C:\Program Files\OpenSSL\html\man7\x509.html
C:\Users\Admin\source\openssl-OpenSSL_1_1_1k>
|
编译多个版本
如果还需要编译其它版本,例如要编译x86
版本,需要以管理员身份运行 x86 版本的VS2019的命令行工具x86 Native Tools Command Prompt for VS 2019
,进入源码目录后,先执行清理命令,然后修改配置信息:
1 2
| nmake clean perl Configure VC-WIN32
|
接下来从步骤3 开始编译
再来一遍。
使用 OpenSSL
测试代码
以计算MD5为例。
将安装后的C:\Program Files\OpenSSL\include
和C:\Program Files\OpenSSL\lib
添加到工程中:
代码中要根据实际情况使用头文件.h
、静态库.lib
、动态库.dll
,这里只用到了#include <openssl\md5.h>
、#pragma comment(lib, "libcrypto.lib")
、libcrypto-1_1-x64.dll
。
测试代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| #include <stdio.h> #include <openssl\md5.h>
#pragma comment(lib, "libcrypto.lib")
int main() { unsigned char szBuf[6] = {'1', '2', '3', '4', '5', '6'}; unsigned char md[MD5_DIGEST_LENGTH] = {0}; MD5(szBuf, sizeof(szBuf), md);
for (int i = 0; i < MD5_DIGEST_LENGTH; i++) { printf_s("%02x", md[i]); } printf_s("\n"); }
|
输出结果e10adc3949ba59abbe56e057f20f883e
。
可能遇到的问题
检查对应版本的dll是否放到程序目录或者系统目录。
报错详情:
1 2 3 4 5 6 7 8
| 已启动生成… 1>------ 已启动生成: 项目: test_openssl, 配置: Debug x64 ------ 1>test_openssl.cpp 1>C:\Users\Admin\source\test_openssl\test_openssl.cpp(6,22): error C2065: “MD5_DIGEST_LENGTH”: 未声明的标识符 1>C:\Users\Admin\source\test_openssl\test_openssl.cpp(7,5): error C3861: “MD5”: 找不到标识符 1>C:\Users\Admin\source\test_openssl\test_openssl.cpp(9,25): error C2065: “MD5_DIGEST_LENGTH”: 未声明的标识符 1>已完成生成项目“test_openssl.vcxproj”的操作 - 失败。 ========== 生成: 成功 0 个,失败 1 个,最新 0 个,跳过 0 个 ==========
|
检查代码是否引入头文件#include <openssl\md5.h>
。
报错详情:
1 2 3 4 5 6 7
| 已启动生成… 1>------ 已启动生成: 项目: test_openssl, 配置: Debug x64 ------ 1>test_openssl.cpp 1>test_openssl.obj : error LNK2019: 无法解析的外部符号 MD5,函数 main 中引用了该符号 1>C:\Users\Admin\source\test_openssl\x64\Debug\test_openssl.exe : fatal error LNK1120: 1 个无法解析的外部命令 1>已完成生成项目“test_openssl.vcxproj”的操作 - 失败。 ========== 生成: 成功 0 个,失败 1 个,最新 0 个,跳过 0 个 ==========
|
检查代码是否有#pragma comment(lib, "libcrypto.lib")
。
1 2 3 4 5 6 7
| 已启动生成… 1>------ 已启动生成: 项目: test_openssl, 配置: Debug Win32 ------ 1>test_openssl.cpp 1>test_openssl.obj : error LNK2019: 无法解析的外部符号 _MD5@12,函数 _main 中引用了该符号 1>C:\Users\Admin\source\test_openssl\Debug\test_openssl.exe : fatal error LNK1120: 1 个无法解析的外部命令 1>已完成生成项目“test_openssl.vcxproj”的操作 - 失败。 ========== 生成: 成功 0 个,失败 1 个,最新 0 个,跳过 0 个 ==========
|
这个问题只出现在32位环境,和上面的无法解析的外部符号xxx
报错信息很像,但是函数名前后多了_
和@数字
字样,原因是代码工程使用了标准调用约定,
使用__stdcall
,函数在obj 中显示为_funname@参数总字节数
,用于函数本身平衡栈空间。
检查工程属性页的配置属性 -- C/C++ -- 高级 -- 调用约定
,是否为C调用约定_cdecl
,OpenSSL 默认使用C调用约定:
参考资料
- OpenSSL的 README.md
- OpenSSL源码目录中的
INSTALL
文件