Android平台AES-128文件加密方案问询
Android平台AES-128文件加密实现方案
问题背景
开发Android应用时,需实现AES-128文件加密功能。Android官方提供的EncryptedFile类虽能便捷实现文件加密,但该类的FileEncryptionScheme仅提供AES-256相关选项,无法直接用于AES-128加密。官方示例代码如下:
// 推荐使用官方指定的密钥生成参数规范,也可自定义 val keyGenParameterSpec = MasterKeys.AES256_GCM_SPEC val mainKeyAlias = MasterKeys.getOrCreate(keyGenParameterSpec) // 创建或替换同名文件,文件名不能包含路径分隔符,且不支持追加写入 val fileToWrite = "my_sensitive_data.txt" val encryptedFile = EncryptedFile.Builder( File(DIRECTORY, fileToWrite), applicationContext, mainKeyAlias, EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB ).build() val fileContent = "MY SUPER-SECRET INFORMATION" .toByteArray(StandardCharsets.UTF_8) encryptedFile.openFileOutput().apply { write(fileContent) flush() close() }
解决方案
1. 官方EncryptedFile类的限制
目前EncryptedFile的内置加密方案仅支持AES-256,没有官方提供的AES-128配置选项,因此无法直接通过该类实现AES-128文件加密。若优先考虑官方API,只能选择AES-256方案;若必须使用AES-128,需自行实现加密逻辑。
2. 自行实现AES-128文件加密
自行实现时需遵守安全规范:必须使用随机生成的IV(初始化向量),且IV需与密文一同存储(解密时需要用到);推荐使用GCM模式(自带完整性校验),比CBC模式更安全。以下是适配文件加密的AES-128实现代码:
import java.io.File import java.io.FileInputStream import java.io.FileOutputStream import java.security.SecureRandom import javax.crypto.Cipher import javax.crypto.spec.GCMParameterSpec import javax.crypto.spec.SecretKeySpec // AES-128 GCM模式加密文件 fun encryptFileAes128(inputFile: File, outputFile: File, key: ByteArray) { // 生成12字节随机IV(GCM模式推荐使用12字节IV) val iv = ByteArray(12) SecureRandom().nextBytes(iv) // 初始化AES-128 GCM加密器 val secretKey = SecretKeySpec(key, "AES") val cipher = Cipher.getInstance("AES/GCM/NoPadding") val gcmSpec = GCMParameterSpec(128, iv) // 128位认证标签长度 cipher.init(Cipher.ENCRYPT_MODE, secretKey, gcmSpec) // 读取输入文件,加密后写入输出文件(先写IV,再写密文) FileInputStream(inputFile).use { inputStream -> FileOutputStream(outputFile).use { outputStream -> // 先写入IV outputStream.write(iv) // 加密并写入文件内容 val buffer = ByteArray(4096) var bytesRead: Int while (inputStream.read(buffer).also { bytesRead = it } != -1) { val encryptedBytes = cipher.update(buffer, 0, bytesRead) encryptedBytes?.let { outputStream.write(it) } } // 写入最后一块加密数据和认证标签 val finalBytes = cipher.doFinal() finalBytes?.let { outputStream.write(it) } } } } // AES-128 GCM模式解密文件 fun decryptFileAes128(inputFile: File, outputFile: File, key: ByteArray) { FileInputStream(inputFile).use { inputStream -> // 先读取IV(12字节) val iv = ByteArray(12) inputStream.read(iv) // 初始化AES-128 GCM解密器 val secretKey = SecretKeySpec(key, "AES") val cipher = Cipher.getInstance("AES/GCM/NoPadding") val gcmSpec = GCMParameterSpec(128, iv) cipher.init(Cipher.DECRYPT_MODE, secretKey, gcmSpec) // 读取密文并解密,写入输出文件 FileOutputStream(outputFile).use { outputStream -> val buffer = ByteArray(4096) var bytesRead: Int while (inputStream.read(buffer).also { bytesRead = it } != -1) { val decryptedBytes = cipher.update(buffer, 0, bytesRead) decryptedBytes?.let { outputStream.write(it) } } // 写入最后一块解密数据 val finalBytes = cipher.doFinal() finalBytes?.let { outputStream.write(it) } } } } // 使用示例 fun usageExample() { // AES-128密钥必须是16字节(128位),推荐用Android Keystore安全存储 val aes128Key = ByteArray(16).apply { SecureRandom().nextBytes(this) // 随机生成安全密钥 } val inputFile = File("/path/to/your/plainfile.txt") val encryptedFile = File("/path/to/your/encryptedfile.aes") val decryptedFile = File("/path/to/your/decryptedfile.txt") // 加密文件 encryptFileAes128(inputFile, encryptedFile, aes128Key) // 解密文件 decryptFileAes128(encryptedFile, decryptedFile, aes128Key) }
注意事项
- 密钥必须是16字节长度(对应AES-128),严禁明文硬编码,推荐使用Android Keystore存储密钥;
- GCM模式的IV需随机生成,不可重复使用同一IV与密钥的组合;
- 示例中使用
use语法自动管理IO资源,避免内存泄漏和数据流未关闭问题。
内容的提问来源于stack exchange,提问作者segoSambel
相关产品推荐
相关产品推荐

