
本文介绍使用 Android Keystore 系统加密存储 SHA-1、API 密钥等敏感字符串的实践方法,避免明文硬编码或存于 values.xml,通过 AES/GCM 加密 + Keystore 私钥保护实现运行时动态解密。
本文介绍使用 android keystore 系统加密存储 sha-1、api 密钥等敏感字符串的实践方法,避免明文硬编码或存于 `values.xml`,通过 aes/gcm 加密 + keystore 私钥保护实现运行时动态解密。
在 Android 开发中,将 SHA-1 指纹、Firebase 配置、Google API Key 等敏感信息以明文形式写入 res/values/strings.xml 或 Java/Kotlin 源码中,属于典型的安全反模式——一旦 APK 被反编译,这些凭证极易泄露。正确做法是利用系统级安全设施(Android Keystore)生成并管理加密密钥,对敏感字符串进行 AES/GCM 加密后固化为 Base64 字符串,并在运行时按需解密。
✅ 推荐方案:Android Keystore + AES/GCM 加密存储
Android Keystore 系统可确保加密密钥无法被导出,且加解密操作在可信执行环境(TEE)或硬件安全模块(HSM)中完成(取决于设备支持)。以下为关键步骤与示例代码:
1. 初始化 Keystore 加密器(推荐封装为单例)
使用如 Josias Sena 提供的开源工具类(或自行基于 KeyGenerator + Cipher 实现),核心逻辑如下:
// 创建密钥别名(建议固定,如 "app_secure_key")
private const val SAMPLE_ALIAS = "app_secure_key"
// 首次运行时生成密钥(仅一次!)
val keyGenerator = KeyGenerator.getInstance(
KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore"
)
keyGenerator.init(
KeyGenParameterSpec.Builder(SAMPLE_ALIAS, KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT)
.setBlockModes(KeyProperties.BLOCK_MODE_GCM)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
.setKeySize(256)
.build()
)
keyGenerator.generateKey()
2. 加密敏感字符串(仅在开发阶段执行一次)
在 MainActivity 或调试入口中临时调用加密逻辑,获取 Base64 编码后的密文:
val encryptor = AndroidKeystoreAesEncryptor() // 假设已封装
val rawSecret = "XX:XX:XX:XX:...:XX" // 替换为你的 SHA-1 指纹
val encryptedBytes = encryptor.encryptText(SAMPLE_ALIAS, rawSecret)
val encryptedBase64 = Base64.encodeToString(encryptedBytes, Base64.DEFAULT)
Log.d("SecureKey", "Encrypted: $encryptedBase64") // 复制此输出
⚠️ 重要提醒:该加密代码仅用于开发期生成密文,上线前必须彻底删除,否则会暴露密钥生成逻辑。
Android 开发调试技能,通过系统 ADB 工具操作 Android 设备。以下场景必须触发此技能:(1) 直接 ADB 操作——安装 APK、查看设备列表、抓取 logcat 日志、查看已安装应用、清除应用数据、截图、重启设备、拉取/推送文件、查看 CPU/内存/电池信息、adb shell 操作;(2)...
3. 运行时安全解密(生产环境唯一允许的操作)
将上一步获得的 Base64 字符串硬编码为常量(如 const val ENCRYPTED_SHA1 = "TAxdnTHhyEC34x510mMxqt2nAMrv7dMXWDjr"),并在需要时解密:
val encryptedBytes = Base64.decode(ENCRYPTED_SHA1, Base64.DEFAULT) val decrypted = encryptor.decryptData(SAMPLE_ALIAS, encryptedBytes, encryptor.iv) // decrypted == "XX:XX:XX:XX:...:XX"
? 注意:
encryptor.iv(初始化向量)需与加密时一致;GCM 模式下 IV 通常随密文一同保存(本例中假设已内建管理)。实际项目建议使用成熟库如 safetynet-helper 或 Jetpack Security(androidx.security:security-crypto)简化实现。
⚠️ 关键注意事项
- SHA-1 本身不是密钥,而是证书指纹:它通常用于服务端校验 App 签名合法性(如 Google Sign-In、Firebase),不应作为加密密钥使用;此处“加密 SHA-1”本质是保护其不被恶意提取复用。
-
勿混淆 Keystore 类型:
AndroidKeyStore(系统级密钥容器) ≠BKS/JKS(Java 密钥库文件);前者无需导出私钥,安全性更高。 -
兼容性考量:Android 6.0+ 全面支持
AndroidKeyStore;若需支持更低版本,应降级为KeyPairGenerator+ RSA 加密(但安全性弱于 GCM)。 -
替代方案参考:对于非高敏场景,可结合构建时注入(Gradle
buildConfigField+ 环境变量)+ ProGuard 混淆,但无法抵御内存 dump 攻击;Keystore 方案是目前 Android 平台最平衡的安全实践。
综上,安全存储的本质不是“隐藏”,而是“可控访问”——通过系统信任链绑定密钥生命周期,使敏感数据仅在授权应用、授权时机、授权设备上可解密。坚持这一原则,才能真正提升应用整体安全水位。










