背景
Android加密数据库的密码、加密的秘钥或者一些敏感的数据,不想泄露出去,可以使用so文件的方式保存,破解难度相对来说比较高。如果简单的保存在so文件中还是不够的,别人反编译后拿到so文件一样可以拿到相应的数据,所以加上签名是一个比较好的方法。
代码实现
-
新建DNK工程,在native-lib.cpp中实现根据不同的签名返回不同的值
#include <jni.h>
#include <string>
#include <android/log.h>
#include <string.h>
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文件


-
配置打包的签名
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);
网友评论