Учебное Android-приложение, демонстрирующее архитектуру, где:
- Kotlin/Android UI вызывает C++ через JNI (NDK);
- C++ запускает фоновую транзакцию (std::thread) и делает callback в Kotlin:
- запросить ввод PIN (
enterPin) - вернуть результат транзакции (
transactionResult)
- запросить ввод PIN (
- ввод PIN выполняется в отдельной Activity (PinpadActivity) и передаётся обратно в C++ через JNI (
providePin); - из C++ ведётся логирование в Logcat через spdlog (
android_sink); - используется mbedTLS для:
- генерации криптостойких случайных байтов (Entropy + CTR_DRBG),
- демонстрационного шифрования/дешифрования (2-key 3DES + ECB + PKCS#5 padding).
Важно: 3DES и режим ECB небезопасны для реальных систем и используются здесь только как простой пример интеграции mbedTLS через JNI.
- Пользователь нажимает кнопку “транзакции” в
MainActivity. - Kotlin вызывает JNI-метод
transaction(trd: ByteArray). - В C++ создаются
GlobalRefнаMainActivityиtrd, запускается фоновый поток. - Фоновый поток:
- парсит сумму из
TRD, - вызывает callback
enterPin(attempts, amount)(C++ → Kotlin) для показа PIN-pad, - ждёт PIN через
condition_variable.
- парсит сумму из
PinpadActivityвозвращает PIN вMainActivity, после чего Kotlin вызываетprovidePin(pin)(Kotlin → C++).- C++ проверяет PIN, повторяет до 3 попыток, затем вызывает
transactionResult(ok)(C++ → Kotlin), UI показывает Toast. - (Дополнительно) после 3 неверных попыток ввод временно блокируется (пример анти-брутфорса).
-
Kotlin / UI
MainActivity:- реализует интерфейс транзакционных событий (enterPin / transactionResult)
- запускает
PinpadActivityчерезActivityResultLauncher - отправляет введённый PIN в native через
providePin
PinpadActivity:- UI ввода PIN + отображение суммы и числа попыток
- перемешивание клавиш (использует
randomBytesиз native)
-
C++ / NDK
JNI_OnLoad:- сохраняет
JavaVM*для последующего attach/detach фоновых потоков
- сохраняет
transaction:- создаёт глобальные ссылки
- запускает
std::thread - вызывает Java-методы через
GetMethodID+CallVoidMethod - синхронизируется с UI через
providePinиcondition_variable
providePin:- получает PIN из Kotlin и будит поток транзакции
spdlog(...):- пишет сообщения в Logcat
initRng/freeRng/randomBytes,encrypt/decrypt:- демонстрация mbedTLS и вызовов из Kotlin
- Android Studio + Android SDK
- Android NDK (через SDK Manager)
- CMake (через SDK Manager)
- Устройство/эмулятор с ABI, под который собраны зависимости (обычно
arm64-v8a)
В проекте используются внешние библиотеки, которые размещаются в libs/:
- mbedTLS:
v3.6.5 - spdlog
fclient/
app/
libs/
mbedtls/
mbedtls/ # исходники mbedtls
build/arm64-v8a/ # результаты сборки
compile.sh # (опционально) ваш скрипт сборки
spdlog/
spdlog/ # исходники spdlog
build/arm64-v8a/ # результаты сборки
compile.sh # (опционально) ваш скрипт сборки
Из корня проекта:
# spdlog
git clone https://github.com/gabime/spdlog.git libs/spdlog/spdlog
# mbedtls (версия 3.6.5)
git clone https://github.com/Mbed-TLS/mbedtls.git libs/mbedtls/mbedtls
cd libs/mbedtls/mbedtls
git checkout v3.6.5
cd ../../../Соберите под нужный ABI (пример: arm64-v8a) вашим способом/скриптами:
cd libs/spdlog/build/
./compile.sh
cd ../../
cd libs/mbedtls/build/
./compile.sh
cd ../../Проверьте, что появились артефакты (пример для arm64-v8a):
libs/spdlog/build/arm64-v8a/libspdlog.alibs/mbedtls/build/arm64-v8a/library/libmbedtls.solibs/mbedtls/build/arm64-v8a/library/libmbedcrypto.so
- Открыть проект в Android Studio
- Gradle Sync
- Run на устройстве/эмуляторе подходящего ABI
JNIEnv*нельзя переносить между потоками — в фоне используетсяAttachCurrentThread/DetachCurrentThread.- Объекты
thizиtrdпередаются в фоновые потоки черезNewGlobalRef, затем освобождаютсяDeleteGlobalRef. - Вызовы UI выполняются в
runOnUiThread(Kotlin), чтобы не нарушать правила Android.
Проект учебный: демонстрация JNI + архитектуры обратных вызовов C++ ↔ Kotlin. Для реальных платёжных/криптосистем используйте современные алгоритмы и режимы (например, AES-GCM или ChaCha20-Poly1305), корректную обработку ошибок/паддинга и защищённую работу с PIN (zeroization, защита памяти, аппаратные модули, PCI DSS и т.д.).