跳转至

第17章 安全与加密技术

安全与加密技术图

学习目标:掌握Android安全开发,理解加密算法、安全存储、代码混淆等技术。

预计学习时间:3-5天 实践时间:1-2天


目录

  1. 安全概述
  2. 数据加密
  3. 安全存储
  4. 代码安全
  5. 网络安全
  6. 实践练习

1. 安全概述

1.1 Android安全模型

  • 应用沙箱:每个应用运行在独立的进程中
  • 权限系统:访问敏感资源需要权限
  • 签名机制:应用发布需要签名
  • 加密存储:敏感数据加密保存

1.2 常见安全威胁

  • 数据泄露
  • 中间人攻击
  • 代码注入
  • 逆向工程

2. 数据加密

2.1 对称加密

Kotlin
// AES 对称加密工具类
object AESUtil {
    private const val ALGORITHM = "AES"                        // 加密算法名称
    private const val TRANSFORMATION = "AES/CBC/PKCS7Padding"  // 算法/模式/填充方式
    private const val IV_SIZE = 16                              // 初始化向量长度(CBC 模式必需)
    private const val KEY_SIZE = 32                             // 密钥长度 32 字节 = AES-256

    /**
     * 从密码派生固定长度密钥(生产环境推荐使用 PBKDF2)
     */
    private fun deriveKey(password: String): SecretKeySpec {
        val keyBytes = password.toByteArray(Charsets.UTF_8)
            .copyOf(KEY_SIZE) // 截断或零填充到 32 字节,保证密钥长度固定
        return SecretKeySpec(keyBytes, ALGORITHM)
    }

    // 加密函数:明文 + 密码 → Base64 编码的密文
    fun encrypt(data: String, password: String): String {
        val cipher = Cipher.getInstance(TRANSFORMATION)     // 获取 AES/CBC 加密器实例
        val secretKey = deriveKey(password)                  // 从密码派生密钥
        // 生成随机 IV(每次加密使用不同 IV,增强安全性)
        val iv = ByteArray(IV_SIZE).also { SecureRandom().nextBytes(it) }
        cipher.init(Cipher.ENCRYPT_MODE, secretKey, IvParameterSpec(iv))
        val encrypted = cipher.doFinal(data.toByteArray())  // 执行加密
        // 将 IV 与密文拼接后 Base64 编码,解密时需要同一 IV
        return Base64.encodeToString(iv + encrypted, Base64.DEFAULT)
    }

    // 解密函数:Base64 密文 + 密码 → 明文字符串
    fun decrypt(encryptedData: String, password: String): String {
        val combined = Base64.decode(encryptedData, Base64.DEFAULT)  // Base64 解码
        val iv = combined.copyOfRange(0, IV_SIZE)                    // 提取前 16 字节作为 IV
        val cipherText = combined.copyOfRange(IV_SIZE, combined.size) // 剩余部分为密文
        val cipher = Cipher.getInstance(TRANSFORMATION)
        val secretKey = deriveKey(password)
        cipher.init(Cipher.DECRYPT_MODE, secretKey, IvParameterSpec(iv))  // 使用相同 IV 初始化
        val decrypted = cipher.doFinal(cipherText)                       // 执行解密
        return String(decrypted)                                          // 字节数组转字符串
    }
}

2.2 非对称加密

Kotlin
// RSA 非对称加密工具类(公钥加密、私钥解密)
object RSAUtil {
    // 生成 RSA 密钥对(包含公钥和私钥)
    fun generateKeyPair(): KeyPair {
        val keyGen = KeyPairGenerator.getInstance("RSA")  // 获取 RSA 密钥生成器
        keyGen.initialize(2048)                            // 设置密钥长度为 2048 位(安全推荐值)
        return keyGen.generateKeyPair()                    // 返回生成的公钥/私钥对
    }

    // 使用公钥加密数据,返回 Base64 编码的密文
    fun encrypt(data: String, publicKey: PublicKey): String {
        val cipher = Cipher.getInstance("RSA")             // 获取 RSA 加密器
        cipher.init(Cipher.ENCRYPT_MODE, publicKey)        // 用公钥初始化为加密模式
        // 加密字节数据并进行 Base64 编码,便于传输和存储
        return Base64.encodeToString(cipher.doFinal(data.toByteArray()), Base64.DEFAULT)
    }
}

