我正在尝试用Java学习编码并坚持使用Cipher.update()方法。它是否有一些可以更新的最大数据长度? 这是我所说的一个例子(我把“String s”值仅用于加速过程,这个值通过加密和解密过程):
public class AES {
public static String s = "long string";
public byte [] encryptAES(byte[] data, byte[] keyPass) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, UnsupportedEncodingException {
Cipher ciph = Cipher.getInstance("AES");
SecretKeySpec AESkeySpec = new SecretKeySpec(keyPass, "AES");
ciph.init(ENCRYPT_MODE,AESkeySpec);
ciph.update(s.getBytes());
byte[] encryptedData = ciph.doFinal();
return encryptedData;
}
}
解密后的输出:long string
如果我改变了价值
public static String s = "long long long long long long long long long long long string";
解码后的输出为:g long string
如果在我取出.update()
方法并执行加密之后
Cipher ciph = Cipher.getInstance("AES");
SecretKeySpec AESkeySpec = new SecretKeySpec(keyPass, "AES");
ciph.init(ENCRYPT_MODE,AESkeySpec);
//ciph.update(s.getBytes());
byte[] encryptedData = ciph.doFinal(s.getBytes());
return encryptedData;
我会得到预期的输出,例如:long long long long long long long long long long long string
为什么会这样?
答案 0 :(得分:3)
update
方法返回加密块。但是我看到你只从doFinal
获取密文。您应该使用update
和doFinal
中的所有块来完成加密的块流。
注意:您正在使用ECB模式,这意味着每个块都是独立加密的,它的安全性较低,只有在您知道自己在做什么时才能使用。这就是为什么你能够解密最后一个块(AES的16个字节)并看到截断的明文。更多信息:http://en.wikipedia.org/wiki/Block_cipher_mode_of_operation
答案 1 :(得分:2)
对于ECB和CBC modes of operation,明文的每个块(128位或16个字节,用于AES)或者一旦可用就会被加密。此外,您的示例使用PKCS#7 padding(或者,在Java中,"PKCS5Padding"
)来确保将最后一个明文填充到完整块。否则你将无法加密它。
加密时,缓冲所有生成的密文显然不是一个好主意。因此,update
只会返回可以加密的所有块。因此,您将始终获得多个块大小。这意味着可能将块的一部分保留在内部缓冲区中。当然,一旦为完整块添加了足够的字节,它将加密并返回数据。所有这些意味着更新可能会比输入更多或更少地返回blocksize - 1
个字节。对于较小的输入,它可能根本不返回任何内容 - 所有内容都被缓冲,直到块已满。
现在PKCS#7填充总是应用,将1加到块大小的字节。显然,在应用填充之前,密码必须知道是否需要更多字节,或者是否达到了明文的结尾。因此doFinal
将返回至少一个块,即使没有数据呈现给它。如果先前的更新未返回任何数据,则doFinal()
方法将返回整个密文。
或多或少可以执行相同的解释推理。另请注意getOutputSize(int inputLength)
的getBlockSize()
和Cipher
方法。如果要立即接收所有数据,可以使用流密码操作模式,例如"AES/CTR/NoPadding"
,其块大小为1个字节。
虽然这可以解释实际问题,但您问的问题是“它是否有一些可以更新的最大数据长度?”。答案是更新仅受JVM中可用内存量和Java中字节数组大小的限制。
答案 2 :(得分:-1)
cipher.update()
返回为该明文生成的密文。
如果忽略该密文,您将无法对其进行解密。