QT + OpenSSL + Android

QT + OpenSSL + Android

本文关键字:Android OpenSSL QT      更新时间:2023-10-16

我想设置OpenSSL库。我的Qt项目。在Linux下,它可以很好地与内置的OpenSSL一起工作。我把这个添加到我的。pro文件中:

LIBS+=-lcrypto
PKGCONFIG += openssl

但如果我在Android中使用它,它会给出错误。我按照下面的说明做了:

$ . ./setenv-android.sh
$ cd openssl-1.0.1h/
$ perl -pi -e 's/install: all install_docs install_sw/install: install_docs install_sw/g' Makefile.org
$ ./config shared -no-ssl2 -no-ssl3 -no-comp -no-hw -no-engine --openssldir=/usr/local/ssl/$ANDROID_API
$ make depend
$ ./Configure shared android-armv7
$ make build_libs
$ export CC=/home/laci/android-ndk-r10/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gcc
$ export AR=/home/laci/android-ndk-r10/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64/bin/arm-linux-androideabi-ar
$ export ANDROID_DEV=/home/laci/android-ndk-r10/platforms/android-14/arch-arm/usr/
$ make all
$ sudo -E make install CC=$ANDROID_TOOLCHAIN/arm-linux-androideabi-gcc RANLIB=$ANDROID_TOOLCHAIN/arm-linux-androideabi-ranlib

这些网站是我的资料来源:

  • OpenSSL wiki
  • QtDoc -添加OpenSSL支持

我做错了什么?

提前感谢您的回答

解决方案是:

1a)正确的方法:为android编译openssl库(使用1.0.2+,不要使用1.1)。* -至少对于Qt 5.9.2)

1b)快速和肮脏的方式:从任何现有的应用程序APK(警告:过时的库==>安全威胁)获取它们,如果你需要快速和肮脏的解决方案。查找libssl。还有libcrypto。所以在APK arm目录下。

然后

2a)打开Qt Creator, Projects -> [project] -> Build &运行-> Android for armeabi->v7a ->构建->构建Android APK -> Android ->附加库->添加…(添加libssl。所以,libcrypto。所以)

2b)在你的.pro makefile中添加以下内容:

ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android
contains(ANDROID_TARGET_ARCH,armeabi-v7a) {
     ANDROID_EXTRA_LIBS = 
        $$PWD/android/libs/arm/libcrypto.so 
        $$PWD/android/libs/arm/libssl.so
}

($ $ PWD/android/. .是您在项目中放置这些库的路径)。ANDROID_PACKAGE_SOURCE_DIR在这种情况下看起来是可选的。

然后

3)添加它们加载到AndroidManifest(至少对Qt 5.9.2有效):小心地将它们添加到您现有的主活动和进程外服务的元数据中,如果有的话。

        <meta-data android:name="android.app.load_local_libs" android:value="-- %%INSERT_LOCAL_LIBS%% --:lib/libssl.so:lib/libcrypto.so"/>

"lib"在这里必须是"lib",它指的是设备上的目录布局,而不是你的项目结构。

然后

4)构建你的apk。检查您的库是否在适当的位置:

$ jar tvf ./android-build/build/outputs/apk/android-build-debug.apk| grep libssl
344388 Tue Apr 11 12:35:36 EEST 2017 lib/armeabi-v7a/libssl.so

我把这个指令放在这里,因为我花了太多时间寻找答案,任何没有ANDROID_EXTRA_LIBS的东西都不能为我工作。

为什么有这么大的问题?因为6.0以下的Android可能包含自己的libssl/libcrypto,通过"-l"链接会在你的主二进制文件中添加自动加载条目(不是qt管理的),系统库可能是错误的版本,或者静默加载而不是你的附带二进制文件,从而掩盖Android 7的bug。Android 7绝对不包含libssl, "-l"将失败,并且在运行时无法解析符号。

通过不使用"-l"和使用Qt的"android.app."相反,您将强制QtLoader使用您的libs版本。请记住,openssl 1.0.2与默认的android Qt构建和1.1一起工作。由于符号不同,*将不起作用。(SSL_init_library是1.0.2,OPENSSL_init_library是1.1.*)

有趣的是,由于这些复杂性,方法"1b)"可能不起作用。您选择的APK可能包含libssl。但是它的作者没有正确地构建和加载它,所以他的libssl。所以可能是不正确的版本的共享库,这在android上通常是不允许的,但作者使用-l并且从不加载自己的库(使用system代替),并且从不知道他的库不会在android上加载

填词+ = -lcrypto

我看到两个潜在的问题。首先,您可能需要LIBS += -lssl -lcrypto

第二,QT 可能使用主机的OpenSSL(即,在/usr/lib中使用i386或x86_64),而不是目标的OpenSSL(即,在/usr/local/ssl/android/lib '中使用libssllibcrypto)。要解决这个问题,我发现最简单的方法是指定库的完整路径:
LIBS += /usr/local/ssl/android/lib/libssl.a /usr/local/ssl/android/lib/libcrypto.a

您必须避免只使用-lssl -lcrypto,如果可用,它链接到共享对象。Android使用OpenSSL 0.9.8。所以你将在编译时编译1.0.1h,但在运行时链接android 0.9.8。这会导致一堆无法解释的错误。

这种行为的发生是因为Android的主进程- Zygote -在启动后加载了0.9.8版本的OpenSSL。在Zygote分叉进入您的进程后,0.9.8已经加载。他们的操作系统将不会加载你的1.0.1版本,因为链接依赖已经满足了。

我想总结一下解决方案(这是我的主观意见):

    仅支持openssl 0.9.8za
  • 必须添加libcrypto。(thankx @jww)

我的setv -android.sh "可编辑"变量:

_ANDROID_NDK="android-ndk-r10"
_ANDROID_EABI="arm-linux-androideabi-4.8"
_ANDROID_ARCH=arch-arm
_ANDROID_API="android-14"

建筑过程:

$ . ./setenv-android.sh
$ tar xzf openssl-0.9.8za.tar.gz
$ cd openssl-0.9.8za/
$ ./config
$ make

。支持文件:

# FORMS, SOURCES, TARGET, etc...
unix:!macx: LIBS += -L$$PWD/../SSL/openssl-0.9.8za/ -lcrypto
INCLUDEPATH += $$PWD/../SSL/openssl-0.9.8za/include
DEPENDPATH += $$PWD/../SSL/openssl-0.9.8za/include
unix:!macx: PRE_TARGETDEPS += $$PWD/../SSL/openssl-0.9.8za/libcrypto.a

对我有用的是:编辑openssl Makefile。共享并替换

-soname=$$SHLIB$$SHLIB_SOVER$$SHLIB_SUFFIX

-soname=$$SHLIB

这样库的内部名称被更改为libcrypto。还有libssl。而不是libcrypto。So .1.0.0

清理并重新编译openssl和你的应用。