博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android jni加密
阅读量:6143 次
发布时间:2019-06-21

本文共 4098 字,大约阅读时间需要 13 分钟。

hot3.png

我们经常会有些敏感的信息需要客户端加解密,但android很容易被反编译,所以我们写在客户端里的密钥终究得不到安全,可能有人会想把加密方式写在C代码中,生成.so供APK使用,可是别人不关心你C里的代码,直接把你的so文件给拿去用就可以了,那么有没有一种安全的措施来加大难度呢,我说一下我们项目中如果解决客户端加密安全方案.

首先加密的代码仍然写在C代码中,至少C被反编译出来是汇编代码,加大阅读难度,另外一点就是如何让我们的.so文件只允许在我们自己的APK中使用,而不被别人拿去使用呢,这就需要签名验证这做一些文章,当程序调用.so时我们可以C代码中检查当前程序的签名是不是我们的,条件成立才进行加解密操作,当然签名泄露这个就另说了,毕竟没有百分百的安全,先来看看C代码 #include <string.h>

#include <jni.h>
#include <stdio.h>
#include <stdlib.h>
#include <android/log.h>

//LOG宏定义

#define LOG_TAG "JNI_SCRIPT"
#define LOG_E(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, VA_ARGS)

jstring JNICALL

Java_com_example_administrator_myapplication_Test_getScriptData( JNIEnv* env,jobject obj, jobject contextObj){
//根据传入的context对象获取getApplicationContext(),防止java中获取其它已安装APK的Context对象
jclass context_cls = (*env)->GetObjectClass(env,contextObj);
jmethodID applicationContextMethod = (*env)->GetMethodID(env, context_cls, "getApplicationContext", "()Landroid/content/Context;");
jobject applicationContext = (*env)->CallObjectMethod(env, contextObj, applicationContextMethod);
if (applicationContext == NULL) {
LOG_E("context invalid!!");
}

char *st = "com.example.administrator.myapplication"; //当前程序包名  //根据传入的context对象getPackageName  jmethodID pkgName_method = (*env)->GetMethodID(env, context_cls, "getPackageName", "()Ljava/lang/String;");  jstring pkgName = (*env)->CallObjectMethod(env, applicationContext, pkgName_method);  char *pkg = (*env)->GetStringUTFChars(env, pkgName, NULL);  //对比  if (strcmp(st, pkg) != 0) {      LOG_E("package name invalid!!");      return NULL;  }  // 获取PackageManager对象  jmethodID getPackageManager_method = (*env)->GetMethodID(env, context_cls, "getPackageManager", "()Landroid/content/pm/PackageManager;");  jobject packageManager = (*env)->CallObjectMethod(env, applicationContext, getPackageManager_method);  // PackageManager class  jclass packageManager_cls = (*env)->GetObjectClass(env, packageManager);  // 得到 getPackageInfo 方法  jmethodID getPackageInfo_method = (*env)->GetMethodID(env, packageManager_cls,                                              "getPackageInfo", "(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;");  // 获取PackageInfo类对象  jobject packageInfo = (*env)->CallObjectMethod(env, packageManager,                                                 getPackageInfo_method, pkgName, 64);  // 获取PackageInfo class  jclass packageInfo_cls = (*env)->GetObjectClass(env, packageInfo);  jfieldID signatures_field = (*env)->GetFieldID(env, packageInfo_cls, "signatures", "[Landroid/content/pm/Signature;");  jobjectArray signatures = (*env)->GetObjectField(env, packageInfo, signatures_field);  jobject signature = (*env)->GetObjectArrayElement(env, signatures, 0);  jclass signature_cls = (*env)->GetObjectClass(env, signature);  jmethodID hashcode_method = (*env)->GetMethodID(env, signature_cls, "hashCode", "()I");  int hashCode = (*env)->CallIntMethod(env, signature, hashcode_method);  // 检测apk签名的hashCode值,然后进行对比  if (hashCode != -1370002482) {      LOG_E("apk signature error,don not use this .so !!")  }  //上面条件都通过后可以进行加密算法处理,加密代码省略  //........  return "加密后的字符串";

}

java中代码 [java] view plain copy public class Test {

static{      System.loadLibrary("mylib");  }  public native String getScriptData(Context context);

}

上面的C的代码中我们从jni对API的反射来获取APK签名的hashCode值,第一步jni中接收Context对象,然后通过context对象获取getApplicationContext(),可能你会问我为什么要这么做,其实这一步是为了防止在java层传入恶意的context对象,打个比方,我们的程序叫A,恶意者的程序叫B,如果恶意者把A和B都安在手机中,那么在B程序中完全可以获取A程序的Context对象,这样一旦把A程序的Context对象传入jni中,我们的检测是通过的,恶意者是怎么能够在它的B程序中获取A程序的Context对象呢?下面一条语句就可以完成: [java] view plain copy Context thirdContext = createPackageContext("A程序的包名", Context.CONTEXT_IGNORE_SECURITY|Context.CONTEXT_INCLUDE_CODE);

是不是很容易,不过不用担心,虽然在B程序中通过上面代码获取A的Context,但我们只要用thirdContext.getApplicationContext()会返回null,所以我们在调用jni中第一步就是先获取一下ApplicationContext对象

第一步通过后,第二步获取当前程序的包名,进行对比,包名相同后接下来我们就要获取so的调用者程序的签名了,这一步就是安全的关键性所在,如果以上条件都通过了,逻辑就到了我们进行加解密的地方。

其实我在签名判断完后,又在安全性上做了一些小的手脚,比如判断我们工程下某些java类是不是存在,这些类中某些方法是不是存在,这样及时签名被泄露后恶意者也要把项目中的一些类、方法全部一模一样的保留才能使用我们的.so库文件,又增加一些复杂度。安全没有十全十美,我们能做的就是尽量加大恶意者的破坏难度。

转载于:https://my.oschina.net/u/2963604/blog/1612860

你可能感兴趣的文章