Android so文件保存密码、秘钥,根据签名返回

背景

Android加密数据库的密码、加密的秘钥或者一些敏感的数据,不想泄露出去,可以使用so文件的方式保存,破解难度相对来说比较高。如果简单的保存在so文件中还是不够的,别人反编译后拿到so文件一样可以拿到相应的数据,所以加上签名是一个比较好的方法。

代码实现

  • 新建DNK工程,在native-lib.cpp中实现根据不同的签名返回不同的值
#include 
#include 
#include 
#include 
static jclass contextClass;
static jclass signatureClass;
static jclass packageNameClass;
static jclass packageInfoClass;

const char* RELEASE_SIGN = "110300e060355040313077368616e67686530820122300d06092a864886f70d01010105000382010f003082010a0282010100c93bb2c8a66a599eec46efabc0d8d5ec140583819c3da5058906d703687f4d90ba74566f52bac082ca796c3276a2ffb89512fe69ad3dc1d3b6c86531ebc6e2d661a70d9c97a44445944a921296cb4743bff69c2d9b467d509d118faa923ac1eeaba7b179c51a764f812fcc792c75126089d332ba78c2ee91592effb4014e10137ac67b6ece0e1a8c4682ac03287625219a99f25119c37b90121207bed85d5c048aebbf5401b69fb8a2c5f5f1ea2a7166b76465f93e274a0f894bd54f9dbb6a19c150e7ca22b02f6d18c20fa5107ef297c3fb8ba915f867378cabe858f10bb";
const char* RELEASE_SIGN_ONLINE="4886f70d01010b0500038201010066acb62d7345a4b6ac0a2ee1873a8e48e947be599b5f2c18c05fcc3f33c27424b60cbcb6e9b5533482c35a29d52aa68069fdb82331a7a4fd0b17a8cd526ddbac7a1b387bfde3a54c1dd24e385110b02b042324fd8bd6b254e4aa1f17bd6942d4a05cabcfd578c8f451f76bc6ec3901ac1a40718525dd1ea3de458594be255142c43a332dd73a5abc9e6d91b1036c3b1ae73c7bbf7abca18e0fb72cbf766df1888fd186f7a1c90f24551ea7399afdbd0066dfb9596faf2a18cb5f8ce256b723791848d7ae27894c91539e588d6c65532f1b63bfb5b6df979fa9987ba8ef32c15e5018a831649951a1e6beea7c1c85cf41b52526879e87ee893978b1669c143f12";
const char* DB_KEY = "123";
extern "C" JNIEXPORT jstring

JNICALL
Java_com_demo_Utils_EncryptionManager_getString(
        JNIEnv *env,jobject instance,
        jobject contextObject,bool isBug) {
    jmethodID getPackageManagerId = (env)->GetMethodID(contextClass, "getPackageManager","()Landroid/content/pm/PackageManager;");
    jmethodID getPackageNameId = (env)->GetMethodID(contextClass, "getPackageName","()Ljava/lang/String;");
    jmethodID signToStringId = (env)->GetMethodID(signatureClass, "toCharsString","()Ljava/lang/String;");
    jmethodID getPackageInfoId = (env)->GetMethodID(packageNameClass, "getPackageInfo","(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;");
    jobject packageManagerObject =  (env)->CallObjectMethod(contextObject, getPackageManagerId);
    jstring packNameString =  (jstring)(env)->CallObjectMethod(contextObject, getPackageNameId);
    jobject packageInfoObject = (env)->CallObjectMethod(packageManagerObject, getPackageInfoId,packNameString, 64);
    jfieldID signaturefieldID =(env)->GetFieldID(packageInfoClass,"signatures", "[Landroid/content/pm/Signature;");
    jobjectArray signatureArray = (jobjectArray)(env)->GetObjectField(packageInfoObject, signaturefieldID);
    jobject signatureObject =  (env)->GetObjectArrayElement(signatureArray,0);
    const char* signStrng =  (env)->GetStringUTFChars((jstring)(env)->CallObjectMethod(signatureObject, signToStringId),0);
    if(strcmp(signStrng,RELEASE_SIGN)==0 &&isBug){
        return (env)->NewStringUTF(DB_KEY);
    }else if (strcmp(signStrng,RELEASE_SIGN_ONLINE)==0 && !isBug){
        return (env)->NewStringUTF(DB_KEY);
    }else{
        return (env)->NewStringUTF("error");
    }
}


上面是完整的代码 RELEASE_SIGN 是debug签名的sign,RELEASE_SIGN_ONLINE是release的sign,如果不知道sign,可以先修改代码,打包so文件,打印sign值,sign可以太长可以保存在一个TXT文件中

打印sign,直接返回sign值

/*if(strcmp(signStrng,RELEASE_SIGN)==0 &&isBug){
        return (env)->NewStringUTF(DB_KEY);
    }else if (strcmp(signStrng,RELEASE_SIGN_ONLINE)==0 && !isBug){
        return (env)->NewStringUTF(DB_KEY);
    }else{
        return (env)->NewStringUTF("error");
    }*/
    return (env)->NewStringUTF(signStrng);

build 生成so文件


微信截图_20200709101106.png

微信截图_20200709101220.png
  • 配置打包的签名

1.在build.gradle中添加以下代码

apply plugin: 'com.android.application'
def keystoreFilepath = ''
def keystoreFiledebugpath = ''
def keystorePSW = ''
def keystoreAlias = ''
def keystoreAliasPSW = ''
def keyfile = file('s.keystore.temp')
def keydubugfile = file('s.keystore.temp')

Properties properties = new Properties()
properties.load(project.rootProject.file('local.properties').newDataInputStream())
keystoreFilepath = properties.getProperty("keystore.releasepath")
keystoreFiledebugpath = properties.getProperty("keystore.debugpath")

if (keystoreFilepath) {
    keystorePSW = properties.getProperty("keystore.keyPassword")
    keystoreAlias = properties.getProperty("keystore.keyAlias")
    keystoreAliasPSW = properties.getProperty("keystore.storePassword")
    keyfile = file(keystoreFilepath)
    keydubugfile = file(keystoreFiledebugpath)
}

在android {}中添加

 signingConfigs {
        debug {
            storeFile keydubugfile
            keyAlias = keystoreAlias
            storePassword keystoreAliasPSW
            keyPassword keystorePSW
        }
        release {
            storeFile keyfile
            keyAlias = keystoreAlias
            storePassword keystoreAliasPSW
            keyPassword keystorePSW
        }
    }

在local.properties中添加

#release签名路径
keystore.releasepath=D\:\\key\\key.jks
#debug签名路径
keystore.debugpath=D\:\\key\\keydebug.jks
keystore.keyAlias=key0
keystore.storePassword=123
keystore.keyPassword=123
  • native方法的调用

注意调用的class要跟native-lib.cpp中全类名一致,例如本文中的com.demo.Utils.EncryptionManager

 static {
        System.loadLibrary("native-lib");
    }

  private  native String getString(Context context,boolean isBug);

你可能感兴趣的:(Android so文件保存密码、秘钥,根据签名返回)