OpenSSL源码编译安装

  • 一、OpenSSL在Linux平台的编译
  • 打包环境
  • 源码准备
  • 编译安装
  • 二、OpenSSL在Windows平台的编译
  • 打包环境
  • 编译32位库
  • 编译64位库
  • 错误处理
  • 编译低版本OpenSSL
  • 三、OpenSSL在Android平台的编译
  • 打包环境
  • 配置环境变量
  • 源码准备
  • 创建编译脚本
  • 执行编译脚本
  • 四、OpenSSL在Mac平台的编译
  • 打包环境
  • 源码准备
  • 执行编译
  • 五、OpenSSL在iOS平台的编译
  • 打包环境
  • 源码准备
  • 创建编译脚本
  • 执行编译脚本



无论在什么平台,OpenSSL的编译一般需要经过三个步骤:

  1. 使用Configure批处理,根据平台环境、选用的编译器及其他参数设置编译的环境变量。
  2. 通过使用批处理指令来根据上面设置好的环境变量生成编译脚本文件。
  3. 使用特定的编译指令进行编译链接。

本文将介绍OpenSSL在Linux、Windows、Android、Mac和iOS平台的编译方式。

一、OpenSSL在Linux平台的编译

打包环境

java 使用openssl生成的pem证书 openssl jar_android


需要安装perl、make和gcc。

源码准备

java 使用openssl生成的pem证书 openssl jar_Desktop_02


java 使用openssl生成的pem证书 openssl jar_网络安全_03

编译安装

  1. 执行config
./config --prefix=/home/workspace/openssl/output/64

java 使用openssl生成的pem证书 openssl jar_openssl_04

./config -t

java 使用openssl生成的pem证书 openssl jar_网络安全_05

  1. 执行make
make

java 使用openssl生成的pem证书 openssl jar_网络安全_06


执行结果:

java 使用openssl生成的pem证书 openssl jar_Desktop_07

  1. 执行make test
make test

java 使用openssl生成的pem证书 openssl jar_openssl_08


执行结果:

java 使用openssl生成的pem证书 openssl jar_网络安全_09

  1. 执行make install
make install

java 使用openssl生成的pem证书 openssl jar_openssl_10


执行完成后,编译生成的文件将会放到/home/workspace/openssl/output/64目录下:

java 使用openssl生成的pem证书 openssl jar_perl_11

二、OpenSSL在Windows平台的编译

打包环境

java 使用openssl生成的pem证书 openssl jar_openssl_12


编译工具:Visual Studio 2019

java 使用openssl生成的pem证书 openssl jar_android_13


INSTALL文件说明了OpenSSL在Windows编译的方式:

java 使用openssl生成的pem证书 openssl jar_android_14


NOTES.WIN文件说明了编译需要的额外依赖工具,我们需要下载安装这些工具,并配置环境变量:

java 使用openssl生成的pem证书 openssl jar_Desktop_15


java 使用openssl生成的pem证书 openssl jar_网络安全_16

编译32位库

  1. 打开[x86 Native Tools Command Prompt for VS 2019]:【开始】-【所有程序】—【Microsoft visual studio2019】—【x86 Native Tools Command prompt for VS 2019】(以管理员身份运行)
  2. 切换到OpenSSL源码目录
  3. 执行编译
#第一步
#若需要编译静态库需要增加no-shared参数,否则默认生成动态库
#perl Configure VC-WIN32 no-shared --prefix=C:\Users\Username\Desktop\openssl\output\32
perl Configure VC-WIN32 --prefix=C:\Users\Username\Desktop\openssl\output\32
#第二步
nmake 
#第三步
nmake test
#第四步
nmake install

编译完成的目标文件:

java 使用openssl生成的pem证书 openssl jar_perl_17

编译64位库

  1. 打开[x64 Native Tools Command Prompt for VS 2019]:【开始】-【所有程序】—【Microsoft visual studio2019】—【x64 Native Tools Command Prompt for VS 2019】(以管理员身份运行)
  2. 切换到OpenSSl源码目录
  3. 执行编译
#第一步
#若需要编译静态库需要增加no-shared参数,否则默认生成动态库
#perl Configure VC-WIN64A no-shared --prefix=C:\Users\Username\Desktop\openssl\output\64
perl Configure VC-WIN64A --prefix=C:\Users\Username\Desktop\openssl\output\64
#第二步
nmake 
#第三步
nmake test
#第四步
nmake install

