Android openssl3.0.x编译和使用

Android openssl3.0.x编译和使用

1、前提准备

编译需要在linux环境下进行,笔者使用的是vmware虚拟机安装ubuntu 20.04进行编译,虚拟机的安装和ubuntu的安装这里就不详细说明了,可自行百度。

vmware官网下载地址

ubuntu 20.04下载地址

2、编译环境

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

3、开始编译

在编译前还需要下载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

4、一键编译

以上只是编译一个架构的静态库,如果需要其他架构还需重复编译,不够便捷,这里提供一个一键编译的版本。新建一个 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

编译后会出现以下文件夹,里面就是编译好的库文件和头文件
Android openssl3.0.x编译和使用_第1张图片

5、使用

将头文件和库文件拷贝到项目中
Android openssl3.0.x编译和使用_第2张图片
链接静态库

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编码的字符效果如下
Android openssl3.0.x编译和使用_第3张图片
参考链接:openssl_for_android/openssl_build.sh at master · 217heidai/openssl_for_android · GitHub

你可能感兴趣的:(android,ubuntu,android,studio)