gpt4 book ai didi

java - AES解密时,出现 "Given final block not properly padded"

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:50:05 25 4
gpt4 key购买 nike

我正在做一个简单的加密文件传输系统,现在因运行时异常而停止:

Exception in thread "main" javax.crypto.BadPaddingException: Given final block not properly padded
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:811)
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:676)
at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:313)
at javax.crypto.Cipher.doFinal(Cipher.java:2087)
at ftpclient.FTPClient.main(FTPClient.java:82)

我尝试使用一个字符串来调试我的代码,以使用相同的 key 进行加密和解密并且它有效。但是,当我尝试从文件传输流时,总是会出现此异常。

下面是双方的代码。起初他们会通过 RSA 交换对称 key (AES key ),然后通过 AES 加密传输大文件。我们可以关注每个代码的最后一部分,其中文件是通过 AES key 加密和解密的。

服务器端:

package ftpserver;

import java.io.*;
import java.net.*;
import javax.crypto.*;
import java.security.*;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;
/**
*
* @author Han
*/
public class FTPServer {
public static void main(String[] args) throws Exception {

//generate symmetric key and initialize cipher for AES
SecretKey skey = null;
Cipher aes = Cipher.getInstance("AES/ECB/PKCS5Padding");

KeyGenerator kg = KeyGenerator.getInstance("AES");
kg.init(128);
skey = kg.generateKey();

//get public key of the receive side
final String PUBLIC_KEY_PATH = "key_b.public";
PublicKey publickey = null;
try {
FileInputStream fis;
fis = new FileInputStream(PUBLIC_KEY_PATH);
ObjectInputStream oin = new ObjectInputStream(fis);
publickey = (PublicKey) oin.readObject();
oin.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
};

//encrypte symmetric key with own private key and send out
Cipher rsa = Cipher.getInstance("RSA");
rsa.init(Cipher.ENCRYPT_MODE, publickey);
byte cipherSKey[] = rsa.doFinal(skey.getEncoded());
//System.out.println(skey); //debug

//create tcp server socket
ServerSocket tcp = new ServerSocket(2000);
Socket client = tcp.accept();

//get input&output stream from the TCP connection
InputStream in = client.getInputStream();
OutputStream out = client.getOutputStream();

//generate a file input stream to get stream from file
File sentFile = new File("F:\\test.txt");
FileInputStream fin = new FileInputStream(sentFile);

//send encrypted symmetric key first
out.write("Symmetric Key:\r\n".getBytes());
out.write(cipherSKey);

DataInputStream din = new DataInputStream(in);
while(true)
{
if(din.readLine().equals("Received."))
{
System.out.println("Send key successfully.");
break;
}

};

//send files
int count;
byte[] bytearray = new byte[8192];
byte[] cipherbuffer;
while((count = fin.read(bytearray))>0)
{
cipherbuffer = Base64.encodeBase64(aes.doFinal(bytearray));
out.write(cipherbuffer,0,cipherbuffer.length);
System.out.println(count+" bytes have been sent.");
};

out.flush();
out.close();

client.close();


}
}

客户端:

package ftpclient;

import java.io.*;
import java.net.*;
import java.security.PrivateKey;
import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;
/**
*
* @author Han
*/
public class FTPClient {

public static void main(String[] args) throws Exception
{
//get the private key of this side


final String PUBLIC_KEY_PATH = "key_b.privat";
PrivateKey privatkey = null;
try {
FileInputStream fis;
fis = new FileInputStream(PUBLIC_KEY_PATH);
ObjectInputStream oin = new ObjectInputStream(fis);
privatkey = (PrivateKey) oin.readObject();
oin.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
};

Cipher rsa = Cipher.getInstance("RSA");
rsa.init(Cipher.DECRYPT_MODE, privatkey);

//create tcp client socket
Socket tcp = new Socket("192.168.1.185",2000);
InputStream in = tcp.getInputStream();
OutputStream out = tcp.getOutputStream();
DataInputStream din = new DataInputStream(in);

//receive symmetric key from server
byte keybuffer[] = new byte[128];
SecretKey skey = null;

while(true)
{
if(din.readLine().equals("Symmetric Key:"))
{
System.out.println("Start to receiving key...");
in.read(keybuffer);
byte[] skeycode = rsa.doFinal(keybuffer);
skey = new SecretKeySpec(skeycode, 0, skeycode.length, "AES");
out.write("Received.\r\n".getBytes());
break;
}
};
//create cipher for symmetric decryption
Cipher aes = Cipher.getInstance("AES/ECB/PKCS5Padding");
aes.init(Cipher.DECRYPT_MODE, skey);
//System.out.println(skey); //debug

//create file stream
FileOutputStream fos = new FileOutputStream("E:\\test_cp.txt");

int count;
int i = 0;
byte[] bytearray = new byte[8192];
byte[] buffer;
while((count = in.read(bytearray)) > 0)
{
buffer = (aes.doFinal(Base64.decodeBase64(bytearray)));
fos.write(buffer,0,buffer.length);
i +=count;
System.out.println(i+" bytes have been received.");
};


fos.flush();
fos.close();
in.close();

tcp.close();
System.out.println("File Transfer completed");

}

}

最佳答案

您多次调用 doFinal。或至少尝试这样做。

当您读取数据时,并非所有数据都立即到达或被读入缓冲区。所以你解密一些然后再读一遍。没关系。

但是当您这样做时,您每次都在调用 doFinal,而不是 update。这是错误的,也是错误的原因。相反,将 doFinal 替换为 update ,然后在读取完所有数据后添加一个额外的 doFinal (有一个 doFinal() 正是出于这个原因,它不接受任何参数。

参见 http://docs.oracle.com/javase/7/docs/api/javax/crypto/Cipher.html

另见 http://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Electronic_codebook_.28ECB.29为什么 ecb 模式通常不是一个好主意(看看企鹅图片)。

关于java - AES解密时,出现 "Given final block not properly padded",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20332636/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com