Administrator
发布于 2026-08-25 / 12 阅读
0
0

系列文章《Android 工程师的 100 篇进阶笔记》第 29 篇:Android 安全进阶:证书固定、Root 检测与数据加密

安全是一个“成本”问题。完美的安全不存在,关键是把攻击成本提到足够高。今天就来聊几个工程上能落地的安全加固点。


一、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

  • 数据库敏感字段加密

  • 不要硬埋密钥在代码里


四、代码混淆与反调试

  1. 用 R8 混淆 + 加固壳

  2. 关键算法用 Native 实现

  3. 检测调试器:

#include <sys/ptrace.h>
ptrace(PTRACE_TRACEME, 0, 0, 0);
  1. 校验签名和完整性


五、安全 checklist

  1. 所有网络请求走 HTTPS

  2. 关键接口做证书固定

  3. Token 等敏感数据加密存储

  4. Root/模拟器检测增加门槛

  5. 日志里不要打印敏感信息

  6. 定期做渗透测试


小结

  1. 证书固定能防中间人攻击,但要注意证书轮换

  2. Root 检测是门槛,不是绝对防御

  3. 敏感数据必须加密存储

  4. 混淆、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


评论