大家都知道我们apk是很容易被有些人破解的,特别是涉及到支付方面的app,如果被有心人换掉支付,二次打包那就是很可怕的事情了。
今天来给大家分享一些关于app安全方面的技术:
1.接口参数加密签名
市面上常用的加密签名方式有两种:MD5,RSA
MD5加密相信大家都已经很熟悉了,这里就不贴代码了。
RSA加密算法代码如下:
public class RSA{ public static final String SIGN_ALGORITHMS = "SHA1WithRSA"; /** * RSA签名 * @param content 待签名数据 * @param privateKey 商户私钥 * @param input_charset 编码格式 * @return 签名值 */ public static String sign(String content, String privateKey, String input_charset) { try { PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec( Base64.decode(privateKey) ); KeyFactory keyf = KeyFactory.getInstance("RSA"); PrivateKey priKey = keyf.generatePrivate(priPKCS8); java.security.Signature signature = java.security.Signature .getInstance(SIGN_ALGORITHMS); signature.initSign(priKey); signature.update( content.getBytes(input_charset) ); byte[] signed = signature.sign(); return Base64.encode(signed); } catch (Exception e) { e.printStackTrace(); } return null; } /** * RSA验签名检查 * @param content 待签名数据 * @param sign 签名值 * @param alipay_public_key 支付宝公钥 * @param input_charset 编码格式 * @return 布尔值 */ public static boolean verify(String content, String sign, String alipay_public_key, String input_charset) { try { KeyFactory keyFactory = KeyFactory.getInstance("RSA"); byte[] encodedKey = Base64.decode(alipay_public_key); PublicKey pubKey = keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey)); java.security.Signature signature = java.security.Signature .getInstance(SIGN_ALGORITHMS); signature.initVerify(pubKey); signature.update( content.getBytes(input_charset) ); boolean bverify = signature.verify( Base64.decode(sign) ); return bverify; } catch (Exception e) { e.printStackTrace(); } return false; } }
2.混淆自己的代码
在proguard-rules.pro文件编写自己的混淆规则,
-keep class com.letui.sdk.base.BaseLeTuiChannelSdk{*; } -keep class com.letui.sdk.base.BaseLeTuiPluginSdk{*; } -keep class com.letui.sdk.util.ResUtil{*; } -keep class com.letui.sdk.view.** {*;}
在gradle照片那个配置如下,执行
gradlew makeJar命令,就可以生成混淆后的jar文件了
task makeJar(type: proguard.gradle.ProGuardTask, dependsOn: "build") { // 未混淆的jar路径 injars 'build/intermediates/intermediate-jars/release/classes.jar' // 混淆后的jar输出路径 outjars 'build/outputs/ltsdk.jar' // 混淆协议 configuration 'proguard-rules.pro' },混淆后的文件如下:
3.校验签名文件,大家都知道,如果apk被二次打包,签名文件肯定会不一样,如果我们在代理里面去校验签名文件,判断使我们自己的签名就让程序去运行,如果不是我们的签名就闪退App,就相当于给我们的apk又加了一层保护壳。最好是把校验签名放在c文件里面,可以增加破解难度。代码如下:
JNIEXPORT jstring JNICALL Java_com_letui_sdk_DR_1JNITest_getSuccessKey (JNIEnv *env, jclass jclazz, jobject contextObject,jint pid){ jclass native_class = env->GetObjectClass(contextObject); jmethodID pm_id = env->GetMethodID(native_class, "getPackageManager", "()Landroid/content/pm/PackageManager;"); jobject pm_obj = env->CallObjectMethod(contextObject, pm_id); jclass pm_clazz = env->GetObjectClass(pm_obj); // 得到 getPackageInfo 方法的 ID jmethodID package_info_id = env->GetMethodID(pm_clazz, "getPackageInfo","(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;"); jclass native_classs = env->GetObjectClass(contextObject); jmethodID mId = env->GetMethodID(native_classs, "getPackageName", "()Ljava/lang/String;"); jstring pkg_str = static_cast<jstring>(env->CallObjectMethod(contextObject, mId)); // 获得应用包的信息 jobject pi_obj = env->CallObjectMethod(pm_obj, package_info_id, pkg_str, 64); // 获得 PackageInfo 类 jclass pi_clazz = env->GetObjectClass(pi_obj); // 获得签名数组属性的 ID jfieldID signatures_fieldId = env->GetFieldID(pi_clazz, "signatures", "[Landroid/content/pm/Signature;"); jobject signatures_obj = env->GetObjectField(pi_obj, signatures_fieldId); jobjectArray signaturesArray = (jobjectArray)signatures_obj; jsize size = env->GetArrayLength(signaturesArray); jobject signature_obj = env->GetObjectArrayElement(signaturesArray, 0); jclass signature_clazz = env->GetObjectClass(signature_obj); //第一种方式--检查签名字符串的方式 jmethodID string_id = env->GetMethodID(signature_clazz, "toCharsString", "()Ljava/lang/String;"); jstring str = static_cast<jstring>(env->CallObjectMethod(signature_obj, string_id)); char *c_msg = (char*)env->GetStringUTFChars(str,0); LOGD("########## i = %s", c_msg); if(strcmp(c_msg,RELEASE_SIGN)==0)//签名一致 返回合法的 api key,否则返回错误 { //这里说明是我们的签名,可以返回我们的key }else {
//这里说明不是我们的签名,可以闪退app} //第二种方式--检查签名的hashCode的方式 /* jmethodID int_hashcode = env->GetMethodID(signature_clazz, "hashCode", "()I"); jint hashCode = env->CallIntMethod(signature_obj, int_hashcode); if(hashCode == RELEASE_SIGN_HASHCODE) { return (env)->NewStringUTF(AUTH_KEY); }else{ return (env)->NewStringUTF("错误"); } */ }
4.so文件也不是非常安全的,这里附上破解链接:
https://blog.csdn.net/qq591840685/article/details/20869491,我们为了增加破解难度,可以混淆so文件,http://www.liuling123.com/2016/06/so_method_mix.html。