编译需要在linux环境下进行,笔者使用的是vmware虚拟机安装ubuntu 20.04进行编译,虚拟机的安装和ubuntu的安装这里就不详细说明了,可自行百度。
vmware官网下载地址
ubuntu 20.04下载地址
openssl编译需要提前安装所需要的环境,这一点在openssl官网文档中有说明。Android编译说明openssl/NOTES-ANDROID.md at master · openssl/openssl · GitHub,下面直接给出需要安装的环境
sudo apt update
sudo apt upgrade
sudo apt install make
sudo apt install build-essential
sudo apt install perl
在编译前还需要下载Android NDK和openssl,下载然后解压。
wget https://www.openssl.org/source/openssl-3.0.5.tar.gz
tar -zxvf openssl-3.0.5.tar.gz
wget https://dl.google.com/android/repository/android-ndk-r22b-linux-x86_64.zip
unzip android-ndk-r22b-linux-x86_64.zip
编译openssl,此前笔者使用的是DNK-r20b编译的,开始在Android Studio上使用的是DNK 21版本进行开发,打包没出现问题,但后面升级到NDK 22+后出现无法打包的情况。 根据提示编译需要添加 -fPIC ,在此记录一下。
export ANDROID_NDK_ROOT=/home/wgc/Android/android-ndk-r22b
PATH=$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin:$ANDROID_NDK_ROOT/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin:$PATH
./Configure android-arm64 -D__ANDROID_API__=21 -static no-shared no-tests -fPIC --prefix=${OUTPUT_PATH}
make && make install
以上只是编译一个架构的静态库,如果需要其他架构还需重复编译,不够便捷,这里提供一个一键编译的版本。新建一个 build_openssl3.x.sh的文件,将以下内容复制到文件中,然后用命令执行 sh build_openssl3.x.sh即可。
#!/bin/bash -e
sudo apt update
sudo apt upgrade
sudo apt install make
sudo apt install build-essential
sudo apt install perl
#编译修改下面四个属性开始
OPENSSL_VERSION=3.0.5
#NDK23及以后下载和解压需要修改,注意下面注释掉的内容和说明
NDK_VERSION=android-ndk-r22b
ANDROID_TARGET_API=21
#需要编译的架构 如果执行报数组错误 请使用 sudo dpkg-reconfigure dash 出现画面选择 否
ANDROID_ABI_ARRAY=(armeabi armeabi-v7a arm64-v8a x86 x86_64) #所有架构(armeabi armeabi-v7a arm64-v8a x86 x86_64 mips mips64)
#编译修改下面四个属性结束
WORK_PATH=$(cd "$(dirname "$0")";pwd)
ANDROID_NDK_PATH=${WORK_PATH}/${NDK_VERSION}
OPENSSL_SOURCES_PATH=${WORK_PATH}/openssl-${OPENSSL_VERSION}
if [ ! -e openssl-${OPENSSL_VERSION}.tar.gz ]
then
echo "openssl 压缩包不存在"
wget https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz
fi
if [ ! -d openssl-${OPENSSL_VERSION} ]
then
echo "openssl 目录不存在"
tar -zxvf openssl-${OPENSSL_VERSION}.tar.gz
fi
if [ ! -e ${NDK_VERSION}-linux-x86_64.zip ]
then
echo "ndk 压缩包不存在"
wget https://dl.google.com/android/repository/${NDK_VERSION}-linux-x86_64.zip
#ndk23+后缀不区分x86_64
#wget https://dl.google.com/android/repository/${NDK_VERSION}-linux.zip
fi
if [ ! -d ${NDK_VERSION} ]
then
echo "ndk 目录不存在"
unzip ${NDK_VERSION}-linux-x86_64.zip
#ndk23+后缀不区分x86_64
#unzip ${NDK_VERSION}-linux.zip
fi
build_library() {
mkdir -p ${OUTPUT_PATH}
make && make install
rm -rf ${OPENSSL_TMP_FOLDER}
rm -rf ${OUTPUT_PATH}/bin
rm -rf ${OUTPUT_PATH}/share
rm -rf ${OUTPUT_PATH}/ssl
rm -rf ${OUTPUT_PATH}/lib/engines*
rm -rf ${OUTPUT_PATH}/lib/pkgconfig
rm -rf ${OUTPUT_PATH}/lib/ossl-modules
echo "Build completed! Check output libraries in ${OUTPUT_PATH}"
}
for ABI in ${ANDROID_ABI_ARRAY[@]}
do
ANDROID_TARGET_ABI=${ABI}
#编译好的库输出路径
OUTPUT_PATH=${WORK_PATH}/openssl_${OPENSSL_VERSION}_${ANDROID_TARGET_ABI}
OPENSSL_TMP_FOLDER=${WORK_PATH}/tmp/openssl_${ANDROID_TARGET_ABI}
mkdir -p ${OPENSSL_TMP_FOLDER}
cp -r ${OPENSSL_SOURCES_PATH}/* ${OPENSSL_TMP_FOLDER}
echo "开始编译 ${ABI}"
if [ "$ANDROID_TARGET_ABI" = "armeabi" ]
then
export ANDROID_NDK_ROOT=${ANDROID_NDK_PATH}
PATH=$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin:$ANDROID_NDK_ROOT/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin:$ANDROID_NDK_ROOT/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64/bin:$PATH
cd ${OPENSSL_TMP_FOLDER}
./Configure android-arm -D__ANDROID_API__=${ANDROID_TARGET_API} -static no-shared no-tests -fPIC --prefix=${OUTPUT_PATH} #NDK22及以上需要添加-fPIC
build_library
elif [ "$ANDROID_TARGET_ABI" = "armeabi-v7a" ]
then
export ANDROID_NDK_ROOT=${ANDROID_NDK_PATH}
PATH=$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin:$ANDROID_NDK_ROOT/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin:$ANDROID_NDK_ROOT/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64/bin:$PATH
cd ${OPENSSL_TMP_FOLDER}
./Configure android-arm -D__ANDROID_API__=${ANDROID_TARGET_API} -static no-shared no-tests -fPIC --prefix=${OUTPUT_PATH} #NDK22及以上需要添加-fPIC
build_library
elif [ "$ANDROID_TARGET_ABI" = "arm64-v8a" ]
then
export ANDROID_NDK_ROOT=${ANDROID_NDK_PATH}
PATH=$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin:$ANDROID_NDK_ROOT/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin:$ANDROID_NDK_ROOT/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64/bin:$PATH
cd ${OPENSSL_TMP_FOLDER}
./Configure android-arm64 -D__ANDROID_API__=${ANDROID_TARGET_API} -static no-shared no-tests -fPIC --prefix=${OUTPUT_PATH} #NDK22及以上需要添加-fPIC
build_library
elif [ "$ANDROID_TARGET_ABI" = "mips" ]
then
export ANDROID_NDK_ROOT=${ANDROID_NDK_PATH}
PATH=$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin:$ANDROID_NDK_ROOT/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin:$ANDROID_NDK_ROOT/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64/bin:$PATH
cd ${OPENSSL_TMP_FOLDER}
./Configure android-mips -D__ANDROID_API__=${ANDROID_TARGET_API} -static no-shared no-tests -fPIC --prefix=${OUTPUT_PATH} #NDK22及以上需要添加-fPIC
build_library
elif [ "$ANDROID_TARGET_ABI" = "mips64" ]
then
export ANDROID_NDK_ROOT=${ANDROID_NDK_PATH}
PATH=$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin:$ANDROID_NDK_ROOT/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin:$ANDROID_NDK_ROOT/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64/bin:$PATH
cd ${OPENSSL_TMP_FOLDER}
./Configure android-mips64 -D__ANDROID_API__=${ANDROID_TARGET_API} -static no-shared no-tests -fPIC --prefix=${OUTPUT_PATH} #NDK22及以上需要添加-fPIC
build_library
elif [ "$ANDROID_TARGET_ABI" = "x86" ]
then
export ANDROID_NDK_ROOT=${ANDROID_NDK_PATH}
PATH=$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin:$ANDROID_NDK_ROOT/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin:$ANDROID_NDK_ROOT/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64/bin:$PATH
cd ${OPENSSL_TMP_FOLDER}
./Configure android-x86 -D__ANDROID_API__=${ANDROID_TARGET_API} -static no-shared no-tests -fPIC --prefix=${OUTPUT_PATH} #NDK22及以上需要添加-fPIC
build_library
elif [ "$ANDROID_TARGET_ABI" = "x86_64" ]
then
export ANDROID_NDK_ROOT=${ANDROID_NDK_PATH}
PATH=$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin:$ANDROID_NDK_ROOT/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin:$ANDROID_NDK_ROOT/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64/bin:$PATH
cd ${OPENSSL_TMP_FOLDER}
./Configure android-x86_64 -D__ANDROID_API__=${ANDROID_TARGET_API} -static no-shared no-tests -fPIC --prefix=${OUTPUT_PATH} #NDK22及以上需要添加-fPIC
build_library
else
echo "Unsupported target ABI: $ANDROID_TARGET_ABI"
exit 1
fi
done
cmake_minimum_required(VERSION 3.18.1)
#隐藏符号表
add_definitions("-fvisibility=hidden")
#指定c++文件路徑
file(GLOB SOURCE ${CMAKE_SOURCE_DIR}/*.cpp)
include_directories(${CMAKE_SOURCE_DIR})
#添加目标库
add_library(openssl_test SHARED ${SOURCE})
#添加两个预编译库
add_library(openssl-crypto STATIC IMPORTED)
set_target_properties(openssl-crypto PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/libs/${CMAKE_ANDROID_ARCH_ABI}/libcrypto.a)
add_library(openssl-ssl STATIC IMPORTED)
set_target_properties(openssl-ssl PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/libs/${CMAKE_ANDROID_ARCH_ABI}/libssl.a)
#查找android log库
find_library(log-lib log)
#编译关联目标库
target_link_libraries(openssl_test ${log-lib} openssl-ssl openssl-crypto)
实现Base64编码
/**
* base64编码
* @param input 待编码内容
* @param length 待编码内容长度
* @param newLine 是否换行
* @return 编码后内容
*/
char *base64Encode(const char *buffer, int length, bool newLine) {
BIO *bmem = nullptr;
BIO *b64 = nullptr;
BUF_MEM *bptr;
b64 = BIO_new(BIO_f_base64());
if (!newLine) {
BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
}
bmem = BIO_new(BIO_s_mem());
b64 = BIO_push(b64, bmem);
BIO_write(b64, buffer, length);
BIO_flush(b64);
BIO_get_mem_ptr(b64, &bptr);
BIO_set_close(b64, BIO_NOCLOSE);
char *buff = (char *) malloc(bptr->length + 1);
memcpy(buff, bptr->data, bptr->length);
buff[bptr->length] = '\0';
BIO_free_all(b64);
return buff;
}
/**
* base64解码
* @param input 待解码内容
* @param length 待解码内容长度
* @param newLine 是否换行
* @return 解码后内容
*/
char *base64Decode(const char *input, int length, bool newLine) {
BIO *b64 = nullptr;
BIO *bmem = nullptr;
char *buffer = (char *) malloc(length);
memset(buffer, 0, length);
b64 = BIO_new(BIO_f_base64());
if (!newLine) {
BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
}
bmem = BIO_new_mem_buf(input, length);
bmem = BIO_push(b64, bmem);
BIO_read(bmem, buffer, length);
BIO_free_all(bmem);
return buffer;
}
extern "C" {
JNIEXPORT jstring
Java_cn_wgc_myapplication_Openssl_base64Encode(JNIEnv * env , jobject instance, jstring content ) {
const char *content_ = env->GetStringUTFChars(content, nullptr);
char *encodeString = base64Encode(content_, strlen(content_), false);
LOGD("jniEncodeString :%s", encodeString) ;
return env -> NewStringUTF(encodeString);
}
}
val content = "123456789abcdefghijklmn"
val javaEncode = Base64.encodeToString(content.toByteArray(), Base64.NO_WRAP)
val opensslEncode = Openssl.instance.base64Encode(content)
执行完java与openssl编码的字符效果如下
参考链接:openssl_for_android/openssl_build.sh at master · 217heidai/openssl_for_android · GitHub