android保存本地密鑰實(shí)踐

在這篇文章你能看到對(duì)安卓本地保存密鑰的實(shí)踐

前言

在網(wǎng)絡(luò)傳輸過程中,我們往往需要一個(gè)密鑰對(duì)參數(shù)進(jìn)行簽名,用于驗(yàn)證來源可靠,所以我們?cè)赼pp打包過程中,就避免不了在app中保存此密鑰。

保存密鑰的方法

直接在java代碼中寫

最基本簡(jiǎn)單的就是直接在java代碼把密鑰串寫在靜態(tài)變量中,最簡(jiǎn)單,顯然也是不太靠譜的,容易反編譯后被發(fā)現(xiàn),即使混淆后,這種靜態(tài)變量也是容易被發(fā)現(xiàn)的。

寫在cpp里

寫在cpp里,打包后,保存在so庫中,這個(gè)方法,安全度增加了很多,編譯后的c代碼,反編譯非常困難,看起來美美的

Java_com_yglx_testjni_MainActivity_getKey(
        JNIEnv *env,
        jobject /* this */) {
    std::string key = "asdkjflaksdjflksjadfasdfasdfasdfasdfsdfasdlfkjasldfjasdlf";
    return env->NewStringUTF(key.c_str());
}

看起來不錯(cuò),但是又有問題了,當(dāng)把a(bǔ)pk解壓后,lib里面可以看到生成的so文件,別人就可以拿到這個(gè)so文件,之后新建一個(gè)相同包名和類名的應(yīng)用,這樣就可以拿到你隱藏的密鑰
了,那能不能在被有心之人拿到so文件的情況下,仍舊不能獲取到密鑰呢,那就是接下來策略,執(zhí)行代碼前先校驗(yàn)app簽名。

cpp里加入應(yīng)用的簽名校驗(yàn)

獲取應(yīng)用的簽名,實(shí)際也是通過android中java的api進(jìn)行獲取的,我把部分代碼貼出。

extern "C"
JNIEXPORT jstring JNICALL
Java_com_yglx_testjni_MainActivity_getSafeKey(JNIEnv *env, jobject instance,jobject contextObject) {
    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)//簽名一致  返回合法的 api key,否則返回錯(cuò)誤
    {
        return (env)->NewStringUTF(AUTH_KEY);
    }else
    {
        return (env)->NewStringUTF("error");
    }
}

到這里,使用cpp并且用校驗(yàn)應(yīng)用簽名的方法就能達(dá)到一個(gè)對(duì)密鑰的比較好的保護(hù)。

附上實(shí)踐中的代碼鏈接

github demo

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容