编译完成的目标文件:

java 使用openssl生成的pem证书 openssl jar_perl_18

错误处理

注意:若在执行perl Configure VC-WIN32 --prefix=C:\Users\Username\Desktop\openssl\output\32或perl Configure VC-WIN64A --prefix=C:\Users\Username\Desktop\openssl\output\64时出现下列错误

It looks like you don't have either nmake.exe or dmake.exe on your PATH,
so you will not be able to execute the commands from a Makefile.  You can
install dmake.exe with the Perl Package Manager by running:

    ppm install dmake

java 使用openssl生成的pem证书 openssl jar_Desktop_19


执行:

ppm install dmake

若执行ppm install dmake还出现下面的错误:

ppm install failed: DBD::SQLite::db selectrow_array failed: database disk image is malformed

java 使用openssl生成的pem证书 openssl jar_perl_20


删除C:\Users\FengGuodong\AppData\Local\ActiveState\ActivePerl目录下的文件:

java 使用openssl生成的pem证书 openssl jar_openssl_21


重新执行:

ppm install dmake

等待下载安装完成。

java 使用openssl生成的pem证书 openssl jar_perl_22


dmake安装完成后,重新开始编译:

#第一步
#编译32位库
#若需要编译静态库需要增加no-shared参数,否则默认生成动态库
#perl Configure VC-WIN32 no-shared --prefix=C:\Users\Username\Desktop\openssl\output\32
perl Configure VC-WIN32 --prefix=C:\Users\Username\Desktop\openssl\output\32

#编译64位库
#若需要编译静态库需要增加no-shared参数,否则默认生成动态库
#perl Configure VC-WIN64A no-shared --prefix=C:\Users\Username\Desktop\openssl\output\64
#perl Configure VC-WIN64A --prefix=C:\Users\Username\Desktop\openssl\output\64

#第二步
nmake 
#第三步
nmake test
#第四步
nmake install

编译低版本OpenSSL

OpenSSL1.0及其以下的版本,编译过程可能略有差别:

# 编译32位动态库
perl Configure VC-WIN32 --prefix=C:\Users\Username\Desktop\openssl\output\32
ms\do_ms.bat
# 可以修改ntdll.mak的CFLAG属性为MT或MD
nmake -f ms\ntdll.mak
nmake -f ms\ntdll.mak clean
#编译64位动态库
perl Configure VC-WIN64A --prefix=C:\Users\Username\Desktop\openssl\output\64
ms\do_win64a.bat
# 可以修改ntdll.mak的CFLAG属性为MT或MD
nmake -f ms\ntdll.mak
nmake -f ms\ntdll.mak clean
# 编译32位静态库
perl Configure VC-WIN32 --prefix=C:\Users\Username\Desktop\openssl\output\32
ms\do_ms.bat
# 可以修改nt.mak的CFLAG属性为MT或MD
nmake -f ms\nt.mak
nmake -f ms\nt.makk clean
#编译64位静态库
perl Configure VC-WIN64A --prefix=C:\Users\Username\Desktop\openssl\output\64
ms\do_win64a.bat
# 可以修改nt.mak的CFLAG属性为MT或MD
nmake -f ms\nt.mak
nmake -f ms\nt.makk clean

三、OpenSSL在Android平台的编译

打包环境

java 使用openssl生成的pem证书 openssl jar_android


NOTES.ANDROID文件说明了在Linux系统环境交叉编译Android库的方式,我们需要安装和配置NDK。

java 使用openssl生成的pem证书 openssl jar_Desktop_24


我们将android-ndk-r20b安装在/usr/local/BUILD目录下,那么ndk的编译工具链在目录/usr/local/BUILD/android-ndk-r20b/toolchains下:

java 使用openssl生成的pem证书 openssl jar_perl_25


NDK必须依赖JDK,Linux环境下搭建Android NDK交叉编译环境请参考《Linux系统Android NDK编译环境搭建》

配置环境变量

export JAVA_HOME=/usr/local/BUILD/jdk1.8.0_181
 export JRE_HOME=${JAVA_HOME}/jre
 export ANDROID_NDK=/usr/local/BUILD/android-ndk-r20b
 export PATH=${JAVA_HOME}/bin:${ANDROID_NDK}:${PATH}

