最近在做代码安全方面的工作,发现一些关键信息如:密钥、加密策略等直接写死在项目代码中,存在代码安全隐患。本文档提供一种示例:把关键信息,保存在native层;并对安装包关联信息进行校验,防止反编译、重签名导致信息泄露的可能。
private String getSign1() {try {//通过PackageManager获取PackageManager pm = getPackageManager();PackageInfo pi = pm.getPackageInfo(getPackageName(), PackageManager.GET_SIGNATURES);Signature[] signatures = pi.signatures;Signature signature0 = signatures[0];return signature0.toCharsString();} catch (Exception e) {e.printStackTrace();return "";}}private String getSign2() {try {// 下面几行代码展示如何任意获取Context对象,在jni中也可以使用这种方式Class> activityThreadClz = Class.forName("android.app.ActivityThread");Method currentApplication = activityThreadClz.getMethod("currentApplication");Application application = (Application) currentApplication.invoke(null);PackageManager pm = application.getPackageManager();PackageInfo pi = pm.getPackageInfo(application.getPackageName(), PackageManager.GET_SIGNATURES);Signature[] signatures = pi.signatures;Signature signature0 = signatures[0];return signature0.toCharsString();} catch (Exception e) {e.printStackTrace();return "";}}
static int verifySign(JNIEnv *env) {// Application objectjobject application = getApplication(env);if (application == NULL) {return JNI_ERR;}// Context(ContextWrapper) classjclass context_clz = env->GetObjectClass(application);// getPackageManager()jmethodID getPackageManager = env->GetMethodID(context_clz, "getPackageManager","()Landroid/content/pm/PackageManager;");// android.content.pm.PackageManager objectjobject package_manager = env->CallObjectMethod(application, getPackageManager);// PackageManager classjclass package_manager_clz = env->GetObjectClass(package_manager);// getPackageInfo()jmethodID getPackageInfo = env->GetMethodID(package_manager_clz, "getPackageInfo","(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;");// context.getPackageName()jmethodID getPackageName = env->GetMethodID(context_clz, "getPackageName","()Ljava/lang/String;");// call getPackageName() and cast from jobject to jstringjstring package_name = (jstring) (env->CallObjectMethod(application, getPackageName));// PackageInfo objectjobject package_info = env->CallObjectMethod(package_manager, getPackageInfo, package_name, 64);// class PackageInfojclass package_info_clz = env->GetObjectClass(package_info);// field signaturesjfieldID signatures_field = env->GetFieldID(package_info_clz, "signatures","[Landroid/content/pm/Signature;");jobject signatures = env->GetObjectField(package_info, signatures_field);jobjectArray signatures_array = (jobjectArray) signatures;jobject signature0 = env->GetObjectArrayElement(signatures_array, 0);jclass signature_clz = env->GetObjectClass(signature0);jmethodID toCharsString = env->GetMethodID(signature_clz, "toCharsString","()Ljava/lang/String;");// call toCharsString()jstring signature_str = (jstring) (env->CallObjectMethod(signature0, toCharsString));// releaseenv->DeleteLocalRef(application);env->DeleteLocalRef(context_clz);env->DeleteLocalRef(package_manager);env->DeleteLocalRef(package_manager_clz);env->DeleteLocalRef(package_name);env->DeleteLocalRef(package_info);env->DeleteLocalRef(package_info_clz);env->DeleteLocalRef(signatures);env->DeleteLocalRef(signature0);env->DeleteLocalRef(signature_clz);//获取到安装的APK对应的签名const char *sign = env->GetStringUTFChars(signature_str, NULL);if (sign == NULL) {LOGE("分配内存失败");return JNI_ERR;}// LOGI("应用中读取到的签名为:%s", sign);int result_debug = strcmp(sign, SIGN_Debug);int result_release = strcmp(sign, SIGN_Release);// 使用之后要释放这段内存env->ReleaseStringUTFChars(signature_str, sign);env->DeleteLocalRef(signature_str);if (result_debug == 0 || result_release == 0) { // 签名一致return JNI_OK;}return JNI_ERR;
}
void Java_com_ankerwork_ctool_Security_setCheckSign(JNIEnv *env, jclass clazz, jboolean is_check) {unsigned char b = is_check;LOGI("/n is_check: %lu ", b);if (b) {isCheck = true;} else {isCheck = false;}
}
找到Module对应的Task,执行 执行assembleRelease
如:
repositories {flatDir {dirs 'libs'}
}
dependencies {compile(name:'XXX', ext:'aar')
}
参考1.1方法
定义变量如:
static const char *sign = "1111"
public class Security {static {System.loadLibrary("selfsecurity");}public static native String getIjmSecret();public static native void setCheckSign(boolean isCheck);
}Security.setCheckSign(true);//设置校验签名
Security.getIjmSecret()
完整代码链接:https://download.csdn.net/download/fepengwang/87594007