Android 使用jni校验应用签名sha1值,防止so文件逆向盗用
来源:互联网 发布:获取windows 7密钥 编辑:程序博客网 时间:2024/06/01 08:05
在日常开发中,我们会把一些关键的算法与数据使用c++编写,然后打包成so文件使用。
下面举一个典型的例子
extern "C"JNIEXPORT jstring JNICALLJava_com_aizuzi_verificationdemo_MainActivity_getToken( JNIEnv *env, jobject, jstring userId) { char* cUserId = jstring2CStr(env,userId); char* code = "123456"; char* result = (char*)malloc((strlen(cUserId) + strlen(code) + 1)); memset(result,0,sizeof(result)); strcat(result,cUserId); strcat(result,code); return env->NewStringUTF(result);}
java调用
public native String getToken(String userId);
使用getToken(String userId)就能获取到加密处理后的token,这样看起来已经达到加密的要求了,反编译后也只能混淆处理后getToken方法,这样就能够确保数据万无一失了吗?too young too native!!!
因为反编译后已经知道我们的应用包名与方法参数,解压apk后so文件也非常容易的获取到,所以只要新建一个java类就能轻松的获取到so文件加密的数据了。
那我们怎样防止生成的so文件被其他人盗用呢?我们知道每个应用必须签名才能安装,这个签名只有我们内部人员才能获取,所以如果我们在so文件里能判断是否是正确的签名才返回,否则抛出异常,这就能解决so文件被盗用的问题了。
下面的例子我已经做成Demo上传到github,地址:
aizuzi/SignatureVerificationDemo
首先修改一下getToken方法,我们把上下文对象通过jni传递进去
public native String getToken(Context context,String userId);
c++层处理
extern "C"JNIEXPORT jstring JNICALLJava_com_aizuzi_verificationdemo_MainActivity_getToken( JNIEnv *env, jobject, jobject contextObject, jstring userId) { char *sha1 = getSha1(env,contextObject); jboolean result = checkValidity(env,sha1); if(result){ return env->NewStringUTF("获取Token成功"); }else{ return env->NewStringUTF("获取失败,请检查valid.cpp文件配置的sha1值"); }}
getSha1方法与checkValidity方法
//签名信息const char *app_sha1="81BA0CF9134C6415F34C3BCC854913A53C71415E";const char hexcode[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};char* getSha1(JNIEnv *env, jobject context_object){ //上下文对象 jclass context_class = env->GetObjectClass(context_object); //反射获取PackageManager jmethodID methodId = env->GetMethodID(context_class, "getPackageManager", "()Landroid/content/pm/PackageManager;"); jobject package_manager = env->CallObjectMethod(context_object, methodId); if (package_manager == NULL) { LOGD("package_manager is NULL!!!"); return NULL; } //反射获取包名 methodId = env->GetMethodID(context_class, "getPackageName", "()Ljava/lang/String;"); jstring package_name = (jstring)env->CallObjectMethod(context_object, methodId); if (package_name == NULL) { LOGD("package_name is NULL!!!"); return NULL; } env->DeleteLocalRef(context_class); //获取PackageInfo对象 jclass pack_manager_class = env->GetObjectClass(package_manager); methodId = env->GetMethodID(pack_manager_class, "getPackageInfo", "(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;"); env->DeleteLocalRef(pack_manager_class); jobject package_info = env->CallObjectMethod(package_manager, methodId, package_name, 0x40); if (package_info == NULL) { LOGD("getPackageInfo() is NULL!!!"); return NULL; } env->DeleteLocalRef(package_manager); //获取签名信息 jclass package_info_class = env->GetObjectClass(package_info); jfieldID fieldId = env->GetFieldID(package_info_class, "signatures", "[Landroid/content/pm/Signature;"); env->DeleteLocalRef(package_info_class); jobjectArray signature_object_array = (jobjectArray)env->GetObjectField(package_info, fieldId); if (signature_object_array == NULL) { LOGD("signature is NULL!!!"); return NULL; } jobject signature_object = env->GetObjectArrayElement(signature_object_array, 0); env->DeleteLocalRef(package_info); //签名信息转换成sha1值 jclass signature_class = env->GetObjectClass(signature_object); methodId = env->GetMethodID(signature_class, "toByteArray", "()[B"); env->DeleteLocalRef(signature_class); jbyteArray signature_byte = (jbyteArray) env->CallObjectMethod(signature_object, methodId); jclass byte_array_input_class=env->FindClass("java/io/ByteArrayInputStream"); methodId=env->GetMethodID(byte_array_input_class,"<init>","([B)V"); jobject byte_array_input=env->NewObject(byte_array_input_class,methodId,signature_byte); jclass certificate_factory_class=env->FindClass("java/security/cert/CertificateFactory"); methodId=env->GetStaticMethodID(certificate_factory_class,"getInstance","(Ljava/lang/String;)Ljava/security/cert/CertificateFactory;"); jstring x_509_jstring=env->NewStringUTF("X.509"); jobject cert_factory=env->CallStaticObjectMethod(certificate_factory_class,methodId,x_509_jstring); methodId=env->GetMethodID(certificate_factory_class,"generateCertificate",("(Ljava/io/InputStream;)Ljava/security/cert/Certificate;")); jobject x509_cert=env->CallObjectMethod(cert_factory,methodId,byte_array_input); env->DeleteLocalRef(certificate_factory_class); jclass x509_cert_class=env->GetObjectClass(x509_cert); methodId=env->GetMethodID(x509_cert_class,"getEncoded","()[B"); jbyteArray cert_byte=(jbyteArray)env->CallObjectMethod(x509_cert,methodId); env->DeleteLocalRef(x509_cert_class); jclass message_digest_class=env->FindClass("java/security/MessageDigest"); methodId=env->GetStaticMethodID(message_digest_class,"getInstance","(Ljava/lang/String;)Ljava/security/MessageDigest;"); jstring sha1_jstring=env->NewStringUTF("SHA1"); jobject sha1_digest=env->CallStaticObjectMethod(message_digest_class,methodId,sha1_jstring); methodId=env->GetMethodID(message_digest_class,"digest","([B)[B"); jbyteArray sha1_byte=(jbyteArray)env->CallObjectMethod(sha1_digest,methodId,cert_byte); env->DeleteLocalRef(message_digest_class); //转换成char jsize array_size=env->GetArrayLength(sha1_byte); jbyte* sha1 =env->GetByteArrayElements(sha1_byte,NULL); char *hex_sha=new char[array_size*2+1]; for (int i = 0; i <array_size ; ++i) { hex_sha[2*i]=hexcode[((unsigned char)sha1[i])/16]; hex_sha[2*i+1]=hexcode[((unsigned char)sha1[i])%16]; } hex_sha[array_size*2]='\0'; LOGD("hex_sha %s ",hex_sha); return hex_sha;}
jboolean checkValidity(JNIEnv *env,char *sha1){ //比较签名 if (strcmp(sha1,app_sha1)==0) { LOGD("验证成功"); return true; } LOGD("验证失败"); return false;}
阅读全文
0 0
- Android 使用jni校验应用签名sha1值,防止so文件逆向盗用
- android so 文件存私密数据,且防止 so文件未知应用盗用
- android so 文件存私密数据,且防止 so文件未知应用盗用
- 【我的Android进阶之旅】Android 如何防止 so库文件被未知应用盗用?
- Andorid jni本地校验应用签名(MD5/SHA1)
- Android-NDK-之so文件签名校验
- Android Studio查看应用签名文件,SHA1值
- Android逆向之115网盘5.3.0apk签名校验so破解并干掉长广告
- Android开发:使用JNI读取应用签名
- Android studio 查看应用MD5和SHA1值(应用签名)
- Android RSA 签名,使用 SHA1
- 获取android应用签名证书的SHA1,MD5,SHA256值
- Android Studio获取MD5和SHA1值(应用签名)
- Android App自定义签名文件的生成、查看SHA1值和使用
- 查看签名文件SHA1值
- Android逆向分析--so文件
- 关于android app签名文件获取sha1和MD值
- android studio生成签名文件,以及SHA1和MD5值
- elasticsearch集群快速上手搭建
- ExtJS 4.2 创建带复选框的树,并且有全选反选功能
- java并发编程学习4--forkJoin
- Android NDK开发三 JNI基础
- vue-resource和php跨域
- Android 使用jni校验应用签名sha1值,防止so文件逆向盗用
- Sift算子特征点提取、描述及匹配全流程解析
- constructor的使用 : 查看对象的构造函数
- coridc求atandmatlab仿真
- editText控件相关
- caffe学习 绘制loss和accuracy
- HDU-5882-Balanced Game 【奇偶】
- 黄金海岸『Gold Beach』之Wet'n Wild Water Park
- 数字信号分析——基础知识点总结