java 使用openssl生成的pem证书 openssl jar_openssl_26

源码准备

java 使用openssl生成的pem证书 openssl jar_Desktop_02


java 使用openssl生成的pem证书 openssl jar_网络安全_03

创建编译脚本

在OpenSSL源码目录下创建build.sh,脚本内容如下:

#!/bin/bash
set -e
set -x

# Android NDK r17之后不支持使用gcc,需要使用clang编译,若不配置使用clang会提示找不到android-gcc命令
CC=clang
# OpenSSL源码目录
OPENSSL_PATH=/home/workspace/openssl/openssl-1.1.1b

func_cmp() {
	make clean &&
	rm -rf $OPENSSL_PATH/output/$ARCH &&
	mkdir -p $OPENSSL_PATH/output/$ARCH &&
	export PATH=$ANDROID_NDK/toolchains/llvm/prebuilt/linux-x86_64/bin:$PATH &&
	./Configure $ARCH_NAME -D__ANDROID_API__=21 --prefix=$OPENSSL_PATH/output/$ARCH &&
	make && make install
}

ARCH_NAME=android-arm
export PATH=$ANDROID_NDK/toolchains/llvm/prebuilt/linux-x86_64/bin:$PATH &&
./Configure $ARCH_NAME -D__ANDROID_API__=21 --prefix=$OPENSSL_PATH/output/$ARCH

#for ARCH in armeabi-v7a armeabi arm64-v8a x86 x86_64 mips mips64
for ARCH in armeabi-v7a armeabi arm64-v8a x86 x86_64
do
	echo $ARCH

	if [ "$ARCH" = "armeabi-v7a" ]; then
		ARCH_NAME=android-arm
	fi

	if [ "$ARCH" = "armeabi" ]; then
		ARCH_NAME=android-arm
	fi

	if [ "$ARCH" = "arm64-v8a" ]; then
		ARCH_NAME=android-arm64
	fi

	if [ "$ARCH" = "mips" ]; then
		ARCH_NAME=android-mips
	fi

	if [ "$ARCH" = "mips64" ]; then
		ARCH_NAME=android-mips64
	fi

	if [ "$ARCH" = "x86" ]; then
		ARCH_NAME=android-x86
	fi

	if [ "$ARCH" = "x86_64" ]; then
		ARCH_NAME=android-x86_64
	fi

	echo $TOOL_CHAIN
	func_cmp
done

执行编译脚本

java 使用openssl生成的pem证书 openssl jar_Desktop_29


等待编译完成,在目录/home/workspace/openssl/openssl-1.1.1b/output下可以找到编译好的目标文件:

java 使用openssl生成的pem证书 openssl jar_android_30


java 使用openssl生成的pem证书 openssl jar_openssl_31

四、OpenSSL在Mac平台的编译

打包环境

java 使用openssl生成的pem证书 openssl jar_perl_32

源码准备

java 使用openssl生成的pem证书 openssl jar_openssl_33


解压后:

java 使用openssl生成的pem证书 openssl jar_openssl_34

执行编译

#第一步
./config --prefix=/Users/ft/Desktop/openssl/openssl-1.1.1b/output
#若需要编译32位的库,需要添加参数KERNEL_BITS=32
#KERNEL_BITS=32 ./config --prefix=/Users/ft/Desktop/openssl/openssl-1.1.1b/output
#第二步
make
#第三步
make test
#第四步
make install

编译生成目标文件:

java 使用openssl生成的pem证书 openssl jar_perl_35

五、OpenSSL在iOS平台的编译

打包环境

java 使用openssl生成的pem证书 openssl jar_openssl_36

源码准备

java 使用openssl生成的pem证书 openssl jar_openssl_33


解压后:

java 使用openssl生成的pem证书 openssl jar_openssl_34

创建编译脚本

#!/bin/bash

set -u

OPENSSL_SRC_DIR=${PWD}
OPENSSL_BUILD_DIR=${OPENSSL_SRC_DIR}/output
OPENSSL_BUILD_LOG_DIR=${OPENSSL_BUILD_DIR}/log
OPENSSL_BUILD_UNIVERSAL_DIR=${OPENSSL_BUILD_DIR}/universal
OPENSSL_UNIVERSAL_LIB_DIR=${OPENSSL_BUILD_UNIVERSAL_DIR}/lib

rm -rf ${OPENSSL_BUILD_DIR}

