我正在加密字符串并将它们写入文本文件。为了解密内容,我正在读取该文件并打印解密的数据。当我用一个字符串值测试我的代码时,它加密和解密完全正常;但是,当我添加更多字符串进行加密时,加密工作正常,但解密给了我这个异常“javax.crypto.BadPaddingException:给定最终块没有正确填充”
这是我的代码。请帮忙!
// these are initialized in main
SecretKey key = KeyGenerator.getInstance("DES").generateKey();
AlgorithmParameterSpec paramSpec = new IvParameterSpec(iv);
ecipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
dcipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
ecipher.init(Cipher.ENCRYPT_MODE, key, paramSpec);
dcipher.init(Cipher.DECRYPT_MODE, key, paramSpec);
// catches ..
// it will take a string and the file that will have the encrypted strings
private static void encrypt(String s, OutputStream os) throws IllegalBlockSizeException, BadPaddingException {
try {
byte[] buf = s.getBytes();
byte[] b = ecipher.doFinal(buf);
os.write(b);
// this is to write a new line after writing each encrypted value and avoid overwriting
os.write(System.getProperty("line.separator").getBytes());
os.flush();
os.close();
}
catch (IOException e) {
System.out.println("I/O Error:" + e.getMessage());
}
}
// this will take the file that has all of the encryptions
private static void decrypt(InputStream is) throws IllegalBlockSizeException, BadPaddingException {
try {
byte[] buf = new byte[is.available()];
is.read(buf);
byte[] decrypted = dcipher.doFinal(buf); // THE CAUSE OF THE PROBLEM!!!!
System.out.println(new String (decrypted));
is.close();
}
catch (IOException e) {
System.out.println("I/O Error:" + e.getMessage());
}
答案 0 :(得分:1)
加密时,您将加密数据写入输出文件,然后添加换行符,但在解密时,您似乎正在读取文件的全部内容并对其进行解密,这将包括换行符,它将包含换行符。尝试解密,好像它是密文的一部分,导致你的填充异常。您还尝试使用单个解密调用解密所有单独编写的字符串,而它们需要单独解密。
我建议在将写入输出文件并附加换行符之前将加密数据转换为Base64 。解密时,读取一行,从Base64转换回byte[]
并解密,然后对输入中的每一行重复。
答案 1 :(得分:0)
在加密字节之后添加一个新行是多余的,应该删除。
问题的实际原因是使用InputStream.available()来获取数据的大小。此方法可以返回从0到输入流中的实际字节数的任何值,因此不适合确定输入数据的大小。在您的示例中,它返回一些值,并且您读取等于它的字节数,但很可能它不是所有加密数据,并且密码将无法正确解码。
通常,无法确定输入流的大小,因此您必须使用循环来读取流。解密代码应基于以下范例:
private static byte[] decrypt( Cipher dcipher, InputStream in, int BUFFER_SIZE ) throws Exception {
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] inputBuffer = new byte[ BUFFER_SIZE ]; // 4K or 8K are pretty good buffer size values
int r = in.read( inputBuffer );
while ( r >= 0 ) {
byte[] outputUpdate = dcipher.update( inputBuffer, 0, r );
out.write( outputUpdate );
r = in.read( inputBuffer );
}
byte[] outputFinalUpdate = dcipher.doFinal();
out.write( outputFinalUpdate );
return out.toByteArray();
}
InputStream
。InputStream.read(byte[])
。ByteArrayOutputStream
可以作为获取可调整大小的字节数组的最简单方法。您还可以首先使用与上述周期相似的代码读取整个加密数据,但不使用中间Cipher.update()
,然后使用单Cipher.doFinal()
次调用一次性解码。
private static byte[] decrypt( Cipher dcipher, InputStream in, int BUFFER_SIZE ) throws Exception {
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] inputBuffer = new byte[ BUFFER_SIZE ]; // 4K or 8K are pretty good buffer size values
int r = in.read( inputBuffer );
while ( r >= 0 ) {
out.write( inputBuffer, 0, r );
r = in.read( inputBuffer );
}
return dcipher.doFinal( out.toByteArray() );
}