我正在使用Cipher
进行加密/解密。一直很好,但是现在在处理大数组字节时遇到问题。
这是我的实现:
val cipher = Cipher.getInstance("AES/GCM/NoPadding")
cipher.init(Cipher.ENCRYPT_MODE, getSecretKey())
val encryptedData = cipher.doFinal(textToEncrypt.toByteArray(StandardCharsets.UTF_8))
如上所述,仅当输入文本太大时,问题才会发生。例如,如果我将长度为168036的字节数组作为doFinal
的输入传递,它将给我返回长度为65652的字节数组。
这与密码的限制有关吗?如果可以,是否有增加输入缓冲区的方法?
[GVillani82显示,他沉迷于一些严肃的Google-Fu;从评论中:
[表明这很可能是运行时27及更低版本中的错误。大概在更高版本中已修复,尽管错误报告没有说哪个版本。
但是,最好使用增量更新来解决此问题。在这种情况下,请确保您的缓冲区严格低于64KiB,例如32KiB。
基本上,在Java中,有两种方法可以执行增量加密。一种是简单地使用许多Cipher.update
方法之一,并从缓冲区中为其提供文本(请注意,Cipher.update
在可用时会返回部分密文)。然后,您需要使用doFinal()
方法来完成加密。
另一个是使用流式传输。对于加密,通常使用CipherOutputStream
,然后手动将明文复制到该明文中(或者再次使用缓冲区),或者如果要写入整个流,则只需执行InputStream.transferTo
方法即可。在这种情况下,您可能希望直接从资源中读取字节(保持原始编码)。但是,在这种情况下,您不知道它将使用什么缓冲区大小。如果您需要流,那么使用update
/ doFinal
调用创建自己的流类相对容易。
[使用输入和输出缓冲区(doFinal
)的ByteBuffer
似乎仍然会触发错误,因此将无法使用。