2017-10-03 20 views
0

J'ai un gros programme client-serveur.java.io.EOFException lors de la lecture/décryptage à partir d'un socket

Mais si j'envoie un paquet crypté, en essayant de le recevoir et de le décrypter, provoque java.io.EOFException.

Si j'utilise la méthode non cryptée (par exemple pour les pings), cela fonctionne parfaitement.

code client (réception):

InputStream is = subChannel.getInputStream(); 
ObjectInputStream pre = new ObjectInputStream(is); 
ObjectInputStream ois; 
boolean crypt = (boolean) pre.readObject(); 

if (crypt) { 
    ois = new ObjectInputStream(SimpleAES.decryptInputStream(c.getAesKey(), is)); 
} else { 
    ois = new ObjectInputStream(is); 
} 

Response<? extends Serializable> res = (Response<? extends Serializable>) ois.readObject(); 
req.onResponse(res); 
is.close(); 

subChannel est un socket qui relie seperated.

Je sais que j'obtiens une réponse cela ne peut pas être l'erreur.

SimpleAES

private final static byte[] iv = new byte[16]; 
private static final String TRANSFORMATION = "AES/CBC/NoPadding"; 

public static CipherOutputStream cryptOutputStream(SecretKey key,OutputStream os) throws InvalidKeyException, InvalidAlgorithmParameterException, NoSuchAlgorithmException, NoSuchPaddingException { 
     Cipher cipher = Cipher.getInstance(TRANSFORMATION); 
     IvParameterSpec ivspec = new IvParameterSpec(iv); 
     cipher.init(Cipher.ENCRYPT_MODE, key, ivspec); 
     CipherOutputStream out = new CipherOutputStream(os, cipher); 
     return out; 
} 

public static CipherInputStream decryptInputStream(SecretKey key,InputStream os) throws InvalidKeyException, InvalidAlgorithmParameterException, NoSuchAlgorithmException, NoSuchPaddingException { 
     Cipher cipher = Cipher.getInstance(TRANSFORMATION); 
     IvParameterSpec ivspec = new IvParameterSpec(iv); 
     cipher.init(Cipher.DECRYPT_MODE, key, ivspec); 
     CipherInputStream out = new CipherInputStream(os, cipher); 
     return out; 
} 

code serveur (envoi):

OutputStream base; 
base = sock.getOutputStream(); 

ObjectOutputStream infoStream = new ObjectOutputStream(base); 

infoStream.writeObject(pack.isEncrypted()); 
ObjectOutputStream packageStream; 

if (pack.isEncrypted()) { 
    String tolken = pack.getClientTolken(); 
    Session s = getSession(tolken); 
    packageStream = new ObjectOutputStream(SimpleAES.cryptOutputStream(s.getAesKey(), base)); 
} 
else 
    packageStream = new ObjectOutputStream(base); 

packageStream.writeObject(pack); 
packageStream.flush(); 

if (pack instanceof Request) { 
    InputStream baseIn = sock.getInputStream(); 
    ObjectInputStream res; 

    if (pack.isEncrypted()) { 
     res = new ObjectInputStream(SimpleAES.decryptInputStream(getSession(pack.getClientTolken()).getAesKey(), baseIn)); 
    } else { 
     res = new ObjectInputStream(baseIn); 
    } 

    @SuppressWarnings("unchecked") 
    Response<? extends Serializable> response = (Response<? extends Serializable>) res.readObject(); 
    ((Request) pack).onResponse(response); 
    res.close(); 
} 

base.close(); 

Je ne pense pas que la trace de la pile vous donnera un grand information, mais voici:

Ping Response : 8ms 
[Client] Added TolkenRequest to Query 
[Client] Added RSARequest to Query 
[Client] Added AESKeyPack to Query 
[Client] Added ValidIdRequest to Query 
java.io.EOFException 
Fatal Error Exit 
    at java.io.ObjectInputStream$PeekInputStream.readFully(Unknown Source) 
    at java.io.ObjectInputStream$BlockDataInputStream.readShort(Unknown Source) 
    at java.io.ObjectInputStream.readShort(Unknown Source) 
    at java.io.ObjectStreamClass.readNonProxy(Unknown Source) 
    at java.io.ObjectInputStream.readClassDescriptor(Unknown Source) 
    at java.io.ObjectInputStream.readNonProxyDesc(Unknown Source) 
    at java.io.ObjectInputStream.readClassDesc(Unknown Source) 
    at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source) 
    at java.io.ObjectInputStream.readObject0(Unknown Source) 
    at java.io.ObjectInputStream.defaultReadFields(Unknown Source) 
    at java.io.ObjectInputStream.readSerialData(Unknown Source) 
    at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source) 
    at java.io.ObjectInputStream.readObject0(Unknown Source) 
    at java.io.ObjectInputStream.readObject(Unknown Source) 
    at com.niton.tele.core.network.client.ClientListenerThread.run(ClientListenerThread.java:104) 

ClientListenerThread.java:104 est cette ligne Réponse res = (Réponse) ois.readObject();

+0

Ceci n'est pas lié à votre problème, mais vous devez utiliser l'IV correctement: lorsque vous le chiffrez, donnez-lui une valeur (aléatoire) imprévisible, transmettez-le en clair (il n'a pas besoin d'être crypté) et utilisez-le lors du décryptage. L'utilisation de la IV comme vous n'êtes pas considéré comme sécurisé. –

+0

Je sais. C'était uniquement pour les tests. Parce que si elle est toujours 0000000 je n'ai pas besoin de Tod envoyer – Niton

+0

Je voudrais essayer de séparer les deux types de flux: écrire une méthode simple pour déchiffrer un flux chiffré et traiter quelques octets d'abord pour s'assurer que cela fonctionne, avant d'essayer de envoyer des objets sérialisés à travers. Juste mes 2 cents. –

Répondre

1

Vous ne pouvez pas mélanger différents flux tamponnés sur le même socket. Ils voleront des données les uns aux autres. Vous devez le re-concevoir et le réécrire en utilisant un seul ObjectInputStream et ObjectOutputStream pour la durée de vie du socket.

Peut-être que vous recherchez SealedObject?