|
|
@@ -0,0 +1,337 @@
|
|
|
+#include<jni.h>
|
|
|
+#include<stdio.h>
|
|
|
+#include<string.h>
|
|
|
+//导入我们创建的头文件
|
|
|
+#include "com_sheep_gamegroup_util_PngUtil.h"
|
|
|
+//全局获取Context
|
|
|
+jobject getGlobalContext(JNIEnv *env);
|
|
|
+//根据Context获取对应安装的apk文件的md5值
|
|
|
+char* getSignatureMd5(JNIEnv * env, jobject obj_package_manager, jobject obj_package_name);
|
|
|
+//根据Context获取对应安装的apk文件的hashCode值
|
|
|
+//jint getSignatureHashCode(JNIEnv* env, jobject obj_package_manager, jobject obj_package_name);
|
|
|
+// 字节流转换为十六进制字符串
|
|
|
+void ByteToHexStr(const unsigned char* source, char* dest, int sourceLen);
|
|
|
+//调用android toast
|
|
|
+void android_toast(JNIEnv *env, jobject context, jstring str);
|
|
|
+//判断java String 与c String 是否相同
|
|
|
+int j_str_cmp_c_str(JNIEnv *env, jstring jStr, char* cStr);
|
|
|
+//合并字符串
|
|
|
+jstring android_string_concat(JNIEnv *env, jstring jStr, char* cStr);
|
|
|
+//合并字符串
|
|
|
+jstring android_string_concat_string(JNIEnv *env, jstring jStr, jstring jStr2);
|
|
|
+//根据Context获取PackageManager
|
|
|
+jobject getPackageManager(JNIEnv * env, jobject context);
|
|
|
+//根据Context获取对应的包名
|
|
|
+jobject getPackageName(JNIEnv * env, jobject context);
|
|
|
+
|
|
|
+/*
|
|
|
+ * cd app\src\main
|
|
|
+ * ndk-build
|
|
|
+ * Class: com_sheep_gamegroup_util_PngUtil
|
|
|
+ * Method: isKfzsSheepApp
|
|
|
+ * Signature: ()Ljava/lang/String;
|
|
|
+ */
|
|
|
+JNIEXPORT jstring JNICALL Java_com_sheep_gamegroup_util_PngUtil_isKfzsSheepApp
|
|
|
+ (JNIEnv *env, jclass jclassp){
|
|
|
+ jobject context = getGlobalContext(env);
|
|
|
+ if(context == NULL){
|
|
|
+ return (*env)->NewStringUTF(env, "error context is NULL");
|
|
|
+ }
|
|
|
+ jobject obj_package_manager = getPackageManager(env, context);
|
|
|
+ jobject obj_package_name = getPackageName(env, context);
|
|
|
+ char* md5 = getSignatureMd5(env, obj_package_manager, obj_package_name);
|
|
|
+ //result已经释放
|
|
|
+ if(strcmp(md5, "C69316882EADA62AE560C31076740400") == 0){
|
|
|
+ android_toast(env, context, (*env)->NewStringUTF(env, "恭喜,您使用的是正版小绵羊!"));
|
|
|
+ } else {
|
|
|
+ android_toast(env, context, (*env)->NewStringUTF(env, "注意,您使用的不是正版小绵羊!"));
|
|
|
+ return (*env)->NewStringUTF(env, "error this is pirate app");
|
|
|
+ }
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+/*
|
|
|
+ * Class: com_sheep_gamegroup_util_PngUtil
|
|
|
+ * Method: decodePng
|
|
|
+ * Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
|
|
|
+ */
|
|
|
+JNIEXPORT jstring JNICALL Java_com_sheep_gamegroup_util_PngUtil_decodePng
|
|
|
+ (JNIEnv *env, jclass jclassp, jstring filePath, jstring gamePackageName, jstring comment){
|
|
|
+ jobject context = getGlobalContext(env);
|
|
|
+ if(context == NULL){
|
|
|
+ return (*env)->NewStringUTF(env, "error context is NULL");
|
|
|
+ }
|
|
|
+ jobject obj_package_manager = getPackageManager(env, context);
|
|
|
+ jobject obj_package_name = getPackageName(env, context);
|
|
|
+ char* md5 = getSignatureMd5(env, obj_package_manager, obj_package_name);
|
|
|
+ //result已经释放
|
|
|
+ if(strcmp(md5, "C69316882EADA62AE560C31076740400") == 0){
|
|
|
+ // android_toast(env, context, (*env)->NewStringUTF(env, "恭喜,您使用的是正版小绵羊!"));
|
|
|
+ } else {
|
|
|
+// android_toast(env, context, (*env)->NewStringUTF(env, "注意,您使用的不是正版小绵羊!"));
|
|
|
+ return (*env)->NewStringUTF(env, "error this is pirate app");
|
|
|
+ }
|
|
|
+ char* gameMd5 = getSignatureMd5(env, obj_package_manager, gamePackageName);
|
|
|
+
|
|
|
+ //加密文本内容:包名;签名md5;试玩应用包名;试玩应用签名md5;任务id;图片总数;图片位置
|
|
|
+
|
|
|
+ jstring result_a;
|
|
|
+ jstring result_b;
|
|
|
+ result_a = android_string_concat(env, obj_package_name, ";");
|
|
|
+ (*env)->DeleteLocalRef(env, obj_package_name);
|
|
|
+ result_b = android_string_concat(env, result_a, md5);
|
|
|
+ (*env)->DeleteLocalRef(env, result_a);
|
|
|
+ result_a = android_string_concat(env, result_b, ";");
|
|
|
+ (*env)->DeleteLocalRef(env, result_b);
|
|
|
+ result_b = android_string_concat_string(env, result_a, gamePackageName);
|
|
|
+ (*env)->DeleteLocalRef(env, result_a);
|
|
|
+ result_a = android_string_concat(env, result_b, ";");
|
|
|
+ (*env)->DeleteLocalRef(env, result_b);
|
|
|
+ result_b = android_string_concat(env, result_a, gameMd5);
|
|
|
+ (*env)->DeleteLocalRef(env, result_a);
|
|
|
+ result_a = android_string_concat(env, result_b, ";");
|
|
|
+ (*env)->DeleteLocalRef(env, result_b);
|
|
|
+
|
|
|
+ result_b = android_string_concat_string(env, result_a, comment);
|
|
|
+ (*env)->DeleteLocalRef(env, result_a);
|
|
|
+// android_toast(env, context, result_b);
|
|
|
+
|
|
|
+ //rsa公钥加密
|
|
|
+ jclass kfzssafeClass = (*env)->FindClass(env, "go/kfzssafe/Kfzssafe");
|
|
|
+ jmethodID publicEncryptMethodID = (*env)->GetStaticMethodID(env, kfzssafeClass,"publicEncrypt","(Ljava/lang/String;)Ljava/lang/String;");
|
|
|
+ result_a = (*env)->CallStaticObjectMethod(env, kfzssafeClass, publicEncryptMethodID, result_b);
|
|
|
+ (*env)->DeleteLocalRef(env, result_b);
|
|
|
+
|
|
|
+// JNIDecodePngUtil.addIEndData(file, result_a);
|
|
|
+
|
|
|
+ jmethodID addIEndDataMethodID = (*env)->GetStaticMethodID(env, kfzssafeClass,"addIEndData2","(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;");
|
|
|
+ jstring result = (*env)->CallStaticObjectMethod(env, kfzssafeClass, addIEndDataMethodID, filePath, result_a);
|
|
|
+ (*env)->DeleteLocalRef(env, result_a);
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ free(md5);
|
|
|
+ free(gameMd5);
|
|
|
+ (*env)->DeleteLocalRef(env, gamePackageName);
|
|
|
+ (*env)->DeleteLocalRef(env, obj_package_manager);
|
|
|
+ (*env)->DeleteLocalRef(env, context);
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+//合并字符串
|
|
|
+jstring android_string_concat(JNIEnv *env, jstring jStr, char* cStr){
|
|
|
+ jclass String_clazz = (*env)->FindClass(env, "java/lang/String");
|
|
|
+ jmethodID concat_methodID = (*env)->GetMethodID(env, String_clazz, "concat", "(Ljava/lang/String;)Ljava/lang/String;");
|
|
|
+ //需要在后面拼接的字符串...
|
|
|
+ jstring strEnd = (*env)->NewStringUTF(env, cStr);
|
|
|
+ jstring result = (*env)->CallObjectMethod(env, jStr, concat_methodID, strEnd);
|
|
|
+ //释放内存
|
|
|
+ (*env)->DeleteLocalRef(env, strEnd);
|
|
|
+ return result;
|
|
|
+}
|
|
|
+//合并字符串
|
|
|
+jstring android_string_concat_string(JNIEnv *env, jstring jStr, jstring jStr2){
|
|
|
+ jclass String_clazz = (*env)->FindClass(env, "java/lang/String");
|
|
|
+ jmethodID concat_methodID = (*env)->GetMethodID(env, String_clazz, "concat", "(Ljava/lang/String;)Ljava/lang/String;");
|
|
|
+ jstring result = (*env)->CallObjectMethod(env, jStr, concat_methodID, jStr2);
|
|
|
+ return result;
|
|
|
+}
|
|
|
+ //判断java String 与c String 是否相同
|
|
|
+int j_str_cmp_c_str(JNIEnv *env, jstring jStr, char* cStr){
|
|
|
+ const char *jStrToCStr = (*env)->GetStringUTFChars(env, jStr, 0);
|
|
|
+ int result = strcmp(jStrToCStr, cStr);
|
|
|
+ (*env)->ReleaseStringUTFChars(env, jStr, jStrToCStr);
|
|
|
+ return result;
|
|
|
+}
|
|
|
+//调用android toast
|
|
|
+void android_toast(JNIEnv *env, jobject context, jstring str){
|
|
|
+ jclass tclss = (*env)->FindClass(env, "android/widget/Toast");
|
|
|
+ jmethodID mid = (*env)->GetStaticMethodID(env, tclss,"makeText","(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;");
|
|
|
+ jobject job = (*env)->CallStaticObjectMethod(env, tclss,mid,context,str);
|
|
|
+ jmethodID showId = (*env)->GetMethodID(env, tclss,"show","()V");
|
|
|
+ (*env)->CallVoidMethod(env, job,showId,context,str);
|
|
|
+}
|
|
|
+//获取Context
|
|
|
+jobject getGlobalContext(JNIEnv *env)
|
|
|
+{
|
|
|
+ //获取Activity Thread的实例对象
|
|
|
+ jclass activityThread = (*env)->FindClass(env, "android/app/ActivityThread");
|
|
|
+ jmethodID currentActivityThread = (*env)->GetStaticMethodID(env, activityThread, "currentActivityThread", "()Landroid/app/ActivityThread;");
|
|
|
+ jobject at = (*env)->CallStaticObjectMethod(env, activityThread, currentActivityThread);
|
|
|
+ //获取Application,也就是全局的Context
|
|
|
+ jmethodID getApplication = (*env)->GetMethodID(env, activityThread, "getApplication", "()Landroid/app/Application;");
|
|
|
+ jobject context = (*env)->CallObjectMethod(env, at, getApplication);
|
|
|
+ return context;
|
|
|
+}
|
|
|
+
|
|
|
+// 字节流转换为十六进制字符串
|
|
|
+//http://blog.csdn.net/pingd/article/details/41945417
|
|
|
+void ByteToHexStr(const unsigned char* source, char* dest, int sourceLen)
|
|
|
+{
|
|
|
+ short i;
|
|
|
+ unsigned char highByte, lowByte;
|
|
|
+
|
|
|
+ for (i = 0; i < sourceLen; i++)
|
|
|
+ {
|
|
|
+ highByte = source[i] >> 4;
|
|
|
+ lowByte = source[i] & 0x0f;
|
|
|
+
|
|
|
+ highByte += 0x30;
|
|
|
+
|
|
|
+ if (highByte > 0x39)
|
|
|
+ dest[i * 2] = highByte + 0x07;
|
|
|
+ else
|
|
|
+ dest[i * 2] = highByte;
|
|
|
+
|
|
|
+ lowByte += 0x30;
|
|
|
+ if (lowByte > 0x39)
|
|
|
+ dest[i * 2 + 1] = lowByte + 0x07;
|
|
|
+ else
|
|
|
+ dest[i * 2 + 1] = lowByte;
|
|
|
+ }
|
|
|
+ return;
|
|
|
+}
|
|
|
+//根据Context获取PackageManager
|
|
|
+jobject getPackageManager(JNIEnv * env, jobject context) {
|
|
|
+ jclass class_context = (*env)->GetObjectClass(env, context);
|
|
|
+ jmethodID tem_method = (*env)->GetMethodID(env, class_context, "getPackageManager", "()Landroid/content/pm/PackageManager;");
|
|
|
+ jobject obj_package_manager = (*env)->CallObjectMethod(env, context, tem_method);
|
|
|
+ return obj_package_manager;
|
|
|
+}
|
|
|
+//根据Context获取对应的包名
|
|
|
+jobject getPackageName(JNIEnv * env, jobject context) {
|
|
|
+ jclass class_context = (*env)->GetObjectClass(env, context);
|
|
|
+ // getPackageName
|
|
|
+ jmethodID tem_method = (*env)->GetMethodID(env, class_context, "getPackageName", "()Ljava/lang/String;");
|
|
|
+ jobject obj_package_name = (*env)->CallObjectMethod(env, context, tem_method);
|
|
|
+ return obj_package_name;
|
|
|
+}
|
|
|
+//根据Context获取对应安装的apk文件的md5值
|
|
|
+//TODO 这个方法中,获取PackageInfo可能会报错,直接挂掉,因为没有安装应用
|
|
|
+char* getSignatureMd5(JNIEnv * env, jobject obj_package_manager, jobject obj_package_name) {
|
|
|
+ jclass tem_class;
|
|
|
+ jmethodID tem_method;
|
|
|
+ // getPackageInfo
|
|
|
+ tem_class = (*env)->GetObjectClass(env, obj_package_manager);
|
|
|
+ tem_method = (*env)->GetMethodID(env, tem_class, "getPackageInfo", "(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;");
|
|
|
+ jobject obj_package_info = (*env)->CallObjectMethod(env, obj_package_manager, tem_method, obj_package_name, 64);
|
|
|
+
|
|
|
+ // Signature[] arrayOfSignature = localPackageInfo.signatures;
|
|
|
+ // Signature localSignature = arrayOfSignature[0];
|
|
|
+ tem_class = (*env)->GetObjectClass(env, obj_package_info);
|
|
|
+ jfieldID fieldID_signatures = (*env)->GetFieldID(env, tem_class, "signatures", "[Landroid/content/pm/Signature;");
|
|
|
+ jobjectArray signatures = (*env)->GetObjectField(env, obj_package_info, fieldID_signatures);
|
|
|
+ jobject signature = (*env)->GetObjectArrayElement(env, signatures, 0);
|
|
|
+ // localSignature.toByteArray()
|
|
|
+ tem_class = (*env)->GetObjectClass(env, signature);
|
|
|
+ tem_method = (*env)->GetMethodID(env, tem_class, "toByteArray", "()[B");
|
|
|
+ jobject obj_sign_byte_array = (*env)->CallObjectMethod(env, signature, tem_method);// 这个就是拿到的签名byte数组
|
|
|
+
|
|
|
+ // MessageDigest localMessageDigest = MessageDigest.getInstance("MD5");
|
|
|
+ jclass class_MessageDigest = (*env)->FindClass(env, "java/security/MessageDigest");
|
|
|
+ tem_method = (*env)->GetStaticMethodID(env, class_MessageDigest, "getInstance", "(Ljava/lang/String;)Ljava/security/MessageDigest;");
|
|
|
+ jobject obj_md5 = (*env)->CallStaticObjectMethod(env, class_MessageDigest, tem_method, (*env)->NewStringUTF(env, "md5"));
|
|
|
+ // localMessageDigest.update(localSignature.toByteArray());
|
|
|
+ //tem_class = (*env)->GetObjectClass(env, obj_md5);
|
|
|
+ tem_method = (*env)->GetMethodID(env, class_MessageDigest, "update", "([B)V");// 这个函数的返回值是void,写V
|
|
|
+ (*env)->CallVoidMethod(env, obj_md5, tem_method, obj_sign_byte_array);
|
|
|
+ // localMessageDigest.digest()
|
|
|
+ tem_method = (*env)->GetMethodID(env, class_MessageDigest, "digest", "()[B");
|
|
|
+ // 这个是md5以后的byte数组,现在只要将它转换成16进制字符串,就可以和之前的比较了
|
|
|
+ jobject obj_array_sign = (*env)->CallObjectMethod(env, obj_md5, tem_method);// jni中有强转类型的概念吗
|
|
|
+ // // 这个就是签名的md5值
|
|
|
+ // String str2 = toHex(localMessageDigest.digest());
|
|
|
+
|
|
|
+ // 尝试用c写一下:http://blog.csdn.net/pingd/article/details/41945417
|
|
|
+ jsize int_array_length = (*env)->GetArrayLength(env, obj_array_sign);
|
|
|
+ jbyte* byte_array_elements = (*env)->GetByteArrayElements(env, obj_array_sign, JNI_FALSE);
|
|
|
+ char* char_result = (char*) malloc(int_array_length*2+1);// 开始没有+1,在有的情况下会越界产生问题,还是在后面补上\0比较好
|
|
|
+ // 将byte数组转换成16进制字符串,发现这里不用强转,jbyte和unsigned char应该字节数是一样的
|
|
|
+ ByteToHexStr(byte_array_elements, char_result, int_array_length);
|
|
|
+ *(char_result+int_array_length*2) = '\0';// 在末尾补\0
|
|
|
+ // release
|
|
|
+ (*env)->ReleaseByteArrayElements(env, obj_array_sign, byte_array_elements, JNI_ABORT);
|
|
|
+ return char_result;
|
|
|
+
|
|
|
+
|
|
|
+ //java code=======================================================
|
|
|
+ // PackageInfo localPackageInfo = context.getPackageManager()
|
|
|
+ // .getPackageInfo(context.getPackageName(), 64);
|
|
|
+ // StringBuilder localStringBuilder = new StringBuilder();
|
|
|
+ // Signature[] arrayOfSignature = localPackageInfo.signatures;
|
|
|
+ // Signature localSignature = arrayOfSignature[0];
|
|
|
+ // MessageDigest localMessageDigest = MessageDigest.getInstance("MD5");
|
|
|
+ // localMessageDigest.update(localSignature.toByteArray());
|
|
|
+ // // 这个就是签名的md5值
|
|
|
+ // String str2 = toHex(localMessageDigest.digest());
|
|
|
+ // localStringBuilder.append("Signature of ")
|
|
|
+ // .append(localPackageInfo.packageName).append('\n').append(str2);
|
|
|
+ // System.out.println(localStringBuilder.toString());
|
|
|
+ // TextView tv = (TextView) findViewById(R.id.tv);
|
|
|
+ // tv.setText(localStringBuilder.toString());
|
|
|
+
|
|
|
+
|
|
|
+ // private String toHex(byte[] paramArrayOfByte) {
|
|
|
+ // StringBuffer localStringBuffer = new StringBuffer();
|
|
|
+ // for (int i = 0; i < paramArrayOfByte.length; i++) {
|
|
|
+ // Object[] arrayOfObject = new Object[1];
|
|
|
+ // arrayOfObject[0] = Byte.valueOf(paramArrayOfByte[i]);
|
|
|
+ // localStringBuffer.append(String.format("%02x", arrayOfObject));
|
|
|
+ // }
|
|
|
+ // return localStringBuffer.toString();
|
|
|
+ // }
|
|
|
+ //java code======================================================
|
|
|
+}
|
|
|
+/**
|
|
|
+*校验APP包名和签名是否合法返回值为1表示合法
|
|
|
+*/
|
|
|
+// jint getSignatureHashCode(JNIEnv* env, jobject packageManager, jobject application_package){
|
|
|
+// // //获得PackageManager类
|
|
|
+// jclass packageManager_clazz=(*env)->GetObjectClass(env,packageManager);
|
|
|
+//
|
|
|
+// //得到getPackageInfo方法的ID
|
|
|
+// jmethodID methodID_getPackageInfo=(*env)->GetMethodID(env,packageManager_clazz,"getPackageInfo",
|
|
|
+// "(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;");
|
|
|
+//
|
|
|
+// // //得到getPackageName方法的ID
|
|
|
+// jmethodID methodID_getPackageName = (*env)->GetMethodID(env,context_clazz,"getPackageName","()Ljava/lang/String;");
|
|
|
+//
|
|
|
+//
|
|
|
+// //获得PackageInfo
|
|
|
+// jobject packageInfo = (*env)->CallObjectMethod(env,packageManager,methodID_getPackageInfo,application_package,64);
|
|
|
+// jclass packageinfo_clazz = (*env)->GetObjectClass(env,packageInfo);
|
|
|
+//
|
|
|
+// //获取签名
|
|
|
+// jfieldID fieldID_signatures = (*env)->GetFieldID(env,packageinfo_clazz,"signatures","[Landroid/content/pm/Signature;");
|
|
|
+// jobjectArray signature_arr = (jobjectArray)(*env)->GetObjectField(env,packageInfo,fieldID_signatures);
|
|
|
+//
|
|
|
+// //Signature数组中取出第一个元素
|
|
|
+// jobject signature = (*env)->GetObjectArrayElement(env,signature_arr,0);
|
|
|
+//
|
|
|
+// //读signature的hashcode
|
|
|
+// jclass signature_clazz = (*env)->GetObjectClass(env,signature);
|
|
|
+// jmethodID methodID_hashcode = (*env)->GetMethodID(env,signature_clazz,"hashCode","()I");
|
|
|
+// jint hashCode = (*env)->CallIntMethod(env,signature,methodID_hashcode);
|
|
|
+//
|
|
|
+// return hashCode;
|
|
|
+//// public class SignatureUtils {
|
|
|
+//// public static int getSignatureHashCode(Context context){
|
|
|
+//// Signature signature = getSignature(context);
|
|
|
+//// int hashCode = signature.hashCode();
|
|
|
+//// return hashCode;
|
|
|
+//// }
|
|
|
+//// public static Signature getSignature(Context argContext) {
|
|
|
+//// Signature signature = null;
|
|
|
+//// try {
|
|
|
+//// String packageName = argContext.getPackageName();
|
|
|
+//// PackageManager packageManager = argContext.getPackageManager();
|
|
|
+//// PackageInfo packageInfo = packageManager.getPackageInfo(packageName,packageManager.GET_SIGNATURES);
|
|
|
+//// Signature[] signatures = packageInfo.signatures;
|
|
|
+//// signature = signatures[0];
|
|
|
+//// } catch (PackageManager.NameNotFoundException e) {
|
|
|
+//// e.printStackTrace();
|
|
|
+//// }
|
|
|
+//// return signature;
|
|
|
+//// }
|
|
|
+//// }
|
|
|
+//
|
|
|
+//}
|
|
|
+
|