`

在ndk中获取apk签名文件的MD5值

 
阅读更多

最近在弄ndk,需要做一个用纯C校验签名的功能,也看了一些帖子,主要是参考下面两个:

主要思路是参考这个帖子,java代码和c代码都是,但是这个帖子里有几个小错误

http://blog.csdn.net/lgl1170860350/article/details/46348965

有的地方看了下这个帖:

http://blog.csdn.net/leifengpeng/article/details/52681196

因为同时用的是unity3D,没法传context参数给我,还顺便研究了下怎么获取context,参考贴:

http://blog.csdn.net/xiaogazhang/article/details/46891139

 

我的代码:

	bool soulgameCheckMD5InPureC(jobject context,JNIEnv *env){
		SGLOGD("soulgameCheckMD5InPureC() begin!");

		//
		jclass tem_class;
		jmethodID tem_method;
		jclass class_context = env->GetObjectClass(context);

		//PackageInfo localPackageInfo = context.getPackageManager()
		tem_method = env->GetMethodID(class_context, "getPackageManager", "()Landroid/content/pm/PackageManager;");
		jobject obj_package_manager = env->CallObjectMethod(context, tem_method);
		if(obj_package_manager == NULL){
			SGLOGD("soulgameCheckMD5InPureC() getPackageManager failed!");
			return false;
		}

		// getPackageName
		tem_method = env->GetMethodID(class_context, "getPackageName", "()Ljava/lang/String;");
		jobject obj_package_name = env->CallObjectMethod(context, tem_method);
		env->DeleteLocalRef(class_context);
		env->DeleteLocalRef(context);
		if(obj_package_name == NULL){
			SGLOGD("soulgameCheckMD5InPureC() getPackageName failed!");
			return false;
		}

		// getPackageInfo
		tem_class = env->GetObjectClass(obj_package_manager);
		tem_method = env->GetMethodID(tem_class, "getPackageInfo", "(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;");
		jobject obj_package_info = env->CallObjectMethod(obj_package_manager, tem_method, obj_package_name, 64);
		env->DeleteLocalRef(obj_package_name);
		env->DeleteLocalRef(obj_package_manager);
		if(obj_package_info == NULL){
			SGLOGD("soulgameCheckMD5InPureC() getPackageInfo failed!");
			return false;
		}

		// Signature[] arrayOfSignature = localPackageInfo.signatures;
		tem_class = env->GetObjectClass(obj_package_info);
		jfieldID fieldID_signatures = env->GetFieldID(tem_class, "signatures", "[Landroid/content/pm/Signature;");
		// Signature localSignature = arrayOfSignature[0];
		jobject signatur = env->GetObjectField(obj_package_info, fieldID_signatures);
		jobjectArray signatures = (jobjectArray)(signatur);
		jobject signature = env->GetObjectArrayElement(signatures, 0);
		env->DeleteLocalRef(signatures);
		env->DeleteLocalRef(obj_package_info);
		if(signatur == NULL){
			SGLOGD("soulgameCheckMD5InPureC() signatures failed!");
			return false;
		}

		// localSignature.toByteArray()
		tem_class = env->GetObjectClass(signature);
		tem_method = env->GetMethodID(tem_class, "toByteArray", "()[B");
		jobject obj_sign_byte_array = env->CallObjectMethod(signature, tem_method);// 这个就是拿到的签名byte数组
		env->DeleteLocalRef(signature);
		env->DeleteLocalRef(tem_class);
		if(obj_sign_byte_array == NULL){
			SGLOGD("soulgameCheckMD5InPureC() toByteArray failed!");
			return false;
		}

		// MessageDigest localMessageDigest = MessageDigest.getInstance("MD5");
		jclass class_MessageDigest = env->FindClass( "java/security/MessageDigest");
		tem_method = env->GetStaticMethodID( class_MessageDigest, "getInstance", "(Ljava/lang/String;)Ljava/security/MessageDigest;");
		jobject obj_md5 = env->CallStaticObjectMethod( class_MessageDigest, tem_method, env->NewStringUTF("md5"));
		if(obj_md5 == NULL){
			SGLOGD("soulgameCheckMD5InPureC() getInstance failed!");
			return false;
		}

		// localMessageDigest.update(localSignature.toByteArray());
		tem_method = env->GetMethodID(class_MessageDigest, "update", "([B)V");// 这个函数的返回值是void,写V
		env->CallVoidMethod(obj_md5, tem_method, obj_sign_byte_array);
		env->DeleteLocalRef(obj_sign_byte_array);

		// localMessageDigest.digest()
		tem_method = env->GetMethodID(class_MessageDigest, "digest", "()[B");
		// 这个是md5以后的byte数组,现在只要将它转换成16进制字符串,就可以和之前的比较了
		jbyteArray obj_array_sign = (jbyteArray)env->CallObjectMethod(obj_md5, tem_method);// jni中有强转类型的概念吗
		env->DeleteLocalRef(obj_md5);
		env->DeleteLocalRef(class_MessageDigest);
		if(obj_array_sign == NULL){
			SGLOGD("soulgameCheckMD5InPureC() digest failed!");
			return false;
		}

		// 尝试用c写一下:http://blog.csdn.net/pingd/article/details/41945417
		jsize int_array_length = env->GetArrayLength(obj_array_sign);
		jbyte* byte_array_elements = env->GetByteArrayElements(obj_array_sign, NULL);
		char* char_result = (char*) malloc(int_array_length*2+1);// 开始没有+1,在有的情况下会越界产生问题,还是在后面补上\0比较好

		// 将byte数组转换成16进制字符串,发现这里不用强转,jbyte和unsigned char应该字节数是一样的
		ByteToHexStr((unsigned char*)byte_array_elements, char_result, int_array_length);
		*(char_result+int_array_length*2) = '\0';// 在末尾补\0
//		jstring string_result = env->NewStringUTF(char_result);
//		env->DeleteLocalRef(string_result);

		// release
		env->ReleaseByteArrayElements( obj_array_sign, byte_array_elements, JNI_ABORT);
		env->DeleteLocalRef(obj_array_sign);

		//校验
		const char* pWhiteObject;
		bool bIsMD5Right;
		int nIndex = 0;
		int nLen = sizeof(pMD5WhiteList)/4;
		for(nIndex = 0;nIndex<nLen;nIndex++){
			pWhiteObject = pMD5WhiteList[nIndex];
			if( strcmp(char_result,pWhiteObject) == 0 ){
				break;
			}
		}
		if(nIndex<nLen){
			bIsMD5Right = true;
		}else{
			bIsMD5Right = false;
		}

		// 释放指针使用free
		free(char_result);

		SGLOGD("soulgameCheckMD5InPureC() finish!");
		if(bIsMD5Right){
			return true;
		}else{
			return false;
		}
	}

 

 

分享到:
评论

相关推荐

    JniCheckSign:一个使用ndk检查签名md5值,防止其他人使用.so文件的演示

    首先,项目会获取当前应用的签名MD5值,这个值可以在应用的APK打包过程中获取。然后,它将此MD5值与.so文件中预存的签名值进行比较。如果两者匹配,说明.so文件正在正确的应用环境中运行;如果不匹配,则表明可能有...

    Diff:Android NDK开发之旅18--NDK--Apk增量更新原始码

    例如,可以使用MD5或SHA-1等哈希算法计算每个文件的指纹,然后比较新旧两个版本中文件指纹的差异,找出需要更新的部分。 为了实现这个功能,我们需要编写C/C++代码来处理文件操作和哈希计算。在Diff-master这个项目...

    APK自我保护方法探讨

    - **MD5校验**:计算整个APK文件的MD5值,并与预设值进行比较。 - **SHA-1校验**:更安全的方式是使用SHA-1算法计算APK的哈希值。 #### 六、Java反射防御 Java反射允许程序在运行时动态访问类和对象,这也可能被...

    android 增量升级DEMO

    随着APP的越来越大,增量升级已是必不可少...通过计算MD5值,判断合并的与新的APP是不是相同的文件,签名时候和已安装客户端是否一致,如一致,提示用户安装,实现分分钟的升级。采集SO方式 ,直接方便调用 ,无须NDK。

    2010年谢彦的android笔记

    - **C库打包进APK**:将C库文件嵌入到APK中,以便在应用中使用。 #### 3.4 典型应用 - **语音合成**:TTS(Text To Speech)技术的实现方法。 - **语音识别**:通过Intent或调用库的方式实现语音输入。 - **人脸识别*...

    android笔记.rar

    3.2.7 Android自带的md5 校验 ... ..61 3.2.8 将数据打进apk包 ... ..63 3.2.9 如何改变窗口的标题栏的布局 ... .66 3.2.10 动态改变控件大小... ...67 3.2.11 缩放drawable ... ...68 2 3.2.12 解析apk...

Global site tag (gtag.js) - Google Analytics