如何在Android Kotlin中解密ImageMagick加密的JPG图片并展示
方案说明
可以通过paraphrase.txt密钥文件解密该加密图片,以下是可落地的实现方案:
前置说明
ImageMagick的-encipher参数本质是基于密钥文件内容生成AES密钥,对图片的像素数据进行对称加密,未修改图片的文件头结构,因此直接加载加密文件只会展示噪点,需要解密像素数据后再渲染。
实现步骤
1. 资源准备
- 把密钥文件
paraphrase.txt放入Android项目的assets目录(不要放入drawable目录,避免资源编译破坏原始密钥内容) - 加密图片保留在drawable目录即可
2. 代码实现(纯Kotlin匹配AES解密方案)
import android.graphics.Bitmap import android.graphics.BitmapFactory import javax.crypto.Cipher import javax.crypto.spec.IvParameterSpec import javax.crypto.spec.SecretKeySpec import kotlin.io.readBytes // 扩展方法:读取assets文件的字节数组 fun android.content.Context.readAssetBytes(fileName: String): ByteArray = assets.open(fileName).use { it.readBytes() } // 解密图片方法 fun decryptImage(context: Context, drawableId: Int, keyFileName: String = "paraphrase.txt"): Bitmap? { // 1. 读取加密图片的原始字节流 val encryptedBytes = context.resources.openRawResource(drawableId).use { it.readBytes() } // 2. 读取密钥,按AES位数截取 val keyBytes = context.readAssetBytes(keyFileName).take(32).toByteArray() // AES-256取前32位,AES-128改为取前16位 val ivBytes = keyBytes.take(16).toByteArray() // ImageMagick默认用密钥前16位作为IV // 3. 初始化AES解密器,匹配ImageMagick的AES/CBC/PKCS7Padding模式 val cipher = Cipher.getInstance("AES/CBC/PKCS7Padding") val secretKey = SecretKeySpec(keyBytes, "AES") cipher.init(Cipher.DECRYPT_MODE, secretKey, IvParameterSpec(ivBytes)) // 4. 执行解密 val decryptedBytes = cipher.doFinal(encryptedBytes) // 5. 转换为Bitmap返回 return BitmapFactory.decodeByteArray(decryptedBytes, 0, decryptedBytes.size) } // 页面调用示例 val file = "e$filename" val id = resources.getIdentifier(file, "drawable", packageName) if (id > 0) { // 建议放到子线程执行解密,避免大图片阻塞主线程 val decryptedBitmap = decryptImage(this, id) decryptedBitmap?.let { binding.imgFoto.setImageBitmap(it) } }
3. 备选兼容方案(无加密模式匹配问题)
如果上述AES解密出现匹配失败的情况,可通过NDK集成轻量版ImageMagick库到Android项目,直接调用原生decipher能力处理:
- 编译对应架构的libmagick.so库
- 传入加密图片字节流和密钥,调用
convert - -decipher paraphrase.txt -命令获取解密后的图片字节流 - 转换为Bitmap渲染即可
注意事项
- 密钥文件不要直接明文存放在assets目录,建议对密钥内容做二次混淆加密,避免APK反编译后密钥泄露
- 解密后的Bitmap使用完及时调用
recycle()回收,减少内存占用 - 大图片解密建议放在子线程执行,避免阻塞主线程导致ANR
内容的提问来源于stack exchange,提问作者GSandro_Strongs
相关产品推荐
相关产品推荐

