I am trying to store api keys using NDK but i tried somany methods always somany error
I will share my code please any body help me..
I will share my steps i followed ..
1 Create a folder “jni” under src/main
2 Create and add “Android.mk” file under “jni” folder with following content:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := keys
LOCAL_SRC_FILES := keys.c
include $(BUILD_SHARED_LIBRARY)
Create and add “Application.mk” file under “jni” folder with the following content:
APP_ABI := all
Create the C/C++ file “keys.c” and add it under “jni” folder. Add the following content to it:
# include < jni.h >
JNIEXPORT jstring JNICALL
Java_com_mytest_aes_MainActivity_getNativeKey1(JNIEnv *env, jobject instance) {
return (*env)->NewStringUTF(env, "haii");
}
In the Activity where you want to access the keys (in our case MainActivity), create a static block and load the library “keys” like:
static
{
System.loadLibrary("keys");
}
Declare two member function of type native to access the keys from the C/C++ file. Since we have stored 2 keys, we will declare 2 functions:
public native String getNativeKey1();
For demo, access the keys in the code like:
String key1 = new String(Base64.decode(getNativeKey1(),Base64.DEFAULT));
((TextView)findViewById(R.id.key)).setText("Key1-->"+key1);
Now, our C/C++ native files and Java code are ready. But to compile or make the native build using NDK, we need to add entry into the gradle file:
android {
.....
buildTypes {
.....
}
externalNativeBuild {
ndkBuild {
path 'src/main/jni/Android.mk'
}
}
}
We need to provide the path for our “Android.mk” file.
Now, sync and build the project. Make sure, you have pointed the NDK path correctly in your module settings.
There are different ways in which API keys can be kept secure.
Best practice for storing and protecting private API keys in applications
Securing API Keys using Android NDK
https://medium.com/#abhi007tyagi/storing-api-keys-using-android-ndk-6abb0adcadad
Don't forget to define the NDK path correctly in your module settings. (File -> Project Structure -> SDK Location Tab -> Android NDK Location)
Note that using NDK, it's not full proof and you can still extract the keys. However, this will add an extra layer of obfuscation for your keys.
The suggested solution:- Can be used as a combination of multiple methods like Obfuscation, Encryption, Using NDK, Storing keys in Server, https integration, etc. based on the sensitivity of data in your application.
Related
I'm working on an Android project which uses a Java class that is a wrapper on a C++ library. The C++ library is a company internal library and we have access to its source code, but in the Android project it is only dynamically linked, so it is used only in the form of headers (.h) and shared objects (.so). Having access to the library source code, is it possible to specify to Android Studio the path to the source code so I can step inside the library using the debugger?
The debugger works, I can step inside the Java_clory_engine_sdk_CloryNative_nativeInit function, but I would also like to further debug the library corresponding to the Clory::Engine class which, as I mentioned, is an internal library we have source code access to.
For example, Clory::Engine::instance is part of the library and I would like to specify to Android Studio the location of the CloryEngine.cpp file so I can step inside Clory::Engine::instance with the debugger, thus debugging this static member function.
I am using Android Studio 3.1.4.
Is this possible?
EDIT:
The clory-sdk.gradle file specifies the CMakeLists.txt file which configures the C++ layer.
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
So I am using an internal application which uses the Clory SDK. Inside the app.gradle file I use:
dependencies {
...
compile project(':clory-sdk-core')
compile project(':clory-sdk')
...
}
so I don't think we're using the aars for the app.gradle project. The aars are shipped to the client, but we are using app.gradle project to test our little SDK functionalities before doing that. The JNI layer is inside clory-sdk-core project.
EDIT 2:
Here is the CMakeLists.txt which handles the JNI layer:
cmake_minimum_required(VERSION 3.4.1)
set(CMAKE_AUTOMOC ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_BUILD_TYPE Debug)
add_library(
clory-lib
SHARED
# JNI layer and other helper classes for transferring data from Java to Qt/C++
src/main/cpp/clory-lib.cpp
src/main/cpp/JObjectHandler.cpp
src/main/cpp/JObjectResolver.cpp
src/main/cpp/JObjectCreator.cpp
src/main/cpp/DataConverter.cpp
src/main/cpp/JObjectHelper.cpp
src/main/cpp/JEnvironmentManager.cpp
)
find_library(
log-lib
log
)
target_compile_options(clory-lib
PUBLIC
-std=c++11
)
# Hardcoded for now...will fix later...
set(_QT_ROOT_PATH /Users/jacob/Qt/5.8)
if(${ANDROID_ABI} MATCHES ^armeabi-v7.*$)
set(_QT_ARCH android_armv7)
elseif(${ANDROID_ABI} MATCHES ^x86$)
set(_QT_ARCH android_x86)
else()
message(FATAL_ERROR "Unsupported Android architecture!!!")
endif()
set(CMAKE_FIND_ROOT_PATH ${_QT_ROOT_PATH}/${_QT_ARCH})
find_package(Qt5 REQUIRED COMPONENTS
Core
CONFIG
)
target_include_directories(clory-lib
PUBLIC
${CMAKE_CURRENT_LIST_DIR}/src/main/cpp
)
set(_CLORYSDK_LIB_PATH ${CMAKE_CURRENT_LIST_DIR}/src/main/jniLibs/${ANDROID_ABI})
target_link_libraries(clory-lib
${log-lib}
-L${_CLORYSDK_LIB_PATH}
clorysdk
Qt5::Core
)
The library clorysdk is actually our internal library I was talking about, which contains e.g. Clory::Engine::instance I would like to step into with the debugger. It was built with qmake and is built in debug mode (CONFIG+=debug was added in the effective qmake call).
EDIT 3:
In the LLDB session which has opened after it hit the Java_clory_engine_sdk_CloryNative_nativeInit breakpoint, I got the following:
(lldb) image lookup -vrn Clory::Engine::instance
2 matches found in /Users/jacob/.lldb/module_cache/remote-android/.cache/6EDE4F0A-0000-0000-0000-000000000000/libclorysdk.so:
Address: libclorysdk.so[0x0001bb32] (libclorysdk.so..text + 8250)
Summary: libclorysdk.so`Clory::Engine::instance(Clory::Engine::Purpose)
Module: file = "/Users/jacob/.lldb/module_cache/remote-android/.cache/6EDE4F0A-0000-0000-0000-000000000000/libclorysdk.so", arch = "arm"
Symbol: id = {0x0000005e}, range = [0xcb41eb32-0xcb41ebc0), name="Clory::Engine::instance(Clory::Engine::Purpose)", mangled="_ZN4Clory2Engine8instanceENS0_7PurposeE"
Address: libclorysdk.so[0x0001b82c] (libclorysdk.so..text + 7476)
Summary: libclorysdk.so`Clory::Engine::instance(Clory::RuntimeConfiguration const&, Clory::Engine::Purpose)
Module: file = "/Users/jacob/.lldb/module_cache/remote-android/.cache/6EDE4F0A-0000-0000-0000-000000000000/libclorysdk.so", arch = "arm"
Symbol: id = {0x000000bd}, range = [0xcb41e82c-0xcb41e970), name="Clory::Engine::instance(Clory::RuntimeConfiguration const&, Clory::Engine::Purpose)", mangled="_ZN4Clory2Engine8instanceERKNS_20RuntimeConfigurationENS0_7PurposeE"
(lldb) settings show target.source-map
target.source-map (path-map) =
First of all, there was no CompileUnit section in the result of the command image lookup -vrn Clory::Engine::instance. How is this possible to have no source-map defined(second lldb command) if the libclorysdk.so was built in Debug mode? Is it possible to explicitly set it so that the debugger would search there for the library's source files?
EDIT 4:
After searching more I found out that the process of creating the APK actually strips the *.so libraries from their debugging symbols. libclorysdk.so built in debug mode has about 10MB while the libclorysdk.so file which I extracted after unarchiving the generated *.apk file is just 350KB.
As stated here, running greadelf --debug-dump=decodedline libclorysdk.so on the debug version outputs references to the source files, but if the command is run on the *.apk extracted library, it outputs nothing.
Is there a way to stop Android Studio from stripping the *.sos? I tried How to avoid stripping for native code symbols for android app but didn't have any effect, *.apk file is the same size as before and debugging the native libraries still doesn't work.
I'm using Gradle 3.1.4.
EDIT 5:
The stripping solution works, but in my case, it needed a Clean & Build before hitting the breakpoints in the library. Deploying *.sos which are not stripped is allowing you to have debugging sessions and step inside the native libraries.
Note:
If the libraries are built using the Qt for Android toolchain, the *.sos deployed to $SHADOW_BUILD/android-build are also stripped(where $SHADOW_BUILD is the build directory usually starting with build-*). So in order to debug those you should copy them from outside the android-build directory where each *.so is generated.
The debug info records the location of the source files when they were built.
(lldb) image lookup -vrn Clory::Engine::instance
The CompileUnit line shows the source file. Suppose it says:
"/BuildDirectory/Sources/Clory/CloryEngine.cpp"
Let's assume you have the source on your machine here:
"Users/me/Sources/Clory"
So you can tell lldb: find the source file rooted at /BuildDirectory/Sources/Clory in Users/me/Sources/Clory instead.
(lldb) settings set target.source-map /BuildDirectory/Sources/Clory Users/me/Sources/Clory
You can use these commands in the lldb console of Android Studio or put into a .lldbinit file for general use.
If there no debug symbols available, you might have to build the referenced library in debug mode.
Either with -DCMAKE_BUILD_TYPE=DEBUG:
defaultConfig {
externalNativeBuild {
cmake {
arguments "-DANDROID_TOOLCHAIN=gcc", "-DCMAKE_BUILD_TYPE=DEBUG"
cppFlags "-std=c++14 -fexceptions -frtti"
}
}
}
externalNativeBuild {
cmake {
path file('src/main/cpp/CMakeLists.txt')
}
}
Or add this to the CMakeLists.txt of the library:
set(CMAKE_BUILD_TYPE Debug)
See the CMake documentation and Symbolicating with LLDB.
Elsewhere it explains (lldb) settings set target.source-map /buildbot/path /my/path:
Remap source file path-names for the debug session. If your source files are no longer located in the same location as when the program was built --- maybe the program was built on a different computer --- you need to tell the debugger how to find the sources at their local file path instead of the build system's file path.
There's also (lldb) settings show target.source-map, to see what is mapped.
(lldb) set append target.source-map /buildbot/path /my/path seems rather suitable, in order not to overwrite existing mappings.
I use Android NDK r8 to generate multiple static libraries with include $(BUILD_STATIC_LIBRARY) and I successfully get : lib1.a, lib2.a, lib3.a, etc.
Now I would like to merge these static libraries into single one.
I try do it with ar.exe from Android NDK :
android-ndk-r8\toolchains\arm-linux-androideabi-4.4.3\prebuilt\windows\arm-linux-androideabi\bin\ar.exe r libALL.a lib1.a lib2.a lib3.a
But when I use libAll.a into Android NDK makefile, it fails saying there is no index.
How can I add this index ?
Other question :
When I display contents of archive libAll.a, I see lib1.a, lib2.a, lib3.a instead of .o symbols from these libraries.
How can I change that (= extract .o from static libraries to merge it in libAll.a) ?
Thanks
ar is simply an archiving tool like zip. It takes the given input files and produces an .aarchive. If you want to include all .ofiles in a single archive, you have to specify each individual file. I don't know how to do this on WIndows, but on Linux you can use somthing like ar rs $(find . -name *.o).
first of all I want to tell you what I want to do. I have a .h-file and a .c-file with usual C-Code in it with which I created a shared library with the Android NDK. So now I have a .so-file which is called libtry.so. Furthermore, I want to use native code in my Android Eclipse project. So I created .java-file with the class "Counter" and the content
public native static int Number(int n);
and
static
{
System.loadLibrary("test");
}
Then I create a C-header file from the .java-file with the javah tool.
Afterwards I create a C-sourcefile for the C-Headerfile in which I implement the native code.
Then I create a shared library with those two files with LOCAL_MODULE := test, so that the file will be named libtest.so . But the point is, that I want to link the shared library libtry.so, which I created at the beginning, to this shared library.
So in the Android.mk-file of libtest.so I put LOCAL_LDLIBS := -L/root/Android/Samples/Test/libs/ -ltry .
Actually this works because I can compile this Android.mk-file with ndk-build.
But now in my Eclipse project, if I want to use the library libtest.so it does not work. I mean If I create an object of the Class "Counter" in which the library libtest.so is loaded,
I get the error: "Cannot load library: link_image[1966]: 1752 could not load needed library 'libtry.so' for 'libtest.so'" .
What am I doing wrong? Thanks in advance.
You are linking a library to a library. In the Java code they must be loaded explicitly in reverse order e.g.
static
{
System.loadLibrary("dependencylib"); // try
System.loadLibrary("mainlib"); // test
}
Answer taken from here
I am new to Android application development.I want develop a dll using android. Is it possible to develop and integrate to android app. Please tell me the solution. If it is possible please tell me the solution one by one.
As for me I once made a note for myself about NDK. Here it is:
Required applicaitions:
1. Eclipse
2. CDT+Sequoyah plug-ins
3. Android ADT
4. Android NDK
Configuration:
1. Install Eclipse, ADT, CDT and Sequoyah plug-ins
2. In the Eclipse -> Window -> Preferences -> Android -> Native Development put NDK location
Steps:
1. Create new Android Project
2. Create Java class for working with native libraries (NativeLibrary.java)
3. In the class NativeLibrary.java define interface for native methods
4. Right click on Project -> Android Tools -> Add Native Support. Define name of the library.
5. Build the project
6. Go to PROJECT_HOME/bin
7. Create C header file with the command javah -jni <packagename>.NativeLibrary
8. Move this file to PROJECT_HOME/jni folder
9. Implement methods from the header file in the generated cpp file. Do not forget to include the moved header in this file.
10. In java classes create new object of NativeLibrary class and call its methods.
11. Build project.
UPDATE: Step by step without plugins
Required applications - this is what you need to develop native applications. In my case I use Eclipse + Android ADT plugin + Android CDT plugin + Sequoyah plugin. You can install them using Eclipse - > Install new software
Then you should download Android NDK. Also you should export PATH to it.
For the configuration: you should define only path to your NDK in Eclipse -> Window -> Preferences -> Android -> Native Development
You are not obliged to use these plugins but it is easier to develop with them. However, Sequoyah contains errors (or it's sometimes not properly configured for my computer)
After that you can create new Android project. Then you can create java class that defines native methods. In my case this is NativeLibrary.java. Here it is:
package com.testpack.nativetest;
public class NativeLibrary {
public native static int add(int a, int b);
static {
System.loadLibrary("nativ");
}
}
After that build your Android project. After that go to your bin/classes (I don't know but before it was just bin directory) directory:
cd ~/programming/android/workspace/NativeTest/bin/classes
And run the following command:
javah -jni com.testpack.nativetest.NativeLibrary
This command should produce com_testpack_nativetest_NativeLibrary.h header in your bin/classes directory. It should look like:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_testpack_nativetest_NativeLibrary */
#ifndef _Included_com_testpack_nativetest_NativeLibrary
#define _Included_com_testpack_nativetest_NativeLibrary
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_testpack_nativetest_NativeLibrary
* Method: add
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_com_testpack_nativetest_NativeLibrary_add
(JNIEnv *, jclass, jint, jint);
#ifdef __cplusplus
}
#endif
#endif
Create jni directory in your project and Run the following command. It will move this header to jni directory.
mv com_testpack_nativetest_NativeLibrary.h ../../jni
After that in jni directory create .c file. In my case it is nativ.c, copy the definition of the function from .h file and generate code:
#include "com_testpack_nativetest_NativeLibrary.h"
JNIEXPORT jint JNICALL Java_com_testpack_nativetest_NativeLibrary_add
(JNIEnv *env, jclass obj, jint a, jint b) {
return a+b;
}
Then in jni directory you should create a make file Android.mk Here it is. Simply change the source (nativ.c) and the name of your library (nativ).
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := nativ
LOCAL_SRC_FILES := nativ.c
include $(BUILD_SHARED_LIBRARY)
Go to the PROJECT_HOME directory. In my case this is
cd ~/programming/android/workspace/NativeTest
and run ndk-build. That's all. After that you can test it in your activity:
package com.testpack.nativetest;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
public class NativeTestActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Log.d("TEST:", "Result 5+4=" + NativeLibrary.add(5, 4));
}
}
With plugins it is a bit easier to develop. But I think you should test it by yourself how to do this.
You can check out the Android NDK, here http://developer.android.com/sdk/ndk/index.html.
The NDK can be used to create linux equvalent .so, of the windows .dll files.
I did build the libssl.so from openssl project with Android NDK under the mac os x shell and now I would like someone to tell me how i can use it in Eclispe and in my android project ?
Is it ok if I drag and drop the file in the project root directory ??
How can I access the library function from the code ??
I saw this example :
// load the library - name matches jni/Android.mk
static {
System.loadLibrary("ndkfoo");
}
// declare the native code function - must match ndkfoo.c
private native String invokeNativeFunction();
...
file ndkfoo.c :
jstring Java_com_mindtherobot_samples_ndkfoo_NdkFooActivity_invokeNativeFunction(JNIEnv* env, jobject javaThis) {
return (*env)->NewStringUTF(env, "Hello from native code!");
}
But the libssl.so has it own functions list and they not named with my java class name i guess...
Any idea ?
to link .so file to yr project, u need to right click project->properties->Java Build Path->Library->Android 2.* -> Native Library location ->Edit -> browse to .so file folder path