Tim*_*Tim 0 java encryption bouncycastle aes
我正在创建一个程序,允许用户上传和下载加密文件,如果他们具有正确的权限,则解密它们.加密和上传很好,下载也是如此,但是当我尝试解密时,我得到"pad block corrupted"错误.
我想要做的是获取加密文件,然后制作一个未加密的副本
我缩短了我的意思所以请不要评论它看起来不完整.
注册机:
public static SecretKey genGroupSecretKey() {
try {
KeyGenerator keyGen = KeyGenerator.getInstance("AES", "BC");
keyGen.init(128);
return keyGen.generateKey();
} catch (NoSuchAlgorithmException | NoSuchProviderException e) {
System.err.println("Error: " + e.getMessage());
e.printStackTrace(System.err);
}
return null;
}
Run Code Online (Sandbox Code Playgroud)
加密:
try (FileInputStream fis = new FileInputStream(sourceFile)) {
response = Utils.decryptEnv((byte[]) tempResponse.getObjContents().get(0), fsSecretKey, ivSpec);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding", "BC");
cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivSpec);
do {
byte[] buf = new byte[4096];
int n = fis.read(buf); // can throw an IOException
else if (n < 0) {
System.out.println("Read error");
fis.close();
return false;
}
byte[] cipherBuf = cipher.doFinal(buf);
// send through socket blah blah blah
} while (fis.available() > 0);
Run Code Online (Sandbox Code Playgroud)
解密:
...
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding", "BC");
cipher.init(Cipher.DECRYPT_MODE, secKey, ivSpec);
File file = new File("D_" + filename); // D_ for decrypted
FileOutputStream fos = null;
if (!file.exists()) {
file.createNewFile();
fos = new FileOutputStream(file);
}
try (FileInputStream fis = new FileInputStream(filename)) {
do {
byte[] buf = new byte[4096];
int n = fis.read(buf);
if (n < 0) {
System.out.println("Read error");
fis.close();
return false;
}
byte[] cipherBuf = cipher.doFinal(buf); // ERROR HERE
System.out.println("IS THIS WORKING WTF: " + new String(cipherBuf));
fos.write(cipherBuf, 0, n);
} while (fis.available() > 0);
fis.close();
fos.close();
return true;
Run Code Online (Sandbox Code Playgroud)
你应该Cipher.doFinal()只为最后一块数据.您应该修改加密和解密代码以Cipher.update()用于所有中间数据,并Cipher.doFinal()在最后使用单个调用.允许Cipher.update()用于所有中间数据块,并在最后调用Cipher.doFinal()带有空数组.
此外,您忽略了fis.read(buf)将从流中读取的数据传递给密码时的返回值.
此外,您正在使用InputStream.available()条件来结束循环.即使循环中的代码是正确的,由于循环条件的虚假触发,您也会得到不可预测的结果.
使用以下模式处理密码:
Cipher cipher = ...
InputStream in = ...
OutputStream out = ...
byte[] inputBuffer = new byte[ BUFFER_SIZE ];
int r = in.read(inputBuffer);
while ( r >= 0 ) {
byte[] outputUpdate = cipher.update( inputBuffer, 0, r );
out.write( outputUpdate );
r = in.read(inputBuffer);
}
byte[] outputFinalUpdate = cipher.doFinal();
out.write( outputFinalUpdate );
Run Code Online (Sandbox Code Playgroud)
检查其他变体Cipher.update()- 可以使用两个预先分配的缓冲区并最小化其他分配.
还要检查是否可以重用javax.crypto.CipherInputStream和javax.crypto.CipherOutputStream分类,这样就不必直接使用密码.