mkdir ${OPENSSL_BUILD_DIR}
mkdir -p ${OPENSSL_BUILD_LOG_DIR}
mkdir -p ${OPENSSL_BUILD_UNIVERSAL_DIR}
mkdir -p ${OPENSSL_UNIVERSAL_LIB_DIR}

CLANG=$(xcrun --find clang)

IPHONE_OS_SDK_PATH=$(xcrun -sdk iphoneos --show-sdk-path)
IPHONE_OS_CROSS_TOP=${IPHONE_OS_SDK_PATH//\/SDKs*/}
IPHONE_OS_CROSS_SDK=${IPHONE_OS_SDK_PATH##*/}

IPHONE_SIMULATOR_SDK_PATH=$(xcrun -sdk iphonesimulator --show-sdk-path)
IPHONE_SIMULATOR_CROSS_TOP=${IPHONE_SIMULATOR_SDK_PATH//\/SDKs*/}
IPHONE_SIMULATOR_CROSS_SDK=${IPHONE_SIMULATOR_SDK_PATH##*/}

ARCH_LIST=("armv7" "armv7s" "arm64" "i386" "x86_64")
ARCH_COUNT=${#ARCH_LIST[@]}
CROSS_TOP_LIST=(${IPHONE_OS_CROSS_TOP} ${IPHONE_OS_CROSS_TOP} ${IPHONE_OS_CROSS_TOP} ${IPHONE_SIMULATOR_CROSS_TOP} ${IPHONE_SIMULATOR_CROSS_TOP})
CROSS_SDK_LIST=(${IPHONE_OS_CROSS_SDK} ${IPHONE_OS_CROSS_SDK} ${IPHONE_OS_CROSS_SDK} ${IPHONE_SIMULATOR_CROSS_SDK} ${IPHONE_SIMULATOR_CROSS_SDK})

config_make()
{
	ARCH=$1;
	export CROSS_TOP=$2
	export CROSS_SDK=$3
	# 启用bitcode
	export CC="${CLANG} -arch ${ARCH} -miphoneos-version-min=6.0 -fembed-bitcode"
	# 不启用bitcode
	#export CC="${CLANG} -arch ${ARCH} -miphoneos-version-min=6.0"

	make clean &> ${OPENSSL_BUILD_LOG_DIR}/make_clean.log

	echo "configure for ${ARCH}..."

	if [ "x86_64" == ${ARCH} ]; then
    	./Configure iphoneos-cross --prefix=${OPENSSL_BUILD_DIR}/${ARCH} no-asm &> ${OPENSSL_BUILD_LOG_DIR}/${ARCH}-conf.log
	else
    	./Configure iphoneos-cross --prefix=${OPENSSL_BUILD_DIR}/${ARCH} &> ${OPENSSL_BUILD_LOG_DIR}/${ARCH}-conf.log
	fi

	echo "build for ${ARCH}..."
	make &> ${OPENSSL_BUILD_LOG_DIR}/${ARCH}-make.log
	make install_sw &> ${OPENSSL_BUILD_LOG_DIR}/${ARCH}-make-install.log

	unset CC
	unset CROSS_SDK
	unset CROSS_TOP

	echo -e "\n"
}

for ((i=0; i < ${ARCH_COUNT}; i++))
do
	config_make ${ARCH_LIST[i]} ${CROSS_TOP_LIST[i]} ${CROSS_SDK_LIST[i]}
done

create_lib()
{
	LIB_SRC=lib/$1
	LIB_DST=${OPENSSL_UNIVERSAL_LIB_DIR}/$1
	LIB_PATHS=( ${ARCH_LIST[@]/#/${OPENSSL_BUILD_DIR}/} )
	LIB_PATHS=( ${LIB_PATHS[@]/%//${LIB_SRC}} )
	lipo ${LIB_PATHS[@]} -create -output ${LIB_DST}
}

create_lib "libssl.a"
create_lib "libcrypto.a"

cp -R ${OPENSSL_BUILD_DIR}/armv7/include ${OPENSSL_BUILD_UNIVERSAL_DIR}

echo "done."

执行编译脚本

将编译脚本build.sh拷贝到OpenSSL目录下,开始执行编译:

java 使用openssl生成的pem证书 openssl jar_网络安全_39


编译生成目标文件:

java 使用openssl生成的pem证书 openssl jar_android_40