我试图在Android上使用javax.crypto.Cipher,用AES-GCM对一个数据流进行分块加密。据我所知,人们可以多次使用Cipher.update来进行多部分的加密操作,并用Cipher.doFinal来最终完成。然而,当使用AES/GCM/NoPadding转换时,Cipher.update拒绝向提供的缓冲区输出数据,并返回0字节的写入量。缓冲区在Cipher内部不断增加,直到我调用.doFinal。这似乎也发生在CCM(和我假设的其他认证模式),但对于其他模式,如CBC的工作。
我想GCM可以在加密的同时计算认证标签,所以我不清楚为什么不允许我在Cipher中消耗缓冲区。
我做了一个例子,只有一个对.update的调用:(kotlin)
val secretKey = KeyGenerator.getInstance("AES").run {
init(256)
generateKey()
val iv = ByteArray(12)
SecureRandom().nextBytes(iv)
val cipher = Cipher.getInstance("AES/GCM/NoPadding")
cipher.init(Cipher.ENCRYPT_MODE, secretKey, IvParameterSpec(iv))
// Pretend this is some file I want to read and encrypt
val inputBuffer = Random.nextBytes(1024000)
val outputBuffer = ByteArray(cipher.getOutputSize(512))
val read = cipher.update(inputBuffer, 0, 512, outputBuffer, 0)
// ^ at this point, read = 0 and outputBuffer is [0, 0, 0, ...]
// Future calls to cipher.update and cipher.getOutputSize indicate that
// the internal buffer is growing. But I would like to consume it through
// outputBuffer
// ...
cipher.doFinal(outputBuffer, 0)
// Now outputBuffer is populated
我想做的是将一个大文件从磁盘上流出来,对其进行加密,然后在网络上逐块发送,而不必将整个文件数据加载到内存中。我曾试图使用CipherInputStream,但它也有同样的问题。
用AES/GCM是否可以这样做?