安全是一个“成本”问题。完美的安全不存在,关键是把攻击成本提到足够高。今天就来聊几个工程上能落地的安全加固点。
一、HTTPS 与证书固定
HTTPS 防中间人,但如果设备被装了伪造证书,还是可能被监听。证书固定(Pinning)可以解决这个问题。
val certificatePinner = CertificatePinner.Builder()
.add("api.example.com", "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=")
.build()
val client = OkHttpClient.Builder()
.certificatePinner(certificatePinner)
.build()
注意:证书会过期,要预留更新机制,否则证书轮换会导致用户无法联网。
二、Root 检测与模拟器检测
fun isRooted(): Boolean {
return File("/system/bin/su").exists() ||
File("/system/xbin/su").exists() ||
Build.TAGS?.contains("test-keys") == true
}
更 robust 的做法:
检查常见 Root 工具文件
检查能否执行 su 命令
检测 Xposed/Frida 等 Hook 框架
校验签名和包名
检测不是目的,是为了在敏感操作前增加门槛。
三、本地数据加密
val keyGenParameterSpec = MasterKeys.AES256_GCM_SPEC
val masterKeyAlias = MasterKeys.getOrCreate(keyGenParameterSpec)
val encryptedPrefs = EncryptedSharedPreferences.create(
"secure_prefs",
masterKeyAlias,
context,
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
)
敏感数据:
Token 存 EncryptedSharedPreferences
数据库敏感字段加密
不要硬埋密钥在代码里
四、代码混淆与反调试
用 R8 混淆 + 加固壳
关键算法用 Native 实现
检测调试器:
#include <sys/ptrace.h>
ptrace(PTRACE_TRACEME, 0, 0, 0);
校验签名和完整性
五、安全 checklist
所有网络请求走 HTTPS
关键接口做证书固定
Token 等敏感数据加密存储
Root/模拟器检测增加门槛
日志里不要打印敏感信息
定期做渗透测试
小结
证书固定能防中间人攻击,但要注意证书轮换
Root 检测是门槛,不是绝对防御
敏感数据必须加密存储
混淆、Native、反调试能进一步提高逆向成本
下一篇,我们跳出单一平台,看看 Kotlin Multiplatform Mobile 如何共享业务层代码。
参考阅读
引用链接
[1]Certificate Pinning: https://developer.android.com/training/articles/security-config#CertificatePinning
[2]EncryptedSharedPreferences: https://developer.android.com/topic/security/data/store