【问题标题】:Three problems with Java cipher and socket streamJava密码和套接字流的三个问题
【发布时间】:2013-11-22 19:48:26
【问题描述】:

我的三个问题如下:

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

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

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

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

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

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

CIPHERCLIENT.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();
    }
}
 }

CIPHERSERVER.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();
}
 }

【问题讨论】:

    标签: java sockets inputstream encryption


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

      您在创建密钥文件之前创建了与服务器的套接字,并且服务器从上次运行中正确读取了密钥。

      尝试在关闭密钥文件后将Socket s = new Socket(host, port); 移至。

      事件如下:

          Client                 Server
          -----------------      ------------------
          Connect to server
                                 Accept connection
                                 Read key file
                                 (block on receive)
          Generate Key
          Write Key File
          Send message
                                 Receive message
          etc.
      

      【讨论】:

        猜你喜欢
        • 2012-04-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-03-17
        • 2014-06-11
        • 1970-01-01
        相关资源
        最近更新 更多