EOFException:Java客户端 - 服务器应用程序中抛出java.io.EOFException

时间:2015-05-12 05:29:49

标签: java networking network-programming

我已经编写了以下客户端 - 服务器对来设置IPSec连接的非常简化版本(与密码术相关)。

问题是,在第二次调用readObject()时,即:

        // Receive finished message from server
        finishedMessage = (BigInteger) inputStream.readObject();

我得到java.io.EOFException.

应该说,在大多数运行中,EOFException被抛出,但在某些运行中它运行得很完美?

我现在已经调试了几个小时,但无法找到错误。

如果有人能看到错误,请告诉我 - 我会很感激!

错误讯息:

[CLIENT]: Connected...
[CLIENT]: Common key = 33569
java.io.EOFException
    at java.io.ObjectInputStream$BlockDataInputStream.peekByte(Unknown Source)
    at java.io.ObjectInputStream.readObject0(Unknown Source)
    at java.io.ObjectInputStream.readObject(Unknown Source)
    at IPSecClient.SetupSSLConnection(IPSecClient.java:68)
    at IPSecClient.main(IPSecClient.java:116)

客户端:

import java.math.BigInteger;
import java.net.*;
import java.util.ArrayList;
import java.util.Random;
import java.io.*;

public class IPSecClient {
    private Socket socket;
    private ObjectInputStream inputStream;
    private ObjectOutputStream outputStream;
    private IPSec gen;
    private ArrayList<BigInteger[]> messages;
    private BigInteger[] message;
    private final int port, numBits;
    private String address;
    private Random rand;
    private int fixedNumber;
    private BigInteger fixedPrime, fixedBase, partialKeyClient, 
    partialKeyServer, commonKey, publicKeyServer, modulusServer;

    public IPSecClient() {
        rand = new Random();
        numBits = 256;
        fixedNumber = rand.nextInt(1000);
        fixedPrime = new BigInteger("51803");
        fixedBase = new BigInteger("3");    
        gen = new IPSec();
        gen.KeyGen(numBits);
        messages = new ArrayList<BigInteger[]>();
        port = 5000;
        address = "localhost";
    }

