LoginSignup
16
10

More than 3 years have passed since last update.

Androidで秘匿情報をNDKで隠蔽化する

Last updated at Posted at 2019-04-12

はじめに

Androidは通常ProGuardで難読化が行われますが、暗号化ではないためにソースコードやxml内の文字列は残ってしまいます。そのため、そこにパスワードやsecret keyなどの秘匿情報を記述していると、リバースエンジニアリングによって漏洩してしまうリスクがあります。

そこで、この記事ではNDK側に秘匿情報(文字列)を持たせ、情報を隠蔽化する方法について書きます。

実装方法

サンプルはこちらに置いておきます
https://github.com/shcahill/NDKSample

Nativeファイルの用意

任意の場所にcppディレクトリを用意し、Cファイルをaddします。
ここに秘匿情報を記載してください。

jni-sample.c
#include <string.h>
#include <jni.h>

JNIEXPORT jstring JNICALL
Java_com_shcahill_ndksample_MainActivity_stringFromJNI(JNIEnv *env, jobject thiz) {
    return (*env)->NewStringUTF(env,
                                // 秘匿情報の文字列(ここのコメントは残ってしまうので、実際には書かない)
                                "string from JNI!");
}

関数名は命名規則があります。

  1. 先頭にJava_をつける
  2. パッケージ名を_繋ぎでつける
  3. 呼び出すKotlin/Javaコードのファイル名をつける(拡張子は付けない)
  4. 関数名をつける

この例だと、MainActivityからstringFromJNIという名前で呼び出せます。
また、この例の場合、thizが未使用だとwarningが出ますが、消せませんのでご注意ください。
※パッケージ名にアンダースコアが含まれると、アンダースコアの後ろに1を付与する必要があります。
パッケージにアンダースコアが入っていた場合にJNI関連でハマったのでメモ

次にMakeファイルを同じ場所に追加します。

CMakeLists.txt
add_library(
        # library name using at Kotlin code
        jni-lib-name
        # as a shared library
        SHARED
        # relative path to C/C++ file
        jni-sample.c)

add_libraryの第一引数は、Kotlin側からsoファイルをloadするときのライブラリ名ですので、任意の名前を付与してください。
第三引数はC/C++ファイルの相対パスです。(ここではMakeFileと同じディレクトリに格納しているため、ファイル名だけになっています)

gradleの設定

Cファイルを読み込むためにはgradleで指定を行い、syncする必要があります。

app/build.gradle
android {
    ...
    externalNativeBuild {
        cmake {
            version '3.10.2'
            path "src/main/cpp/CMakeLists.txt"
        }
    }
}

sync後、Android Studio上にも先ほど追加したファイルが表示されるようになります。

Kotlin側の実装

soファイルのロードします。MakeFileで指定した第一引数の名前です。
このクラス実行時の一番最初にやりたいため、companion objectのinitで実行します。

MainActivity.kt
companion object {
  init {
      System.loadLibrary("jni-lib-name")
  }
}

ここで、soファイル名をtypoしたりするとこのファイルを呼んだタイミングで、soファイルがロードできないとエラーが出てクラッシュします。

最後に、ロードしたsoファイルから呼び出しを行います。関数名、戻り値はjni-sample.cで定義したとおりにします。

MainActivity.kt
private external fun stringFromJNI(): String

あとは、使いたいところで普通の関数としてstringFromJNI()を呼べます。

.gitignore

app/.externalNativeBuildを追加しておくと中間生成物をignoreできます。

References

公式ドキュメントも充実しています。
公式ドキュメント

16
10
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
10