3. 安全存储

3.1 EncryptedSharedPreferences

Kotlin
// 创建主密钥,使用 AES256-GCM 方案(密钥存储在 Android Keystore 中)
val masterKey = MasterKey.Builder(context)
    .setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
    .build()

// 创建加密的 SharedPreferences 实例
val sharedPreferences = EncryptedSharedPreferences.create(
    context,
    "secret_shared_prefs",           // 加密存储文件名
    masterKey,                        // 用于加解密的主密钥
    EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,   // 键名加密方案
    EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM  // 键值加密方案
)

// 像普通 SharedPreferences 一样使用,数据会自动加密存储
sharedPreferences.edit().putString("api_key", "secret_key").apply()

3.2 Keystore系统

Kotlin
// 在 Android Keystore 中生成 AES 密钥(密钥由硬件安全模块保护,无法导出)
val keyGenerator = KeyGenerator.getInstance("AES", "AndroidKeyStore")
// 配置密钥参数
val keyGenParameterSpec = KeyGenParameterSpec.Builder(
    "my_key",        // 密钥别名,后续通过此名称引用密钥
    KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT  // 密钥用途:加密和解密
)
    .setBlockModes(KeyProperties.BLOCK_MODE_GCM)           // 使用 GCM 模式(支持认证加密)
    .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)  // GCM 模式不需要填充
    .build()
keyGenerator.init(keyGenParameterSpec)  // 用参数初始化密钥生成器
keyGenerator.generateKey()              // 生成密钥并自动存储到 Keystore

4. 代码安全

4.1 ProGuard/R8混淆

Text Only
# 保留指定类名不被混淆(第三方库或反射使用的类需要保留)
-keep public class com.example.MyClass

# 保留被 Gson @SerializedName 注解标记的字段,防止 JSON 序列化/反序列化失败
-keepclassmembers class * {
    @com.google.gson.annotations.SerializedName <fields>;
}

# 混淆后保留源文件名和行号,便于线上崩溃日志的堆栈追踪
-renamesourcefileattribute SourceFile
-keepattributes SourceFile,LineNumberTable

4.2 根检测

Kotlin
// 检测设备是否已 Root(Root 设备存在安全风险,可能被恶意利用)
fun isDeviceRooted(): Boolean {
    // 常见的 Root 标志文件路径列表
    val paths = arrayOf(
        "/system/app/Superuser.apk",  // SuperUser 管理应用
        "/sbin/su",                   // su 二进制文件(常见路径)
        "/system/bin/su",
        "/system/xbin/su"
    )
    // 只要任意一个路径存在,就判定设备已 Root
    return paths.any { File(it).exists() }
}

5. 网络安全

5.1 SSL Pinning

Kotlin
// SSL 证书固定(Certificate Pinning)——防止中间人攻击
// 将服务器证书的 SHA-256 指纹绑定到客户端,只信任指定证书
val certificatePinner = CertificatePinner.Builder()
    .add("api.example.com", "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=")  // 域名 + 证书哈希
    .build()

// 创建配置了证书固定的 OkHttp 客户端
val client = OkHttpClient.Builder()
    .certificatePinner(certificatePinner)  // 启用证书固定校验
    .build()

5.2 安全网络配置

XML
<!-- res/xml/network_security_config.xml -->
<network-security-config>
    <domain-config cleartextTrafficPermitted="false">
        <domain includeSubdomains="true">api.example.com</domain>
        <pin-set expiration="2027-01-01">
            <pin digest="SHA-256">sha256_hash_here</pin>
        </pin-set>
    </domain-config>
</network-security-config>

6. 实践练习

练习1:加密存储用户数据

任务:实现用户敏感信息加密存储

要求: - 使用EncryptedSharedPreferences - 密钥存储在Keystore - 支持数据读取

练习2:安全网络请求

任务:实现证书固定的网络请求

要求: - 配置SSL Pinning - 处理证书错误 - 日志记录


本章小结

核心要点

  1. 加密算法:AES对称加密,RSA非对称加密
  2. 安全存储:EncryptedSharedPreferences,Keystore
  3. 代码安全:ProGuard混淆,根检测
  4. 网络安全:SSL Pinning,HTTPS

下一步

完成本章学习后,请进入第18章:音视频开发


本章完成时间:预计3-5天