Androd開發:保存私密字符串到So庫

logo

未經允許禁止轉載

一、寫這篇文章的原因

在平日開發中,我們時常是需要保存一些字符串,而這些字符串比較重要,我們可以通過一些途徑進行保存</br>

(1)通過網絡分發動態的密碼,以及對應的加密的字符串,在一定時間內密碼有效。
(2)密碼本地存儲在一些地方,如SP,數據庫,MMKV,動態鏈接庫等等

本文就基于第二種方案中的動態鏈接庫去進行開發,即我們俗稱的So庫,由于不存在百分百解不開的加密方式,都是時間長和短的問題,我們要增加的是解密的時間成本,而且考慮到開發時候的方便以及性能問題,我們都采用多種結合,例如 網路+本地秘鑰雙重校驗,或者動態分發加密關鍵信息再組合等等。

二、Gradle Plugin開發

1、建一個Module

創建模塊

2、Grdlde基本配置

假設我們的Module名字是plugin,那么在Project根目錄的中,修改引入方法

//include(":plguin") 改成下面
includeBuild("plguin")

本項目基于kotlin開發的所以需要把build.gradle修改為build.gradle.kts文件</br>
大致的配置如下:

buildscript {
    repositories {
        jcenter()
        google()
    }
    dependencies {
        classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.21")
    }
}

dependencies {
    compileOnly(gradleApi())
    compileOnly("org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.21")
    compileOnly("com.android.tools.build:gradle:4.0.1")
    implementation("com.squareup:javapoet:1.13.0") //用于生產JAVA代碼
}

gradlePlugin {
    plugins {
        create(Plugin的名字,自己定義) {
            id = "自己定義獨立Id"
            implementationClass = "對應的Plugin的路徑,即包名.類名"
        }
    }
}

其中“org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.21” 可以修改為 “kotlin-dsl”
主要是為了導入Kotlin開發Gradle Plugin的基礎環境, "com.squareup:javapoet:1.13.0" 用于生產自定義的JAVA代碼,動態生成代碼處理我們儲存的內容。

如何實現實現獨立存在:app和:Library

1、自己生成CMakeLists文件

如果有NDK開發經驗都應該知道,我們需要一個CMakeLists.txt文件去構建混合了Native C++的項目,而這個CMakeLists.txt很容易存在沖突等問題,包括同名的動態鏈接庫也是,所以我們利用Gradle的Task任務進行,動態生成CMakeLists.txt,并且So庫的名字也是不同名字,內容大致如下:

cmake_minimum_required(VERSION 3.4.1)

add_library(
        core-client //你的.So庫名字,就是,生成結果是libcore-client.so文件,System.loadLibrary("core-client")
        
        SHARED

        src/main/cpp/core-client.cpp
        src/main/cpp/core-environment.cpp
        src/main/cpp/core-encryption.cpp
)

find_library(
              log-lib
              log )

target_link_libraries(
        core-client  //你的.So庫名字
                     ${log-lib} )

有了這個關鍵因素那么我們就可以解決重復名字的.So庫的問題了,自己改了這個名字,讓互不干擾。

2、如何把Nativce方法動態綁定到我們的JAVA文件

既然我們的.So是獨立的那么,我們調用這些方法的JAVA文件最好也是獨立一個,這時候又要兼容app和libray的存在,就會出現包名路徑不同,如果單純的傳統的native方法自動生成代碼的不可行了

extern "C"
包_名_XXX_XXX_XX_名字(JNIEnv *env,jclass clazz)

這種不能滿足我們的要求,我們需要動態注冊方法

jint JNI_OnLoad(JavaVM *vm, void *reserved)// System.loadLibrary("") 加載

那我就在這里注冊方法

extern "C" 
JNIEXPORT jstring JNICALL getString(JNIEnv *env,jclass clazz,jstring key_){
    return env->NewStringUTF(result);
}

JNINativeMethod methods[] = {
        { "getString", "(Ljava/lang/String;)Ljava/lang/String;",(void*)getString},
};

jint JNI_OnLoad(JavaVM *vm, void *reserved) {
    env->RegisterNatives(clazz, methods, sizeof(methods)/sizeof(JNINativeMethod));
    return JNI_VERSION_1_6;
    }
//對應JAVA的方法
public static native String getString(String key);

這個JNINativeMethod methods[]其實很好理解,第一個是方法名字,第二個是(參數)和返回值(return = what?),第三個指向的實現方法
具體怎么填寫,這里也不展開細講。找到這篇參考文章

3、支持兩種加密方式

本項目采用最簡單的兩種對稱加密方式:AES和DES

具體調用

由于庫我已經上傳到Jitpack了,所以需要在根目錄的project中配置環境

buildscript {

repositories {
        google()
        jcenter()
        maven { setUrl("https://jitpack.io") }
    }

dependencies {
        classpath("com.occ.orca:orca.so:2.0.0-release13")
    }
}

然后在項目的module和app中build.gradle添加

plugins {
    id 'com.android.application'
    id 'Orca' //必須先于kotlin-android 后于com.android.application
    id 'kotlin-android'
}

使用也很方便,在項目或者模塊的build.gradle的里書寫

android{
   Orca.go{
        isDebug = true //默認值為false,必須輸入Signature 
        encryptMode = "des" // 輸入AES或者DES,不用區分大小寫
        storeSet{
            "data"{
                value = "4444444444"
            }
            "1223"{
                value = "888888" //命名數字開頭,方法名會有下劃線
            }
        }
    }
  }
  
  //這是我們調用的地方,注意CoreClient有包名的區分,不是把所有結果集合到同一個類里
  val data = CoreClient.getData()
  val data1 = CoreClient.get_1223()
  

4、使用注意

代碼在C++層中,進行了判斷簽名的校驗,如果簽名校驗錯誤會直接崩潰,字段為secretKey,而你們加密的所用到的Key則為字段signature,而控制是否輸入signatureisDebug字段進行控制,都是小駝峰寫法。

小結

本項目采用的AESEncryption和DESEncryption,提出的方案還有很多需要完善的處理,后續會考慮直接在C++層做加密的運算,歡迎各位Pull Request.

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容