2015-05-12 53 views
0

我編寫了以下客戶端 - 服務器對,以設置IPSec連接的非常簡化版本(與密碼相關)。EOFException:在Java客戶端 - 服務器應用程序中引發java.io.EOFException

的問題是,在第二次調用的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(); 
    } 
} 

安全:

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))); 
    } 
} 
+0

這看起來像是簡單地擊中了'InputStream'的末尾。但是,如果沒有在您的問題中發佈的意見,我們可能無法確切地診斷原因。 –

+0

我已更新錯誤消息。 – Shuzheng

+0

我們也需要看到你的_input_。 –

回答

1

您的服務器barfing在這裏簽名驗證階段:

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

和關閉套接字不發送完成的消息。檢查其輸出日誌。在這種情況下,你應該首先發送一個錯誤對象。否則將EOFException視爲握手失敗。

NB:

  • 爲了安全起見,最好在ObjectInputStream兩端之前去構造的ObjectOutputStream
  • 您應該關閉ObjectOutputStream,而不是套接字或輸入流。這樣你就可以確定它會被刷新。關閉其中三個關閉另外兩個。
  • 不要在事件「SSL」時調用它們。
+0

我也應該關閉serverSocket,對不對? – Shuzheng

+0

不,爲什麼?讓它循環接受另一個連接。一個協議失敗並不意味着你應該停止整個服務器。特別是當你試圖實現安全的東西。 – EJP

+0

Stll得到錯誤:-(,你試過運行代碼嗎? – Shuzheng

相關問題