Cipher.doFinal之后的Android AES加密丢失字节

时间:2019-03-01 12:24:38

标签: android encryption kotlin aes

我正在尝试从滑行加密输入流。

我将输入流转换为字节数组,并以我的加密方法传递它:

fun encrypt(input: ByteArray): ByteArray {

    Log.e("TAG", "inputsize: ${input.size}")

    val iv           = ByteArray(KeyStoreHelper.IV_SIZE)
    val secureRandom = SecureRandom()
    secureRandom.nextBytes(iv)

    val c = Cipher.getInstance(KeyStoreHelper.AES_MODE)
    c.init(Cipher.ENCRYPT_MODE, getKey(), GCMParameterSpec(KeyStoreHelper.GCM_SIZE, iv))
    Log.e("TAG", "outputsize: ${c.getOutputSize(input.size)}")
    val encodedBytes = c.doFinal(input)

    Log.e("TAG", "encodedBytesSize: ${encodedBytes.size}")

    val byteBuffer = ByteBuffer.allocate( iv.size + encodedBytes.size)
    byteBuffer.put(iv)
    byteBuffer.put(encodedBytes)

    Log.e("TAG", "byteBuffer: ${byteBuffer.array().size}")


    return byteBuffer.array()
}

日志如下:

inputsize: 750683 
outputsize: 750699 
encodedBytesSize: 95339 
byteBuffer: 95351

如您所见,加密的图像字节数组很小,我不明白为什么-如果我尝试对字符串或较小的图像(大约100kb-200kb)进行加密,它就像一种魅力。

感谢您的帮助!

亲切的问候 汤姆

1 个答案:

答案 0 :(得分:2)

似乎您在一个不合逻辑的位置遇到了一个错误,这很奇怪:95339是质数。您几乎会认为有些开发人员会故意保留该值,以防万一他忘记或测试测试团队。

但是,将所有数据缓存在内存中以获取如此大量的信息不是一个好主意,即使对于GCM也是如此。您应该尝试使用流媒体代替。您可以使用CipherOutputStream进行加密,并使用CipherInputStream进行解密。您可以将这些流连接到其他流,例如FileOutputStreamFileInputStream,以直接读取/写入文件系统。也可以将IV写入这些基础流。

请注意,不同提供商处理GCM的方式可能会有很大差异。正如您所注意到的,与Android密钥存储区关联的存储区是出于安全性(无论如何都是密钥)而不是速度而构建的。 GCM的其他实现可能不会显示此错误。请注意,不同的Java(-esk)平台和这些平台的版本之间可用的提供程序可能会有所不同。