Java密码和套接字流的三个问题

时间:2013-11-11 04:54:13

标签: java sockets inputstream encryption

我的三个问题如下:

  • 我无法弄清楚如何填充字节并让它在没有错误的情况下工作: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();
}
 }

2 个答案:

答案 0 :(得分:1)

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

在关闭密钥文件后尝试将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.

答案 1 :(得分:0)

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