zoukankan      html  css  js  c++  java
  • (转) android so 文件存私密数据,且防止 so文件未知应用盗用

    android so 文件存私密数据,且防止 so文件未知应用盗用

     

           有时候我们需要在客户端 存放一些 保密的数据,比如 服务端的IP 端口,接口的地址,授权的key 等等,如果我们直接写在java中,别人反编译就能看到,那么我们可以把这些数据 存在  so文件中,这样别人就不可能会看到了,顺便 so里面验证 app的签名 来防止别人盗用so文件,

    下面的例子是 在so里面获取我的客户端key

    1.jni的java文件   JNI.java

    [java] view plain copy
    1. package com.android.jni;  
    2.   
    3. import android.content.Context;  
    4.   
    5. public class JNI {  
    6.   
    7.      static{  
    8.          System.loadLibrary("auth");  
    9.      }  
    10.        
    11.      /** 
    12.       * 获取api 调用授权 key 
    13.       * @param signature 应用签名信息,防止http 接口  授权 key 被盗用 
    14.       * @return 
    15.       */  
    16.      public native String getAuthKey(Context context);  
    17.        
    18. }  
    [java] view plain copy
     在CODE上查看代码片派生到我的代码片
    1.   
    2. .h头文件  com_android_jni_JNI.h
    [cpp] view plain copy
    1. /* DO NOT EDIT THIS FILE - it is machine generated */  
    2. #include <jni.h>  
    3. /* Header for class com_android_jni_JNI */  
    4.   
    5. #ifndef _Included_com_android_jni_JNI  
    6. #define _Included_com_android_jni_JNI  
    7. #ifdef __cplusplus  
    8. extern "C" {  
    9. #endif  
    10. /* 
    11.  * Class:     com_android_jni_JNI 
    12.  * Method:    getAuthKey 
    13.  * Signature: (Landroid/content/pm/Signature;)Ljava/lang/String; 
    14.  */  
    15. JNIEXPORT jstring JNICALL Java_com_android_jni_JNI_getAuthKey  
    16.   (JNIEnv *, jobject, jobject);  
    17.   
    18. #ifdef __cplusplus  
    19. }  
    20. #endif  
    21. #endif  
    3. so的 c++实现  com_android_jni_JNI.cpp
    [cpp] view plain copy
     在CODE上查看代码片派生到我的代码片
    1. #include <jni.h>  
    2. #include <string.h>  
    3. #include <stdio.h>  
    4. #include <com_android_jni_JNI.h>  
    5. /** 
    6.  * http api 授权 key ,由服务端提供 
    7.  */  
    8. const char* AUTH_KEY = "0CC175B9C0F1B6A831C399E269772661";  
    9.   
    10. /** 
    11.  * 发布的app 签名,只有和本签名一致的app 才会返回合法的 授权 key 
    12.  */  
    13. const char* RELEASE_SIGN ="3082030d308201f5a0030201020204163677d7300d06092a864886f70d01010b05003037310b30090603550406130255533110300e060355040a1307416e64726f6964311630140603550403130d416e64726f6964204465627567301e170d3134303131343035333835315a170d3434303130373035333835315a3037310b30090603550406130255533110300e060355040a1307416e64726f6964311630140603550403130d416e64726f696420446562756730820122300d06092a864886f70d01010105000382010f003082010a02820101008f02a948189bfa0134bdb17155061a4b62956c08881eac87b39f0a0acf1c808596100b09a16600f5567e5504f035f1deadc1dcc93fa93b930f78ac9a55ee961283458d66d3775e612e4eb5f5076bf06aeabb6e285400e89dd6e1327a52b4739a91d04d7288bc64c336b7776efe0b6341913d655943ffc9da4b8ba157a52f7790a815bf0cc693dd684209a07290b9c8d4220c8f56c00c25bee78500231213adba58b3c2c9e95951308dfab9edc4f9744fe6c99b3311b54971210db4c2e8a5d518def97535a69170827d6c14bd8a822a0d1b179a3633178db16376a9596df91c595b8cb3d3a916b0f10d029a0aad3b345a7ad54e85f2547686f612b62a010d7dd90203010001a321301f301d0603551d0e04160414f7c342dca7f916bb77312bb517105732c5e96328300d06092a864886f70d01010b0500038201010010b1bb9c29118a7eb15193ef15d40bafd4338526b200511f0e348e5c93eb9cbdf9330163cba183022572513dc7dac14cbd384c116bfc2c3d5efc9f545c3972ec8ce32908eb4e54a6940774ac569d682c188388380d60ed1904ecca4f4bf6bdcacd8be71557f1133c2fd5bcc2577fde19adef54cb91e02e635b47e6a6bfb1f46a5956259a10c61727e70cd8595fd632d4ed6c588dcb089967f164090aa89050911fd70eb1f7ccacd4d7b75c0b5ecd2bb84709b16176b9ac21f8bb25a970f65105af7939057cbf616abf5e9617f1ef87e39d16e458b278cbdc4f9ccb5d8e0c69719a5fae55bdd786b7b59c4a37a205972de1b0f3d4e8877267bad8f28ab09800f2";  
    14.   
    15. /** 
    16.  * 拿到传入的app  的 签名信息,对比合法的app 签名,防止so文件被未知应用盗用 
    17.  */  
    18. static jclass contextClass;  
    19. static jclass signatureClass;  
    20. static jclass packageNameClass;  
    21. static jclass packageInfoClass;  
    22. JNIEXPORT jstring JNICALL Java_com_android_jni_JNI_getAuthKey(  
    23.         JNIEnv * env, jobject obj, jobject contextObject) {  
    24.   
    25.     jmethodID getPackageManagerId = (env)->GetMethodID(contextClass, "getPackageManager","()Landroid/content/pm/PackageManager;");  
    26.     jmethodID getPackageNameId = (env)->GetMethodID(contextClass, "getPackageName","()Ljava/lang/String;");  
    27.     jmethodID signToStringId = (env)->GetMethodID(signatureClass, "toCharsString","()Ljava/lang/String;");  
    28.     jmethodID getPackageInfoId = (env)->GetMethodID(packageNameClass, "getPackageInfo","(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;");  
    29.     jobject packageManagerObject =  (env)->CallObjectMethod(contextObject, getPackageManagerId);  
    30.     jstring packNameString =  (jstring)(env)->CallObjectMethod(contextObject, getPackageNameId);  
    31.     jobject packageInfoObject = (env)->CallObjectMethod(packageManagerObject, getPackageInfoId,packNameString, 64);  
    32.     jfieldID signaturefieldID =(env)->GetFieldID(packageInfoClass,"signatures", "[Landroid/content/pm/Signature;");  
    33.     jobjectArray signatureArray = (jobjectArray)(env)->GetObjectField(packageInfoObject, signaturefieldID);  
    34.     jobject signatureObject =  (env)->GetObjectArrayElement(signatureArray,0);  
    35.   
    36.     const char* signStrng =  (env)->GetStringUTFChars((jstring)(env)->CallObjectMethod(signatureObject, signToStringId),0);  
    37.     if(strcmp(signStrng,RELEASE_SIGN)==0)//签名一致  返回合法的 api key,否则返回错误  
    38.     {  
    39.        return (env)->NewStringUTF(AUTH_KEY);  
    40.     }else  
    41.     {  
    42.        return (env)->NewStringUTF("error");  
    43.     }  
    44.   
    45. }  
    46.   
    47.   
    48. JNIEXPORT jint JNICALL JNI_OnLoad (JavaVM* vm,void* reserved){  
    49.   
    50.      JNIEnv* env = NULL;  
    51.      jint result=-1;  
    52.      if(vm->GetEnv((void**)&env, JNI_VERSION_1_4) != JNI_OK)  
    53.        return result;  
    54.   
    55.      contextClass = (jclass)env->NewGlobalRef((env)->FindClass("android/content/Context"));  
    56.      signatureClass = (jclass)env->NewGlobalRef((env)->FindClass("android/content/pm/Signature"));  
    57.      packageNameClass = (jclass)env->NewGlobalRef((env)->FindClass("android/content/pm/PackageManager"));  
    58.      packageInfoClass = (jclass)env->NewGlobalRef((env)->FindClass("android/content/pm/PackageInfo"));  
    59.   
    60.      return JNI_VERSION_1_4;  
    61.  }  

    关于如何获取正式keystone签名的问题

    先打一个正式的包,代码里面获取到签名,然后再log里面打印出来,copy到cpp文件里面编译so即可,下面是android里面获取签名字符串的代码

    [java] view plain copy
    1. public static String getSignature(Context context)  
    2.     {  
    3.         try {  
    4.             /** 通过包管理器获得指定包名包含签名的包信息 **/  
    5.             PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), PackageManager.GET_SIGNATURES);  
    6.             /******* 通过返回的包信息获得签名数组 *******/  
    7.             Signature[] signatures = packageInfo.signatures;  
    8.             /******* 循环遍历签名数组拼接应用签名 *******/  
    9.             return signatures[0].toCharsString();  
    10.             /************** 得到应用签名 **************/  
    11.         } catch (NameNotFoundException e) {  
    12.             e.printStackTrace();  
    13.         }  
    14.       
    15.         return null;  
    16.     }  
    17.       
  • 相关阅读:
    BEGIN2 序列求和
    BEGIN2 序列求和
    《算法竞赛入门经典》 习题45 IP网络(IP Networks,ACM、ICPC NEERC 2005,UVa1590)
    C#中char空值的几种表示方式
    C#中char空值的几种表示方式
    C#中() =>是什么意思
    C#中() =>是什么意思
    C# Task 暂停与取消
    C# Task 暂停与取消
    C# WinForm设置透明
  • 原文地址:https://www.cnblogs.com/VindyLeong/p/5363667.html
Copyright © 2011-2022 走看看