QT + OpenSSL + Android

Я хотел бы настроить OpenSSL lib. для моего проекта 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

Эти веб-сайты были моими источниками:

Что я делаю неправильно?

Заранее благодарим за ваши ответы

4 ответа

ЛИЭС + = - lcrypto

Здесь я вижу две потенциальные проблемы. Во-первых, вам, вероятно, понадобится LIBS += -lssl -lcrypto.

Во-вторых, QT, вероятно, использует хост OpenSSL (т.е. i386 или x86_64 в /usr/lib), а не целевой OpenSSL (т.е. libssl и libcrypto в /usr/local/ssl/android/lib `). Чтобы исправить это, самый простой способ, который я нашел, - указать полный путь к библиотеке:

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 во время компиляции, но свяжетесь с Androids 0.9.8 во время выполнения. Это вызовет кучу необъяснимых ошибок.

Поведение происходит из-за того, что основной процесс Android - Zygote - загружает версию 0.9.8 OpenSSL после ее запуска. После того, как Zygote превратится в ваш процесс, 0.9.8 уже загружен. Они не будут загружать вашу версию 1.0.1, потому что зависимость ссылок уже выполнена.


Решение:

1a) правильный способ: скомпилировать библиотеки openssl для android (используйте 1.0.2+, не используйте 1.1. * - по крайней мере для Qt 5.9.2)

или

1b) быстрый и грязный способ: ПОЛУЧИТЕ ИХ ИЗ любого существующего приложения APK (предупреждение: устаревшие libs == > угроза безопасности), если вам нужно быстрое и грязное решение. Найдите libssl.so и libcrypto.so внутри каталога APK arm.

ТОГДА

2a) открыть Qt Creator, Projects → [project] → Build and Run → Android for armeabi- > v7a → Build → Build Android APK → Android → Дополнительные библиотеки → Добавить.. (добавить libssl.so, libcrypto.so есть)

или

2b) в файле make. make добавьте следующее:

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): аккуратно добавьте их здесь в существующие метаданные основной активности и внепроцессные службы, если они есть.


"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 могут содержать свой собственный libssl/libcrypto, а ссылка через "-l" добавит запись автозагрузки в ваш основной двоичный файл (не Qt-управляемый), а системные библиотеки могут быть неправильной версии или загрузить SILENTLY INSTEAD OF ВАШИ отгруженные двоичные файлы таким образом маскируют ошибку с Android 7. Android 7 определенно не содержит libssl, а "-l" потерпит неудачу, и символы не будут разрешены во время выполнения.

Не используя "-l" и вместо этого используя Qt "android.app.load_local_libs", вы вынуждаете QtLoader использовать вашу версию lib. Помните, что openssl 1.0.2 работает с установкой по умолчанию android Qt, а 1.1. * НЕ будет работать из-за разных символов. (SSL_init_library - 1.0.2, OPENSSL_init_library - 1.1. *)

Интересно, что из-за этих сложностей метод "1b" "может не работать. APK, который вы выбрали, может содержать libssl.so, но его автор построил его неправильно и загрузил его неправильно, поэтому его libssl.so может быть неправильной версией общей библиотеки, которая, как правило, не работает на android, но автор использовал -l и никогда не загружал собственную lib (вместо этого использовалась система) и никогда не знала, что его библиотека не будет загружаться на Android.


Что сработало для меня было: отредактируйте файл openssl Makefile.shared и замените

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

с

-soname=$$SHLIB

Таким образом, внутреннее имя библиотеки будет изменено на libcrypto.so и libssl.so вместо libcrypto.so.1.0.0

Очистите и перекомпилируйте openssl и ваше приложение.


Я хотел бы обобщить решение (это мое субъективное мнение):

  • Только openssl 0.9.8za работает с Android.
  • Должен добавить libcrypto.a(thankx @jww)

My setenv-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

.pro файл:

# 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

licensed under cc by-sa 3.0 with attribution.