You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何保护Gradle.properties中的敏感信息不被APK反编译泄露?

防护APK中敏感配置信息的实用方案

刚踩过类似的坑,反编译后看到gradle里的敏感信息直接暴露确实挺吓人的。下面从构建阶段到运行时防护,给你整理几个可落地的方案:

1. 构建阶段:把敏感信息移出代码库,用环境变量/本地配置文件管理

永远不要把真实的敏感值写在提交到版本库的gradle.properties里,改用占位符+本地配置/环境变量的方式:

  • 在公共的gradle.properties中只写占位符,比如:
    AUTH_TOKEN=${AUTH_TOKEN}
    SALT_KEY=${SALT_KEY}
    HTACCESS_USER=${HTACCESS_USER}
    HTACCESS_PWD=${HTACCESS_PWD}
    
  • 创建一个local.properties文件(一定要添加到.gitignore,禁止提交到代码库),在里面写入真实值:
    AUTH_TOKEN=your_actual_auth_token_here
    SALT_KEY=your_secure_salt_here
    HTACCESS_USER=admin_user
    HTACCESS_PWD=your_strong_password
    
  • 在Gradle脚本中读取这些值:
    def authToken = project.properties['AUTH_TOKEN'] ?: System.getenv('AUTH_TOKEN')
    def saltKey = project.properties['SALT_KEY'] ?: System.getenv('SALT_KEY')
    
    这样本地构建时会优先读取local.properties,CI/CD环境可以通过系统环境变量传入值,既保证了构建正常,又不会把敏感信息打包进APK。

2. 运行时:用Android Keystore存储敏感密钥

如果你的APP需要在运行时使用密钥(比如加密本地数据),绝对不要硬编码,把密钥存在Android Keystore里:

  • Android Keystore是系统提供的安全存储容器,支持硬件级加密(部分设备),即使APK被反编译,攻击者也无法直接获取里面的内容。
  • 示例代码思路:
    // 生成并存储密钥到Keystore
    KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
    keyStore.load(null);
    if (!keyStore.containsAlias("app_secure_salt")) {
        KeyGenerator keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");
        keyGenerator.init(new KeyGenParameterSpec.Builder("app_secure_salt", 
            KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
                .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
                .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
                .build());
        keyGenerator.generateKey();
    }
    // 运行时获取密钥
    SecretKey secretKey = (SecretKey) keyStore.getKey("app_secure_salt", null);
    
    用这个密钥来加密需要存储的敏感数据,即使本地数据被窃取,没有Keystore的权限也无法解密。

3. 混淆+字符串加密:降低逆向难度

如果有些字符串不得不打包进APK,先加密再存储,同时开启ProGuard/R8混淆:

  • 对敏感字符串进行AES加密,把加密后的字节数组或字符串放在代码里,运行时用Keystore里的密钥解密。
  • 开启ProGuard/R8混淆,在proguard-rules.pro中配置混淆规则,把解密相关的类、方法名混淆成无意义的名称,增加攻击者逆向的成本。
    比如:
    -keep class com.yourpackage.EncryptionUtils {
        public static byte[] decrypt(byte[]);
    }
    -obfuscationdictionary proguard-dictionary.txt
    

4. 云端拉取:完全不在APK中存储敏感配置

最安全的方式是把所有敏感配置放在后端服务,APP启动时通过HTTPS请求获取:

  • 后端接口需要做身份校验(比如设备绑定、用户登录态校验),确保只有合法的APP实例能获取配置。
  • 获取到的配置只存在内存中,不要写入本地文件或SharedPreferences,使用完后及时清理内存。
    这样APK里完全没有敏感信息,即使被反编译,攻击者也拿不到任何有用的配置。

额外注意事项

  • 检查你的.gitignore,确保local.propertiesgradle-local.properties、任何包含敏感信息的文件都不会被提交到代码库。
  • 禁止在Logcat中打印任何敏感信息,即使是调试阶段也要注意。
  • 所有涉及敏感数据的网络请求必须用HTTPS,防止中间人攻击窃取数据。

内容的提问来源于stack exchange,提问作者Saikumar

火山引擎 最新活动