4

我的三个问题如下:

  • 我不知道如何填充字节并让它在没有错误的情况下工作:javax.crypto.BadPaddingException: Given final block not properly padded

  • 如果我将它切换到 NoPadding,我必须使用一个 8 的倍数的字符串

  • 最后也是最重要的是,我无法让服务器正确解密它。我在CipherClient.java中证明解密在通过套接字发送之前有效。

使用 asHex,我可以证明 CipherServer.java 获得了相同的字节,但是在解密消息时,它没有正确解密。

我错过了什么吗?我不明白客户端如何正确解密它,但是一旦通过流,服务器就不能。

我整天都在互联网上寻找示例,但我无法弄清楚。在有人说什么之前,我知道使用 DES 并不明智,但是,这仅适用于需要 DES 的项目。

密码客户端.java

import java.io.*;
import java.net.*;
import java.security.*;

import javax.crypto.*;

public class CipherClient
{public static void main(String[] args) throws Exception 
{
    try {
        //Starts socket
        String host = "localhost";
        int port = 8001;
        Socket s = new Socket(host, port);

        //Generate a DES key.
        KeyGenerator keygen = KeyGenerator.getInstance("DES");
        keygen.init(56, new SecureRandom());
        SecretKey key = keygen.generateKey();           

        //Store the key in a file
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("KeyFile.xx"));
        oos.writeObject(key);
        oos.close();

        //Start Cipher Instance and cipher the message
        //Cipher c = Cipher.getInstance("DES/ECB/PKCS5Padding");            
        Cipher c = Cipher.getInstance("DES/ECB/NoPadding");
        c.init(Cipher.ENCRYPT_MODE,key);

        //Get string and encrypted version
        //String message = "The quick brown fox jumps over the lazy dog.";
        String message = "12345678";
        byte[] encryptedMsg = c.doFinal(message.getBytes("UTF-8"));

        System.out.println("Client - Message: " + message);
        System.out.println("Client - Encrypted: " + CipherServer.asHex(encryptedMsg));


        //TEST DECRYPT W/ KEY FILE W/O SERVER (WORKS!)
        //-------------------------------

        //Read key from file test
            ObjectInputStream file = new ObjectInputStream(new FileInputStream("KeyFile.xx"));
            SecretKey key2 = (SecretKey) file.readObject();
            System.out.println("Key Used: " + file.toString());
            file.close();

        //Decrypt Test
            c.init(Cipher.DECRYPT_MODE,key2);
            byte[] plainText = c.doFinal(encryptedMsg);
            System.out.println("Decrypted Message: " + new String(plainText));


        //Open stream to cipher server
        DataOutputStream os = new DataOutputStream(s.getOutputStream());
        os.writeInt(encryptedMsg.length);
        os.write(encryptedMsg);

        os.flush();
        os.close();

        //Close socket
        s.close();

    }catch (Exception e) {
        e.printStackTrace();
    }
}
 }

密码服务器.java

import java.io.*;
import java.net.*;
import java.security.NoSuchAlgorithmException;

import javax.crypto.*;


public class CipherServer
{
public static void main(String[] args) throws Exception 
{
    //Start socket server
    int port = 8001;
    ServerSocket s = new ServerSocket();
    s.setReuseAddress(true);
    s.bind(new InetSocketAddress(port));
    Socket client = s.accept();

    CipherServer server = new CipherServer();
    server.decryptMessage(client.getInputStream());

    s.close();
}


public void decryptMessage(InputStream inStream) throws IOException, NoSuchAlgorithmException
{
    try {

        //Create the Data input stream from the socket
        DataInputStream in = new DataInputStream(inStream);

        //Get the key
        ObjectInputStream file = new ObjectInputStream(new FileInputStream("KeyFile.xx"));
        SecretKey key = (SecretKey) file.readObject();
        System.out.println("Key Used: " + file.toString());
        file.close();

        //Initiate the cipher
        //Cipher d = Cipher.getInstance("DES/ECB/PKCS5Padding");                        
        Cipher d = Cipher.getInstance("DES/ECB/NoPadding");
        d.init(Cipher.DECRYPT_MODE,key);

        int len = in.readInt();
        byte[] encryptedMsg = new byte[len];
        in.readFully(encryptedMsg);         

        System.out.println("Server - Msg Length: " + len);
        System.out.println("Server - Encrypted: " + asHex(encryptedMsg));


        //String demsg = new String(d.doFinal(encryptedMsg), "UTF-8");
        //System.out.println("Decrypted Message: " + demsg);
        // -Print out the decrypt String to see if it matches the orignal message.
        byte[] plainText = d.doFinal(encryptedMsg);
        System.out.println("Decrypted Message: " + new String(plainText, "UTF-8"));


    } catch (Exception e) {
        e.printStackTrace();
    }
}

//Function to make the bytes printable (hex format)
public static String asHex(byte buf[]) {
    StringBuilder strbuf = new StringBuilder(buf.length * 2);
    int i;
    for (i = 0; i < buf.length; i++) {
        if (((int) buf[i] & 0xff) < 0x10) {
            strbuf.append("0");
        }
        strbuf.append(Long.toString((int) buf[i] & 0xff, 16));
    }
    return strbuf.toString();
}
 }
4

2 回答 2

1

You create your socket to the server before you create the key file, and the server properly read the key from last run.

Try moving the Socket s = new Socket(host, port); to after you have closed the key file.

The events is as follows:

    Client                 Server
    -----------------      ------------------
    Connect to server
                           Accept connection
                           Read key file
                           (block on receive)
    Generate Key
    Write Key File
    Send message
                           Receive message
    etc.
于 2013-11-14T02:30:18.830 回答
0

查看代码我只能假设密钥不正确。也许您使用了错误的文件夹或类似文件夹。BadPaddingException通常仅在填充不正确、数据的最后一个块已损坏或您使用了错误的键时才会发生。也许您可以使用调试器或SecretKey.getEncoded()检查密钥是否与您的十六进制编码器一起使用。

于 2013-11-11T21:32:38.673 回答