2017-12-28 3 views
0

Ich habe zwei Methoden zum Verschlüsseln/Entschlüsseln von JSON-Nachrichten zwischen Clients und einem Server. Der Server verfügt über ein Paar RSA-Schlüssel (einen privaten und einen öffentlichen) und einen Client. Darüber hinaus haben beide Zugriff auf einen symmetrischen Sitzungsschlüssel, der beim ersten Herstellen einer Kommunikation generiert wird, der zum Chiffrieren der JSON-Nachricht verwendet wird, da der Kanal selbst nicht sicher ist. Der Client generiert einen AES-Schlüssel (Sitzungsschlüssel), den er dann mit dem öffentlichen Schlüssel des Servers (allen bekannt) verschlüsselt und an den Server sendet, der den Sitzungsschlüssel entschlüsselt und in einer HashMap unter der ID des Kunden speichert.JAVA - Nicht übereinstimmende AES-Schlüssellängen

Hier ist das Problem, obwohl: Ich habe die Schlüssellänge vor dem Senden überprüft und es ist 16 Bytes lang. Wenn der Server den verschlüsselten Sitzungsschlüssel empfängt und entschlüsselt, ist er 24 Byte lang. Ich nehme an, dass zwischendurch etwas schief gelaufen ist, entweder während der Chiffre oder der Entschlüsselungsoperation. Dies ist ein Problem, da der Server die Anforderung nicht entschlüsseln und lesen kann, wenn der Client mit dem Senden von Anforderungen (in Form von verschlüsselten JSON-Nachrichten) beginnen möchte, da der Schlüssel die falsche Größe hat (java.security.InvalidKeyException: Ungültige Schlüsselgröße) oder Standardparameter).

Die Chiffre/entziffern Methoden unten geschrieben werden:

public String cipher(Key key, String alg, String msg){ 
    try { 
     Cipher c = Cipher.getInstance(alg); 
     c.init(Cipher.ENCRYPT_MODE, key); 
     return encoder.encodeToString(c.doFinal(msg.getBytes("UTF-8"))); 
    } catch (IllegalBlockSizeException e) { 
     (...) 
    } 
} 

Die encoder/decoder von java.util.Base64 sind.

public String decipher(Key key, String alg, String msg){ 
    try { 
     Cipher c = Cipher.getInstance(alg); 
     c.init(Cipher.DECRYPT_MODE,key); 
     return new String(c.doFinal(decoder.decode(msg)), "UTF-8"); 
    } catch (IllegalBlockSizeException e) { 
     (...) 
    } 
} 

Client-Chiffrierung und Senden der Sitzungsschlüssel:

SecretKey sk = KeyGenerator.getInstance("AES/CBC/PKCS5Padding").generateKey(); 

System.out.println(sk.getEncoded().length) //length = 16 bytes 

String sessionKey = cipher(client.getServerPublicKey(), 
    "RSA/ECB/PKCS5Padding", encoder.encodeToString(sk.getEncoded())); 

printWriter.write("{(...), \"key\":\"" + sessionKey + "\"}"); 

Server die chiffrierten Sitzungsschlüssel zu empfangen und es in der HashMap Sparend:

byte[] aux = decipher(registry.getServerPrivateKey(), 
    "RSA/ECB/PKCS5Padding", data.get("key").toString().replace("\"", "")) 
     .getBytes("UTF-8"); 

System.out.println(aux.length) //length = 24 bytes 

registry.addSession(..., new SecretKeySpec(aux, 0, aux.length, "AES")); 

Ich habe versucht, verschiedene Algorithmen und verschiedene Polsterungen , aber ich kann nicht herausfinden, wo der Fehler ist.

Antwort

1

Sie base64 kodieren Ihren Schlüssel, bevor sie mit dieser Aussage Verschlüsselung:

String sessionKey = cipher(client.getServerPublicKey(), 
    "RSA/ECB/PKCS5Padding", encoder.encodeToString(sk.getEncoded())); 

.. Ihr 16-Byte-Schlüssel in eine lange Base64-Darstellung 24 Zeichen zu machen. Sie müssen Ihren Schlüssel vor der Verschlüsselung nicht mit base64 verschlüsseln, da die Verschlüsselung binäre Daten problemlos verarbeiten kann. Versuchen Sie es mit dieser:

String sessionKey = cipher(client.getServerPublicKey(), 
    "RSA/ECB/PKCS5Padding", sk.getEncoded()); 

Und zugleich Ihre cipher(..) Methode ändern msg als byte[]

public String cipher(Key key, String alg, byte[] msg){ 
    try { 
     Cipher c = Cipher.getInstance(alg); 
     c.init(Cipher.ENCRYPT_MODE, key); 
     return encoder.encodeToString(c.doFinal(msg)); 
    } catch (IllegalBlockSizeException e) { 
     (...) 
    } 
} 

auch zu akzeptieren, Ihre decipher(..) ändern wie auch auf binär:

public byte[] decipher(Key key, String alg, String msg){ 
    try { 
     Cipher c = Cipher.getInstance(alg); 
     c.init(Cipher.DECRYPT_MODE,key); 
     return c.doFinal(decoder.decode(msg)); 
    } catch (IllegalBlockSizeException e) { 
     (...) 
    } 
} 
+0

Diese sicherlich das Problem der Schlüsselgröße gelöst, es ist jetzt 16 Bytes auf Client- und Server-Seiten, danke! Dieser 'encoder.encodeToString (sk.getEncoded())' war der Überrest einer früheren Implementierung, die ich versucht hatte. –

Verwandte Themen