You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AES解密抛出BadPaddingException:UDP加密聊天程序问题求助

问题分析与修复方案

核心问题定位

  1. 客户端未执行加密操作:客户端发送逻辑直接将明文转为字节数组发送,完全没调用Encryption方法,服务器却对明文执行解密,必然触发填充验证失败。
  2. UDP接收时传递了无效数据:服务器直接把整个缓冲区buffer传给解密方法,但UDP数据包的有效数据长度是datagramPacket.getLength(),多余的空字节会破坏解密的填充规则。
  3. (可选)AES模式默认值不安全:Cipher.getInstance("AES")默认使用ECB模式(无安全性可言),建议显式指定安全模式如CBC。

修复代码

1. 修复客户端发送逻辑(调用加密方法)

public void sentThenReceive(byte[] key) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
    Scanner scanner = new Scanner(System.in);
    while (true) {
        try {
            String messageToSend = scanner.nextLine();
            byte[] message = messageToSend.getBytes();
            // 新增:调用加密方法生成密文
            byte[] encryptedMessage = Encryption(message, key);
            // 使用密文创建UDP数据包
            DatagramPacket datagramPacket = new DatagramPacket(encryptedMessage, encryptedMessage.length, inetAddress, 2468);
            datagramSocket.send(datagramPacket);
            // 后续接收逻辑(如果有)...
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

2. 修复服务器接收逻辑(截取有效数据)

public void receiveThenSend(byte[] key) throws NoSuchPaddingException, NoSuchAlgorithmException, IllegalBlockSizeException, BadPaddingException, InvalidKeyException {
    while (true) {
        try {
            DatagramPacket datagramPacket = new DatagramPacket(buffer, buffer.length);
            datagramSocket.receive(datagramPacket);
            // 修复:只提取UDP包中的有效数据
            byte[] receivedData = new byte[datagramPacket.getLength()];
            System.arraycopy(datagramPacket.getData(), 0, receivedData, 0, datagramPacket.getLength());
            // 解密并打印
            System.out.println(Decryption(receivedData, key));
            // 后续发送逻辑(如果有)...
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

3. 进阶优化:使用安全的AES模式(CBC)

如果要提升安全性,可修改加解密方法为CBC模式(需要初始化向量IV),示例如下:

客户端加密方法

public byte[] Encryption(byte[] message, byte[] keyBytes) throws InvalidKeyException, NoSuchPaddingException, 
        NoSuchAlgorithmException, BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException {
    // 显式指定AES/CBC/PKCS5Padding模式
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    SecretKey secretKey = new SecretKeySpec(keyBytes, "AES");
    
    // 生成随机IV(需和密文一起发送给服务器)
    byte[] iv = new byte[cipher.getBlockSize()];
    new SecureRandom().nextBytes(iv);
    IvParameterSpec ivParams = new IvParameterSpec(iv);
    
    cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivParams);
    byte[] encrypted = cipher.doFinal(message);
    
    // 合并IV和密文,发送时一起传递
    byte[] result = new byte[iv.length + encrypted.length];
    System.arraycopy(iv, 0, result, 0, iv.length);
    System.arraycopy(encrypted, 0, result, iv.length, encrypted.length);
    return result;
}

服务器解密方法

public String Decryption(byte[] message, byte[] keyBytes) throws InvalidKeyException, NoSuchPaddingException, 
        NoSuchAlgorithmException, BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException {
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    SecretKey secretKey = new SecretKeySpec(keyBytes, "AES");
    
    // 分离IV和密文
    byte[] iv = new byte[cipher.getBlockSize()];
    System.arraycopy(message, 0, iv, 0, iv.length);
    byte[] encrypted = new byte[message.length - iv.length];
    System.arraycopy(message, iv.length, encrypted, 0, encrypted.length);
    
    IvParameterSpec ivParams = new IvParameterSpec(iv);
    cipher.init(Cipher.DECRYPT_MODE, secretKey, ivParams);
    byte[] originalMessage = cipher.doFinal(encrypted);
    return new String(originalMessage);
}

额外注意事项

  • 确保客户端和服务器使用完全一致的密钥(当前密钥开头有空格,注意不要误删或多输入)。
  • UDP是无连接协议,实际应用中需处理丢包、乱序问题,学习阶段可暂不考虑。

内容的提问来源于stack exchange,提问作者Thunder123

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 09:15:35