    public void SetupSSLConnection() {
        try {
            socket = new Socket(address, port);
            outputStream = new ObjectOutputStream(socket.getOutputStream());
            inputStream = new ObjectInputStream(socket.getInputStream());

            System.out.println("[CLIENT]: Connected...");

            // Send partial key and certificate (public key) to server
            partialKeyClient = fixedBase.pow(fixedNumber).mod(fixedPrime);
            message = new BigInteger[] {partialKeyClient, gen.PublicKey(), gen.Modulus()};
            messages.add(message);
            outputStream.writeObject(message);
            outputStream.flush();

            // Receive partial key and certificate from server
            message = (BigInteger[]) inputStream.readObject();
            messages.add(message);
            partialKeyServer = message[0];
            publicKeyServer = message[1];
            modulusServer = message[2];

            // Generate common key
            commonKey = partialKeyServer.pow(fixedNumber).mod(fixedPrime);
            System.out.println("[CLIENT]: Common key = " + commonKey.intValue());

            // Send finished message
            BigInteger accumulatedMessages = AccumulateMessages(messages).mod(gen.PublicKey());
            BigInteger finishedMessage = gen.GenerateRSASignature(accumulatedMessages);

            outputStream.writeObject(finishedMessage);
            outputStream.flush();

            // Receive finished message from server
            finishedMessage = (BigInteger) inputStream.readObject();

            // Verify finished message
            boolean result = gen.VerifyRSASignature(AccumulateMessages(messages).mod(publicKeyServer), finishedMessage, publicKeyServer, modulusServer);
            System.out.println("[CLIENT]: Verification of finished message " + (result ? "succeeded" : "failed"));

            if (!result) {
                System.out.println("[CLIENT]: SSL-connection could not be estasblished...");
                CloseConnection(-1);
            }

            System.out.println("[CLIENT]: SSL-connection estasblished...");
            CloseConnection(0);
        } catch (SocketException se) {
            se.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }


    private void CloseConnection(int exitCode) {
        try {
            socket.close();
            outputStream.close();
            inputStream.close();
            System.exit(exitCode);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private BigInteger AccumulateMessages(ArrayList<BigInteger[]> messages) {
        BigInteger accumulator = new BigInteger("0");
        for (BigInteger[] message : messages)
        {
            for (BigInteger part : message)
            {
                accumulator = accumulator.add(part);
            }
        }
        return accumulator;
    }

    public static void main(String[] args) {
        IPSecClient client = new IPSecClient();
        client.SetupSSLConnection();
    }
}

服务器

import java.io.*;
import java.math.BigInteger;
import java.net.*;
import java.util.ArrayList;
import java.util.Random;

public class IPSecServer {
    private ServerSocket serverSocket;
    private Socket socket;
    private ObjectInputStream inputStream;
    private ObjectOutputStream outputStream;
    private IPSec gen;
    private ArrayList<BigInteger[]> messages;
    private BigInteger[] message;
    private final int port;
    private Random rand;
    private int fixedNumber;
    private BigInteger fixedPrime, fixedBase, partialKeyClient, 
    partialKeyServer, commonKey, publicKeyClient, modulusClient;

    public IPSecServer() {
        rand = new Random();
        fixedNumber = rand.nextInt(1000);
        fixedPrime = new BigInteger("51803");
        fixedBase = new BigInteger("3");    
        gen = new IPSec();
        gen.KeyGen(2048);
        messages = new ArrayList<BigInteger[]>();
        port = 5000;
    }

    public void SetupSSLConnection() {
        try {
            serverSocket = new ServerSocket(port);
            System.out.println("[SERVER]: Listening...");
            socket = serverSocket.accept();
            inputStream = new ObjectInputStream(socket.getInputStream());
            outputStream = new ObjectOutputStream(socket.getOutputStream());

            System.out.println("[SERVER]: Connected... " + "Port/IP: " + socket.getPort() + socket.getInetAddress());

            // Receive partial key and certificate from client
            message = (BigInteger[]) inputStream.readObject();
            messages.add(message);
            partialKeyClient = message[0];
            publicKeyClient = message[1];
            modulusClient = message[2];

            // Send partial key and certificate to client
            partialKeyServer = fixedBase.pow(fixedNumber).mod(fixedPrime);
            message = new BigInteger[] {partialKeyServer, gen.PublicKey(), gen.Modulus()};
            messages.add(message);
            outputStream.writeObject(message);
            outputStream.flush();

            // Generate common key
            commonKey = partialKeyClient.pow(fixedNumber).mod(fixedPrime);
            System.out.println("[SERVER]: Common key = " + commonKey.intValue());

            // Receive finished message from client
            BigInteger finishedMessage = (BigInteger) inputStream.readObject();
            messages.add(new BigInteger[] {finishedMessage});

            // Verify finished message
            boolean result = gen.VerifyRSASignature(AccumulateMessages(messages).mod(publicKeyClient), finishedMessage, publicKeyClient, modulusClient);
            System.out.println("[SERVER]: Verification of finished message " + (result ? "succeeded" : "failed"));

            if (!result) {
                System.out.println("[SERVER]: SSL-connection could not be estasblished...");
                CloseConnection(-1);
            }

            // Send finished message to client
            BigInteger accumulatedMessages = AccumulateMessages(messages).mod(gen.PublicKey());
            finishedMessage = gen.GenerateRSASignature(accumulatedMessages);
            outputStream.writeObject(finishedMessage);
            outputStream.flush();           

            System.out.println("[SERVER]: SSL-connection estasblished...");
            CloseConnection(0);

        } catch (SocketException se) {
            System.exit(0);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    private void CloseConnection(int exitCode) {
        try {
            socket.close();
            outputStream.close();
            inputStream.close();
            serverSocket.close();
            System.exit(exitCode);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private BigInteger AccumulateMessages(ArrayList<BigInteger[]> messages) {
        BigInteger accumulator = new BigInteger("0");
        for (BigInteger[] message : messages)
        {
            for (BigInteger part : message)
            {
                accumulator = accumulator.add(part);
            }
        }
        return accumulator;
    }

    public static void main(String[] args) {
        IPSecServer server = new IPSecServer();
        server.SetupSSLConnection();
    }
}

的IPSec:

import java.math.BigInteger;
import java.util.Random;
import java.security.*;

public class IPSec {

    private static final BigInteger one = new BigInteger("1");

    // private key (n,d)
    private BigInteger privateKey;
    // public key (n,e)
    private BigInteger publicKey = new BigInteger("3");
    // modulus n
    private BigInteger modulus;

    public IPSec() {
    }

    // PUBLIC KEY

    public BigInteger PublicKey() {
        return publicKey;
    }

    public BigInteger Modulus() {
        return modulus;
    }

    // KEY GENERATION

    public void KeyGen(int keyLength) {     
        BigInteger p = BigInteger.probablePrime((int)Math.ceil(keyLength / 2), new Random());
        BigInteger q = BigInteger.probablePrime((int)Math.ceil(keyLength / 2), new Random());

        while (!(p.subtract(one)).gcd(publicKey).equals(one))
            p = p.nextProbablePrime();

        while (!(q.subtract(one)).gcd(publicKey).equals(one))
            q = q.nextProbablePrime();

        BigInteger phi = (p.subtract(one)).multiply(q.subtract(one));       
        modulus = p.multiply(q);
        privateKey = publicKey.modInverse(phi);
    }

    // ENCRYPT

    public BigInteger Encrypt(BigInteger message) {
        return message.modPow(publicKey, modulus);
    }

    public static BigInteger Encrypt(BigInteger message, BigInteger publicKey, BigInteger modulus) {
        return message.modPow(publicKey, modulus);
    }

    // DECRYPT

    public BigInteger Decrypt(BigInteger message) {
        return message.modPow(privateKey, modulus);
    }

    // SIGNATURE GENERATION 

    // Generate RSA-signatures for a message
    public BigInteger GenerateRSASignature(BigInteger message) {
        MessageDigest digest;
        try {
            digest = MessageDigest.getInstance("SHA-256");
            return Decrypt(new BigInteger(1, digest.digest(message.toByteArray())).mod(Modulus()));
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            System.exit(-1);
        }
        return message;
    }

    // Verify RSA-signatures for a message
    public boolean VerifyRSASignature(BigInteger message, BigInteger signature) {
        try {
            MessageDigest digest = MessageDigest.getInstance("SHA-256");
            return (new BigInteger(1, digest.digest(message.toByteArray())).mod(Modulus())).equals(Encrypt(signature));
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            System.exit(-1);
        }
        return false;
    }

    public boolean VerifyRSASignature(BigInteger message, BigInteger signature, 
            BigInteger publicKey, BigInteger modulus) {
        try {
            MessageDigest digest = MessageDigest.getInstance("SHA-256");
            return (new BigInteger(1, digest.digest(message.toByteArray())).mod(Modulus())).equals(Encrypt(signature, publicKey, modulus));
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            System.exit(-1);
        }
        return false;
    }

    public static void main(String[] args) {
        Testing();
    }

    // MISC

    public void printKeys() {
        String s = "";
        s += "public  = " + publicKey  + "\n";
        s += "private = " + privateKey + "\n";
        s += "modulus = " + modulus;
        System.out.println(s);
    }

    public static void Testing() {
        IPSec gen = new IPSec();
        gen.KeyGen(128);
        BigInteger message = new BigInteger("329");
        System.out.println("Verify: " + gen.VerifyRSASignature(message, gen.GenerateRSASignature(message)));
    }
}

1 个答案:

答案 0 :(得分:1)

您的服务器正在此处的签名验证阶段进行调整:

if (!result) {
    System.out.println("[SERVER]: SSL-connection could not be established...");
    CloseConnection(-1);
}

并关闭套接字而不发送FINISHED消息。检查其输出日志。在这种情况下,您可能应首先发送错误对象。或者将EOFException视为握手失败。

NB:

  • 为安全起见,最好在两端ObjectOutputStream之前构建ObjectInputStream
  • 您应该关闭ObjectOutputStream,而不是套接字或输入流。这样你就可以确定它会被冲洗掉。关闭其中任何一个就会关闭另外两个。
  • 不要打电话给SSL&#39; SSL&#39;当他们不是。