/*
* Created on 08-Nov-2005
* Created by Paul Gardner
* Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* AELITIS, SAS au capital de 40,000 euros
* 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
*
*/
package com.aelitis.azureus.core.clientmessageservice.secure.impl;
import java.io.IOException;
import java.security.SecureRandom;
import java.security.interfaces.RSAPublicKey;
import java.util.HashMap;
import java.util.Map;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import org.minicastle.crypto.CipherParameters;
import org.minicastle.crypto.encodings.PKCS1Encoding;
import org.minicastle.crypto.engines.RSAEngine;
import org.minicastle.crypto.params.ParametersWithRandom;
import org.minicastle.jce.provider.RSAUtil;
import org.gudy.azureus2.core3.util.Debug;
import org.gudy.azureus2.core3.util.RandomUtils;
import org.gudy.azureus2.plugins.utils.StaticUtilities;
import com.aelitis.azureus.core.clientmessageservice.ClientMessageService;
import com.aelitis.azureus.core.clientmessageservice.ClientMessageServiceClient;
public class
SecureMessageServiceClientHelper
implements ClientMessageService
{
public static ClientMessageService
getServerService(
String server_address,
int server_port,
int timeout_secs,
String msg_type_id,
RSAPublicKey public_key )
throws IOException
{
return new SecureMessageServiceClientHelper( server_address, server_port, timeout_secs, msg_type_id, public_key );
}
private ClientMessageService delegate;
private SecretKey session_key;
private byte[] encryped_session_key;
protected
SecureMessageServiceClientHelper(
String server_address,
int server_port,
int timeout_secs,
String msg_type_id,
RSAPublicKey public_key )
throws IOException
{
try{
KeyGenerator secret_key_gen = KeyGenerator.getInstance("DESede");
session_key = secret_key_gen.generateKey();
byte[] secret_bytes = session_key.getEncoded();
try{
Cipher rsa_cipher = Cipher.getInstance( "RSA" );
rsa_cipher.init( Cipher.ENCRYPT_MODE, public_key );
encryped_session_key = rsa_cipher.doFinal( secret_bytes );
}catch( Throwable e ){
// fallback to the BC implementation for jdk1.4.2 as JCE RSA not available
RSAEngine eng = new RSAEngine();
PKCS1Encoding padded_eng = new PKCS1Encoding( eng );
CipherParameters param = RSAUtil.generatePublicKeyParameter(public_key);
param = new ParametersWithRandom(param, RandomUtils.SECURE_RANDOM);
padded_eng.init( true, param );
encryped_session_key = padded_eng.processBlock(secret_bytes, 0, secret_bytes.length);
}
}catch( Throwable e ){
e.printStackTrace();
throw( new IOException( "Secure client message service initialisation fails - " + Debug.getNestedExceptionMessage(e)));
}
delegate = ClientMessageServiceClient.getServerService( server_address, server_port, msg_type_id );
}
public void
sendMessage(
Map plain_payload )
throws IOException
{
Map secure_payload = new HashMap();
try{
byte[] message_bytes = StaticUtilities.getFormatters().bEncode( plain_payload );
Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, session_key );
byte[] encrypted_message = cipher.doFinal( message_bytes );
secure_payload.put( "ver", "1" );
secure_payload.put( "alg", "DESede" );
secure_payload.put( "key", encryped_session_key );
secure_payload.put( "content", encrypted_message );
}catch( Throwable e ){
throw( new IOException( "send message failed - " + Debug.getNestedExceptionMessage(e)));
}
delegate.sendMessage( secure_payload );
}
public Map
receiveMessage()
throws IOException
{
Map secure_payload = delegate.receiveMessage();
byte[] encrypted_message = (byte[])secure_payload.get( "content" );
try{
Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, session_key );
byte[] message_bytes = cipher.doFinal( encrypted_message );
Map plain_payload = StaticUtilities.getFormatters().bDecode( message_bytes );
return( plain_payload );
}catch( Throwable e ){
throw( new IOException( "send message failed - " + Debug.getNestedExceptionMessage(e)));
}
}
public void
close()
{
delegate.close();
}
public void
setMaximumMessageSize( int max_bytes )
{
delegate.setMaximumMessageSize( max_bytes );
}
}