<strong><span style="font-size:24px;">众所周知安卓很容易被反编译,即使做了防止反编译处理许多代码也可以看的到,目前用的比较多的手段是jni,即:把核心代码放到c++中,然后做出so库,这样的话安全性提高不少,但如果不对so库进行特殊处理的话,通过查看反编译后的java代码就会推测出你定义的调用so库的接口,别人就可以仿造你的接口,然后调用你的so库。 其实我们可以再每次调用so库时都在so库中的函数中判断一下安卓的公钥是不是你的,从而阻止他们使用你的so库,具体代码及工程如下</span></strong>
#include"com_example_singjni_MainActivity.h"
#include <stdio.h>
#include <stdlib.h>
//
//获取公钥的java代码
//public void getSingInfo() {
// try {
// String pn=getPackageName();
//
// PackageInfo packageInfo = getPackageManager().getPackageInfo(
// pn, PackageManager.GET_SIGNATURES);
// Signature[] signs = packageInfo.signatures;
// Signature sign = signs[0];
// parseSignature(sign.toByteArray());
// } catch (Exception e) {
// e.printStackTrace();
// }
// }
//
// public void parseSignature(byte[] signature) {
// ByteArrayInputStream bi=new ByteArrayInputStream(signature);
// try {
// CertificateFactory certFactory = CertificateFactory
// .getInstance("X.509");
// X509Certificate cert = (X509Certificate) certFactory
// .generateCertificate(new ByteArrayInputStream(signature));
// String pubKey = cert.getPublicKey().toString();
// String signNumber = cert.getSerialNumber().toString();
//
//
// System.out.println("signName:" + cert.getSigAlgName());
// System.out.println("pubKey:" + pubKey);
// System.out.println("signNumber:" + signNumber);
// System.out.println("subjectDN:"+cert.getSubjectDN().toString());
// } catch ( Exception e) {
// e.printStackTrace();
// }
// }
//核心代码如下 ,其他可以忽略
JNIEXPORT jstring JNICALL Java_com_example_singjni_MainActivity_sing__Landroid_content_Context_2
(JNIEnv * env, jobject ob1, jobject thiz){
jclass thisClass=env->GetObjectClass(thiz);
jmethodID getPNId=env->GetMethodID(thisClass,"getPackageName","()Ljava/lang/String;");
jstring packName=(jstring)env->CallObjectMethod(thiz,getPNId);
jmethodID getPMId=env->GetMethodID(thisClass,"getPackageManager","()Landroid/content/pm/PackageManager;");
jobject packManger=env->CallObjectMethod(thiz,getPMId);
jmethodID getPIId=env->GetMethodID(env->GetObjectClass(packManger),"getPackageInfo","(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;");
jobject packageInfo=env->CallObjectMethod(packManger,getPIId,packName,0x00000040);
jfieldID signaturesId=env->GetFieldID(env->GetObjectClass(packageInfo),"signatures","[Landroid/content/pm/Signature;");
jobject signatures=env->GetObjectField(packageInfo,signaturesId);
jobjectArray signaturesArray=(jobjectArray)signatures;
//signature=signs[0]
jobject signature=env->GetObjectArrayElement(signaturesArray,0);
jmethodID signatureBytesMId=env->GetMethodID(env->GetObjectClass(signature),"toByteArray","()[B");
//sign.toByteArray()
jobject signatureBytes=env->CallObjectMethod(signature,signatureBytesMId);
///////////////// public void parseSignature(byte[] signature) {}/////////////////////////////////////////////////////////////////
jclass certificateFactoryClass=env->FindClass("java/security/cert/CertificateFactory");
jmethodID getInstanceMId=env->GetStaticMethodID(certificateFactoryClass,"getInstance","(Ljava/lang/String;)Ljava/security/cert/CertificateFactory;");
jobject certFactory=env->CallStaticObjectMethod(certificateFactoryClass,getInstanceMId,env->NewStringUTF("X.509"));
///////////////////////////////////
jclass byteInStreamClass=env->FindClass("java/io/ByteArrayInputStream");
jmethodID byteArrayInStreamConMId= env->GetMethodID(byteInStreamClass,"<init>","([B)V");
jobject byteArrayInStream=env->NewObject(byteInStreamClass,byteArrayInStreamConMId,signatureBytes);
jmethodID generateCertificateMId=env->GetMethodID(certificateFactoryClass,"generateCertificate","(Ljava/io/InputStream;)Ljava/security/cert/Certificate;");
jobject certificate=env->CallObjectMethod(certFactory,generateCertificateMId,byteArrayInStream);
jmethodID getPKMId=env->GetMethodID(env->GetObjectClass(certificate),"getPublicKey","()Ljava/security/PublicKey;");
jobject publicKey=env->CallObjectMethod(certificate,getPKMId);
jmethodID toStringMId=env->GetMethodID(env->GetObjectClass(publicKey),"toString","()Ljava/lang/String;");
jstring publickeyStr=(jstring)env->CallObjectMethod(publicKey,toStringMId);
///////////////////////
jmethodID equalsMId=env->GetMethodID(env->GetObjectClass(publickeyStr),"equals","(Ljava/lang/Object;)Z");
jboolean isCorrect=env->CallBooleanMethod(publickeyStr,equalsMId,env->NewStringUTF("OpenSSLRSAPublicKey{modulus=123..你的公钥...,publicExponent=10001}"));
if(!isCorrect)
return env->NewStringUTF( "wrong");
jstring jstr=env->NewStringUTF( "correct");
return jstr;
}
JNIEXPORT jstring JNICALL Java_com_example_singjni_MainActivity_sing
(JNIEnv * env, jobject thiz){
jstring jstr=env->NewStringUTF( "");
return jstr;
}
java端代码
package com.example.singjni;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.text.SimpleDateFormat;
import java.util.Date;
import android.app.Activity;
import android.app.Application;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.Signature;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends Activity {
static{
System.loadLibrary("jniso");
}
EditText et;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et=(EditText) findViewById(R.id.et);
String s=sing(this);
et.setText(s);
System.out.println(s);
}
public native String sing();
public native String sing(Context context);
}
原文地址:http://blog.csdn.net/qingchunweiliang/article/details/39139351