2017-12-28 31 views
0

クライアントとサーバーの間でJSONメッセージを暗号化/解読する2つの方法があります。サーバーにはRSAキー(プライベートとパブリック)のペアがあり、クライアントも同様です。さらに、チャネル自体が安全でないため、JSONメッセージを暗号化するために使用される通信を最初に確立したときに生成された対称セッション鍵にアクセスできます。クライアントはAES鍵(セッション鍵)を生成し、サーバの公開鍵(すべてに知られている)と暗号化し、サーバに送信します。サーバは、セッション鍵を解読し、クライアントのIDのHashMapに格納します。JAVA - 一致しないAESキーの長さ

これは問題ですが、送信する前に鍵の長さを確認していますが、長さは16バイトです。サーバーが暗号化されたセッションキーを受信し、それを解読すると、サーバーは24バイトの長さになります。私は何か間違っている間、暗号または解読操作中に間違っていたと仮定します。これは、クライアントが要求を(暗号化されたJSONメッセージの形で)送信を開始したいときに、キーのサイズが間違っているためにサーバーが解読して読み取ることができないためです(java.security.InvalidKeyException:Illegal key sizeまたはデフォルトパラメータ)。

暗号/解読方法を以下に掲載されています

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) { 
     (...) 
    } 
} 

encoder/decoderjava.util.Base64からです。

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) { 
     (...) 
    } 
} 

クライアントの暗号化セッション鍵送信:

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の暗号化セッション鍵を受信し、HashMapでそれを保存:

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")); 

を私は異なるアルゴリズムと異なるパディングを試してみましたしかし、私はエラーがどこにあるのかわからない。

答えて

1

あなたはこの文を使用して暗号化する前にあなたの鍵をコード化するbase64である:

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

.. 24文字の長base64で表現へのあなたの16バイトのキーを作ります。暗号化が完全にバイナリデータを処理できるので、暗号化の前にあなたの鍵をbase64でエンコードする必要はありません。

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

と同時に、また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) { 
     (...) 
    } 
} 

をMSGを受け入れるだけでなくのようなバイナリためにあなたのdecipher(..)を変更するには、あなたのcipher(..) Methodeのを変更します:

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

この本を試してみてください確かにキーサイズの問題を解決しました。クライアント側とサーバー側の両方で16バイトになりました。ありがとうございます!その 'encoder.encodeToString(sk.getEncoded())'は私が試した以前の実装の残り物でした。 –

関連する問題