【问题标题】:javax.crypto.BadPaddingException: Given final block not properly padded - DES Decryptionjavax.crypto.BadPaddingException:给定最终块未正确填充 - DES 解密
【发布时间】:2018-04-09 20:58:50
【问题描述】:

我正在尝试解密服务器上的消息 - 我得到的错误是

使用的加密技术 - DES。

--线程“main”javax.crypto.BadPaddingException 中的异常:给定最终块未正确填充

我很难解决这个问题, 任何帮助将不胜感激

class TCPClient {
public static void main(String argv[]) throws Exception {
    byte[] sentence, textEncrypted;
    String modifiedSentence;
    String password;
    BufferedReader inFromUser = new BufferedReader(new InputStreamReader(System.in));
    Socket clientSocket = new Socket("localhost", 6789);
    DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
    password = "Passcode";
    byte[] salt = new byte[64];
    Random rnd = new Random();
    rnd.nextBytes(salt);
    byte[] data = deriveKey(password, salt, 64);

    // BufferedReader inFromServer = new BufferedReader(new
    // InputStreamReader(clientSocket.getInputStream()));
    System.out.println("Enter the Data to be transmisted to server\n");
    sentence = inFromUser.readLine().getBytes();
    SecretKey desKey = SecretKeyFactory.getInstance("DES").generateSecret(new DESKeySpec(data));
    Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
    cipher.init(Cipher.ENCRYPT_MODE, desKey);
    textEncrypted = cipher.doFinal(sentence);
    outToServer.writeBytes(new String(textEncrypted) + '\n');
    clientSocket.close();
}

public static byte[] deriveKey(String password, byte[] salt, int keyLen) {
    SecretKeyFactory kf = null;
    try {
        kf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
    } catch (NoSuchAlgorithmException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    KeySpec specs = new PBEKeySpec(password.toCharArray(), salt, 1024, keyLen);
    SecretKey key = null;
    try {
        key = kf.generateSecret(specs);
    } catch (InvalidKeySpecException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return key.getEncoded();
}
}

服务器端代码

class TCPServer {
public static void main(String argv[]) throws Exception {
    String password = null;
    String capitalizedSentence;
    ServerSocket welcomeSocket = new ServerSocket(6789);

    while (true) {
        Socket connectionSocket = welcomeSocket.accept();
        BufferedReader inFromClient = new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));
        password = "Passcode";
        byte[] salt = new byte[64];
        Random rnd = new Random();
        rnd.nextBytes(salt);
        byte[] data = deriveKey(password, salt, 64);
        byte [] EncyptedText = inFromClient.readLine().getBytes();
        System.out.println("Received Encrypted message " + EncyptedText);
        SecretKey desKey = SecretKeyFactory.getInstance("DES").generateSecret(new DESKeySpec(data));
        Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, desKey);
        // Decrypt the text
        System.out.println("Text Received " + EncyptedText);
        byte[] textDecrypted = cipher.doFinal(EncyptedText);
        System.out.println("Text Decryted : " + new String(textDecrypted));

    }
}

public static byte[] deriveKey(String password, byte[] salt, int keyLen) {
        SecretKeyFactory kf = null;
        try {
            kf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
        } catch (NoSuchAlgorithmException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        KeySpec specs = new PBEKeySpec(password.toCharArray(), salt, 1024, keyLen);
        SecretKey key = null;
        try {
            key = kf.generateSecret(specs);
        } catch (InvalidKeySpecException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return key.getEncoded();
}
}

【问题讨论】:

  • 这里只是集思广益,但您的客户端盐与服务器端盐不同。这不会造成任何问题吗?
  • 我确实尝试过使用盐,但我最终得到了同样的错误:(

标签: java cryptography


【解决方案1】:

这样做会丢失数据:

outToServer.writeBytes(new String(textEncrypted) + '\n');

除此之外,没有必要。密文并不是现代密码的真正文本,它是二进制的。由于套接字提供二进制InputStreams 和OutputStreams,因此根本没有理由将密文转换为字符串。所需要做的就是将可能的输入字符串转换为二进制(当然,在客户端和服务器上使用相同的编码 - 现在首选 UTF-8)。

【讨论】:

  • 在修改后的代码中,我写的是字节而不是通过 TCP 发送字符串。我面临的唯一问题是在服务器上获取密钥,请建议我如何在系统之间共享密钥。
  • 好吧,在这种情况下,您可能想要共享一个包含密钥的二进制文件。我的意思是,无论如何,那里没有什么是安全的,所以我认为这只是测试。 SecretKey.getEncoded(), KeyFactory... 但这是另一个问题。为了安全起见,请使用 TLS 和 PKI 方案。
猜你喜欢
  • 2014-01-22
  • 2018-08-17
  • 1970-01-01
  • 1970-01-01
  • 2011-05-16
  • 2013-12-02
  • 2012-05-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多