4

我正在为 Android 开发一个基于 Qt 的应用程序,它使用 QSslSocket 下载数据。由于依赖于 OpenSSL 库的 Marshmallow Qt 程序,Android 从 OpenSSL 转向 BoringSSL,因此在 Android 6+ 上会产生以下警告:

W libtestopenssl.so: (null):0 ((null)): qt.network.ssl: QSslSocket: 无法解析 CRYPTO_free
W libtestopenssl.so: (null):0 ((null)): qt.network.ssl: QSslSocket: 无法解析 EVP_CipherFinal
W libtestopenssl.so: (null):0 ((null)): qt.network.ssl: QSslSocket: 无法解析 EVP_rc2_cbc
W libtestopenssl.so: (null):0 ((null)): qt.network.ssl: QSslSocket: 无法解析 SSLv2_client_method
W libtestopenssl.so: (null):0 ((null)): qt.network.ssl: QSslSocket: 无法解析 SSLv2_server_method
W libtestopenssl.so: (null):0 ((null)): qt.network.ssl: QSslSocket: 无法解析 OPENSSL_add_all_algorithms_noconf
W libtestopenssl.so: (null):0 ((null)): qt.network.ssl: QSslSocket: 无法解析 OPENSSL_add_all_algorithms_conf
W libtestopenssl.so: (null):0 ((null)): qt.network.ssl: QSslSocket: 无法解析 EC_get_builtin_curves
W libtestopenssl.so: (null):0 ((null)): qt.network.ssl: QSslSocket: 无法调用未解析的函数 OPENSSL_add_all_algorithms_conf
W libtestopenssl.so: (null):0 ((null)): qt.network.ssl: QSslSocket: 无法调用未解析的函数 EC_get_builtin_curves
W libtestopenssl.so: (null):0 ((null)): qt.network.ssl: QSslSocket: 无法调用未解析的函数 EC_get_builtin_curves
W libtestopenssl.so: (null):0 ((null)): qt.network.ssl: 无法设置 SSL_CTRL_SET_TLSEXT_HOSTNAME,服务器名称指示已禁用
W libtestopenssl.so: (null):0 ((null)): qt.network.ssl: QSslSocket: 无法调用未解析的函数 CRYPTO_free

但是,套接字本身成功连接到远程主机并从那里读取数据,没有任何明显的问题。这让我想知道我是否需要自己构建 OpenSSL 库并将其打包,或者使用平台提供的 BoringSSL 是否可以。

我还注意到,Android 版本低于 6 的应用程序倾向于使用 OpenSSL 的系统版本,即使我提供了自己的版本。我尝试添加构建的 libssl.so 和 libcrypto.so(从 libssl.so.1.0.0 和 libcrypto.so.1.0.0 重命名)ANDROID_EXTRA_LIBS(不确定是否LIBS+=也需要使用),甚至静态链接 libssl.a 和libcrypto.a. 仍然 QSslSocket::sslLibraryVersionString() 返回平台上可用的版本。

我的问题是:

  1. 是需要自己搭建OpenSSL库并打包还是使用平台提供的库就可以了?
  2. 如果我这样做,如何让 Android 识别 libssl.so 和 libcrypto.so?
4

1 回答 1

2

1. OpenSSL库需要自己搭建并打包好还是使用平台提供的库好?

  • 是的 - 您应该构建 OpenSSL 并将其打包。

https://developer.android.com/about/versions/nougat/android-7.0-changes.html

从 Android 7.0 开始,系统会阻止应用动态链接非 NDK 库,这可能会导致您的应用崩溃。这种行为改变旨在跨平台更新和不同设备创建一致的应用体验。

  • 使用已安装的 BoringSSL 可能暂时可行,但建议应用程序自带 OpenSSL 库。
  • 否则,您的用户将看到一条警告消息弹出,并且该应用程序可能无法在更高版本的 Android 上运行。

为了减少此限制可能对当前发布的应用程序产生的影响,在 Android 7.0 上暂时可以访问一组使用量很大的库(例如 libandroid_runtime.so、libcutils.so、libcrypto.so 和 libssl.so) (API 级别 24)适用于面向 API 级别 23 或更低级别的应用。如果您的应用程序加载其中一个库,logcat 会生成一个警告,并且目标设备上会出现一个 toast 来通知您。如果您看到这些警告,则应更新您的应用程序以包含其自己的这些库副本或仅使用公共 NDK API。Android 平台的未来版本可能会完全限制私有库的使用并导致您的应用程序崩溃。

2.如果我这样做,如何让Android识别libssl.so和libcrypto.so?

  • 我主要按照此处概述的步骤成功:http: //doc.qt.io/qt-5/opensslsupport.html

  • 但请确保您获得了正确的版本:openssl-1.1.0f.tar.gz 似乎与 Qt 5.9 不兼容,并且我的应用程序没有加载库。

  • 为桌面编译并调用 QSslSocket::sslLibraryVersionString() 以查看您的 Qt 使用哪个 OpenSSL 版本。对我来说,它显示“OpenSSL 1.0.1t 2016 年 5 月 3 日”
  • git repo 中的标签“OpenSSL_1_0_1t”为我使用 Qt 5.9.1
  • 来自 openssl.org 的 openssl-1.0.2l.tar.gz 也适用于 Qt 5.9.1

我使用了 API 级别 19。一旦我使用 API 级别 23 或 25 进行了测试,我将更新这个答案。

于 2017-08-26T13:49:09.533 回答