[jboss-cvs] JBossRemoting/src/main/org/jboss/remoting/marshal/encryption ...

Anil Saldhana anil.saldhana at jboss.com
Wed Aug 16 15:18:30 EDT 2006


  User: asaldhana
  Date: 06/08/16 15:18:30

  Added:       src/main/org/jboss/remoting/marshal/encryption     
                        EncryptingMarshaller.java
                        EncryptingUnMarshaller.java EncryptionManager.java
                        EncryptionOutputStream.java KeyGeneratorUtil.java
  Log:
  JBAS-419: code,tests and keys for encrypting the streams
  
  Revision  Changes    Path
  1.1      date: 2006/08/16 19:18:30;  author: asaldhana;  state: Exp;JBossRemoting/src/main/org/jboss/remoting/marshal/encryption/EncryptingMarshaller.java
  
  Index: EncryptingMarshaller.java
  ===================================================================
  /*
  * JBoss, Home of Professional Open Source
  * Copyright 2005, JBoss Inc., and individual contributors as indicated
  * by the @authors tag. See the copyright.txt in the distribution for a
  * full listing of individual contributors.
  *
  * This is free software; you can redistribute it and/or modify it
  * under the terms of the GNU Lesser General Public License as
  * published by the Free Software Foundation; either version 2.1 of
  * the License, or (at your option) any later version.
  *
  * This software 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
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this software; if not, write to the Free
  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
  */
  
  package org.jboss.remoting.marshal.encryption;
  
  import java.io.IOException;
  import java.io.ObjectOutputStream;
  import java.io.OutputStream;
  import java.security.Key;
   
  import javax.crypto.Cipher;
  import javax.crypto.CipherOutputStream; 
  
  import org.jboss.remoting.marshal.Marshaller;
  import org.jboss.remoting.marshal.serializable.SerializableMarshaller;
  import org.jboss.remoting.serialization.SerializationManager;
  import org.jboss.remoting.serialization.SerializationStreamFactory;
  
  
  /**
   * <code>EncryptingMarshaller</code> and <code>EncryptingMarshaller</code> are a general
   * purpose encryption based marshaller / decompressing unmarshaller pair 
   * based on Java's Cipher facilities.
   * <p/>
   * <code>EncryptingMarshaller</code> is subclassed from <code>SerializableMarshaller</code>, 
   * and by default it uses <code>super.write()</code> to marshall an object, which is then
   * encrypted.  Optionally, it can wrap any other marshaller and use that instead of
   * <code>SerializableMarshaller</code> to marshall an object before it is encrypted.
   * For example,
   * <p/>
   * <center><code>new EncryptingMarshaller(new HTTPMarshaller())</code></center>
   * <p/>
   * will create a marshaller that encrypts the output of an <code>HTTPMarshaller</code>.
   *
   * @author <a href="mailto:anil.saldhana at jboss.com">Anil Saldhana</a> 
   */
  
  public class EncryptingMarshaller extends SerializableMarshaller
  {
     /** The serialVersionUID */
     private static final long serialVersionUID = 1L;
  
     public final static String DATATYPE = "encrypt";
  
     private Marshaller wrappedMarshaller; 
     
     private String cipherAlgorithm = EncryptionManager.DEFAULT_CIPHER_ALGORITHM;
     
     private Cipher cipher = EncryptionManager.getCipher(Cipher.ENCRYPT_MODE, cipherAlgorithm);
  
     /**
      * Create a new EncryptingMarshaller.
      */
     public EncryptingMarshaller()
     { 
     }
     
     /**
      * 
      * Create a new EncryptingMarshaller.
      * 
      * @param algo Cipher Algorithm
      * @param key Key
      * @see #setCipherAlgorithm(String)
      */
     public EncryptingMarshaller(String algo, Key key)
     { 
        cipher = EncryptionManager.getCipher(Cipher.ENCRYPT_MODE, algo, key);
     }
  
  
     /**
      * Create a new EncryptingMarshaller.
      *
      * @param marshaller A <code>Marshaller</code> which is used to turn objects into byte streams.
      */
     public EncryptingMarshaller(Marshaller marshaller)
     {
        wrappedMarshaller = marshaller;
     }
     
     /**
      * Set the Cipher Algorithm to use
      * @param algo
      * @see EncryptionManager#DEFAULT_CIPHER_ALGORITHM
      */
     public void setCipherAlgorithm(String algo)
     {
        this.cipherAlgorithm = algo;
        cipher = EncryptionManager.getCipher(Cipher.ENCRYPT_MODE, this.cipherAlgorithm);
     }
  
  
     /**
      * Writes encrypted, marshalled form of <code>dataObject</code> to <code>output</code>.
      *
      * @param dataObject arbitrary object to be marshalled
      * @param output     <code>OutputStream</code> to which <code>output</code> is to be marshalled
      */
     public void write(Object dataObject, OutputStream output) throws IOException
     { 
        if(cipher == null)
           throw new IllegalStateException("Cipher is null for algo="+ this.cipherAlgorithm);
        output.flush(); 
        
        //EOS intercepts the close() call and does not close the stream
        EncryptionOutputStream eos = new EncryptionOutputStream(output);
         
        CipherOutputStream cos = new CipherOutputStream(eos, cipher);
         
        SerializationManager sm = SerializationStreamFactory.getManagerInstance(getSerializationType());
        ObjectOutputStream oos = sm.createOutput(cos);
        
        if(wrappedMarshaller != null)
        { 
           wrappedMarshaller.write(dataObject, oos);
        }
        else
        {
           super.write(dataObject, oos);
        }  
        oos.flush();  
        
        //Vagaries of CipherOutputStream which needs a close() to flush at the end
        cos.close(); //Tests fail without this statement - oos.close() should do it
        oos.close(); //There is a need to close cos
     }
  
     /**
      * Returns a <code>EncryptingMarshaller</code>.
      *
      * @return a <code>EncryptingMarshaller</code>.
      * @throws CloneNotSupportedException In practice no exceptions are thrown
      */
     public Marshaller cloneMarshaller() throws CloneNotSupportedException
     {
        EncryptingMarshaller em = new EncryptingMarshaller(wrappedMarshaller);
        em.setCipherAlgorithm(this.cipherAlgorithm);
        return em;
     } 
  }
  
  
  
  
  1.1      date: 2006/08/16 19:18:30;  author: asaldhana;  state: Exp;JBossRemoting/src/main/org/jboss/remoting/marshal/encryption/EncryptingUnMarshaller.java
  
  Index: EncryptingUnMarshaller.java
  ===================================================================
  /*
  * JBoss, Home of Professional Open Source
  * Copyright 2005, JBoss Inc., and individual contributors as indicated
  * by the @authors tag. See the copyright.txt in the distribution for a
  * full listing of individual contributors.
  *
  * This is free software; you can redistribute it and/or modify it
  * under the terms of the GNU Lesser General Public License as
  * published by the Free Software Foundation; either version 2.1 of
  * the License, or (at your option) any later version.
  *
  * This software 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
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this software; if not, write to the Free
  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
  */
  
  package org.jboss.remoting.marshal.encryption;
  
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.ObjectInputStream; 
  import java.util.Map;
  
  import javax.crypto.Cipher;
  import javax.crypto.CipherInputStream;
  
  import org.jboss.remoting.marshal.UnMarshaller;
  import org.jboss.remoting.marshal.serializable.SerializableUnMarshaller;
  import org.jboss.remoting.serialization.SerializationManager;
  import org.jboss.remoting.serialization.SerializationStreamFactory;
  
  
  /**
   * <code>EncryptingMarshaller</code> and <code>EncryptingUnMarshaller</code> are a general
   * purpose encrypting marshaller / decompressing unmarshaller pair based on 
   * Java's crypto stream facilities.
   * <p/>
   * <code>EncryptingUnMarshaller</code> is subclassed from <code>SerializableUnMarshaller</code>,
   * and by default it uses <code>super.read()</code> to deserialize an object, once the object has been
   * decrypted.  Optionally, it can wrap any other unmarshaller and use that instead of
   * <code>SerializableUnMarshaller</code> to unmarshall an encrypted input stream.  For example,
   * <p/>
   * <center><code>new EncryptingUnMarshaller(new HTTPUnMarshaller())</code></center
   * <p/>
   * will create an umarshaller that
   * uses an <code>HTTPUnMarshaller</code> to restore an unencrypted input stream.
   *
   * @author Anil.Saldhana at jboss.org
   * @version $Revision: 1.1 $ 
   */
  
  public class EncryptingUnMarshaller extends SerializableUnMarshaller
  {
     /** The serialVersionUID */
     private static final long serialVersionUID = 1L;
  
     public final static String DATATYPE = "encrypt";
  
     private UnMarshaller wrappedUnMarshaller; 
     
     private String cipherAlgorithm = EncryptionManager.DEFAULT_CIPHER_ALGORITHM;
     
     private Cipher cipher = EncryptionManager.getCipher(Cipher.DECRYPT_MODE, cipherAlgorithm);
     
  
     /**
      * Create a new EncryptingUnMarshaller.
      */
     public EncryptingUnMarshaller()
     {
     }
   
  
     /**
      * Create a new EncryptingUnMarshaller.
      *
      * @param unMarshaller unmarshaller to be used to restore 
      * unencrypted byte stream to original object
      */
     public EncryptingUnMarshaller(UnMarshaller unMarshaller)
     {
        wrappedUnMarshaller = unMarshaller;
     }
  
     /**
      * Set the Cipher Algorithm to use
      * @param algo
      * @see EncryptionManager#DEFAULT_CIPHER_ALGORITHM
      */
     public void setCipherAlgorithm(String algo)
     {
        this.cipherAlgorithm = algo;
        cipher = EncryptionManager.getCipher(Cipher.DECRYPT_MODE, this.cipherAlgorithm);
     }
  
     /**
      * Restores a encrypted, marshalled form of an object to its original state.
      *
      * @param inputStream <code>InputStream</code> from which marshalled form is to be retrieved
      * @param metadata    can be any transport specific metadata (such as headers from http transport).
      *                    This can be null, depending on if transport supports metadata.
      * @return restored object
      * @throws IOException            if there is a problem reading from <code>inputStream</code>
      * @throws ClassNotFoundException if there is a problem finding a class needed for unmarshalling
      */
     public Object read(InputStream inputStream, Map metadata) throws IOException, ClassNotFoundException
     {  
        if(cipher == null)
           throw new IllegalStateException("Cipher is null for algo="+ this.cipherAlgorithm);
        CipherInputStream cis = new CipherInputStream(inputStream,cipher);
        SerializationManager sm = SerializationStreamFactory.getManagerInstance(getSerializationType());
        ObjectInputStream ois = sm.createRegularInput(cis);
         
        Object obj = null;
        if(wrappedUnMarshaller != null)
        {
           obj = wrappedUnMarshaller.read(ois, metadata); 
        }
        else
        {
           obj = super.read(ois, metadata);
        } 
        return obj;
     } 
  
     /**
      * Returns a new <code>EncryptingUnMarshaller</code>
      *
      * @return a new <code>EncryptingUnMarshaller</code>
      * @throws CloneNotSupportedException In practice no exceptions are thrown.
      */
     public UnMarshaller cloneUnMarshaller() throws CloneNotSupportedException
     {
        EncryptingUnMarshaller um = new EncryptingUnMarshaller(wrappedUnMarshaller);
        um.setCipherAlgorithm(this.cipherAlgorithm);
        return um;
     } 
  }
  
  
  
  
  1.1      date: 2006/08/16 19:18:30;  author: asaldhana;  state: Exp;JBossRemoting/src/main/org/jboss/remoting/marshal/encryption/EncryptionManager.java
  
  Index: EncryptionManager.java
  ===================================================================
  /*
    * JBoss, Home of Professional Open Source
    * Copyright 2005, JBoss Inc., and individual contributors as indicated
    * by the @authors tag. See the copyright.txt in the distribution for a
    * full listing of individual contributors.
    *
    * This is free software; you can redistribute it and/or modify it
    * under the terms of the GNU Lesser General Public License as
    * published by the Free Software Foundation; either version 2.1 of
    * the License, or (at your option) any later version.
    *
    * This software 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
    * Lesser General Public License for more details.
    *
    * You should have received a copy of the GNU Lesser General Public
    * License along with this software; if not, write to the Free
    * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
    * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
    */
  package org.jboss.remoting.marshal.encryption;
   
  import java.io.InputStream;
  import java.io.ObjectInput;
  import java.io.ObjectInputStream;
  import java.security.Key;
  import java.util.Map;
  
  import javax.crypto.Cipher;
  
  import org.jboss.logging.Logger;
  
  import EDU.oswego.cs.dl.util.concurrent.ConcurrentHashMap;
  
  //$Id: EncryptionManager.java,v 1.1 2006/08/16 19:18:30 asaldhana Exp $
  
  /**
   *  Manager that deals with the generation of the Cipher
   *  @author <a href="mailto:Anil.Saldhana at jboss.org">Anil Saldhana</a>
   *  @since  Aug 11, 2006 
   *  @version $Revision: 1.1 $
   */
  public class EncryptionManager
  {
     private static Logger log = Logger.getLogger(EncryptionManager.class);
     private static Map keys =  new ConcurrentHashMap(); 
     public static final String DEFAULT_CIPHER_ALGORITHM = "DES";
     
     static
     {
        //Generate Keys for the common algorithms
        try
        {
           keys.put("AES", loadKey("AES"));
           keys.put("DES", loadKey("DES"));
           keys.put("DESede", loadKey("DESede"));
           keys.put("Blowfish", loadKey("Blowfish"));
           keys.put("RC4", loadKey("RC4"));
        }
        catch (Exception e)
        {
           if(log.isTraceEnabled())
              log.trace("Exception in loading key",e);
        }  
     }
     
     /**
      * Generate a Cipher
      * @param mode Cipher.ENCRYPT_MODE or Cipher.DECRYPT_MODE (Wrap/Unwrap not supported)
      * @param algo Cipher Algorithm
      * @return cipher
      */
     public static Cipher getCipher(int mode, String algo)
     {
        if(algo == null)
           algo = DEFAULT_CIPHER_ALGORITHM;
        Cipher cipher = null;
        boolean correctMode = (mode == Cipher.ENCRYPT_MODE
                  || mode == Cipher.DECRYPT_MODE);
        if(!correctMode)
           throw new IllegalArgumentException("Cipher Mode is wrong");
         
         try
        {
           cipher = Cipher.getInstance(algo);
           Key key = (Key)keys.get(canonicalize(algo));
           if(key == null)
              throw new IllegalStateException("Key is null for algo="+algo);
           cipher.init(mode, key);
        }
        catch (Throwable e)
        {
           if(log.isTraceEnabled())
              log.trace("getCipher failed:", e);
        } 
         return cipher;
     }
     
     /**
      * Obtain an initialized cipher given the Cipher mode,
      * algorithm and key
      * @param mode Cipher.ENCRYPT_MODE or Cipher.DECRYPT_MODE
      * @param algo
      * @param key
      * @return initialized cipher
      */
     public static Cipher getCipher(int mode, String algo, Key key)
     {
        Cipher cipher = null;
        boolean correctMode = (mode == Cipher.ENCRYPT_MODE
                  || mode == Cipher.DECRYPT_MODE);
        if(!correctMode)
           throw new IllegalArgumentException("Cipher Mode is wrong");
         
         try
        {
           cipher = Cipher.getInstance(algo);
           cipher.init(mode, key);
        }
        catch (Throwable e)
        {
           if(log.isTraceEnabled())
              log.trace("getCipher failed:", e);
        } 
         return cipher;
     }
     
     /**
      * Load the serialized key
      * @param algo
      * @return
      * @throws Exception
      */
     private static Key loadKey(String algo) throws Exception
     {  
        ClassLoader tcl = Thread.currentThread().getContextClassLoader();
        String file = "org/jboss/remoting/marshall/encryption/"+algo+".key";
        InputStream is = tcl.getResourceAsStream(file);
        if(is == null)
           throw new IllegalStateException("Key file is not locatable");
        ObjectInput out = new ObjectInputStream(is);
        Key key = (Key)out.readObject();
        out.close();
        return key;
     }
     
     //Remove padding etc from the key algo
     private static String canonicalize(String algo)
     { 
        if(algo == null)
           throw new IllegalArgumentException("Null algorithm passed");
        String result = algo; 
        if(algo.indexOf("/")> 0)
        {
           result = algo.substring(0,algo.indexOf("/"));
        } 
        return result; 
     }
  }
  
  
  
  1.1      date: 2006/08/16 19:18:30;  author: asaldhana;  state: Exp;JBossRemoting/src/main/org/jboss/remoting/marshal/encryption/EncryptionOutputStream.java
  
  Index: EncryptionOutputStream.java
  ===================================================================
  /*
    * JBoss, Home of Professional Open Source
    * Copyright 2005, JBoss Inc., and individual contributors as indicated
    * by the @authors tag. See the copyright.txt in the distribution for a
    * full listing of individual contributors.
    *
    * This is free software; you can redistribute it and/or modify it
    * under the terms of the GNU Lesser General Public License as
    * published by the Free Software Foundation; either version 2.1 of
    * the License, or (at your option) any later version.
    *
    * This software 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
    * Lesser General Public License for more details.
    *
    * You should have received a copy of the GNU Lesser General Public
    * License along with this software; if not, write to the Free
    * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
    * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
    */
  package org.jboss.remoting.marshal.encryption;
  
  import java.io.IOException;
  import java.io.OutputStream; 
  
  //$Id: EncryptionOutputStream.java,v 1.1 2006/08/16 19:18:30 asaldhana Exp $
  
  /**
   *  OutputStream that is piped into a CipherOutputStream such that
   *  CipherOutputStream.close will not close the underlying stream
   *  @author <a href="mailto:Anil.Saldhana at jboss.org">Anil Saldhana</a>
   *  @since  Aug 16, 2006 
   *  @version $Revision: 1.1 $
   */
  public class EncryptionOutputStream extends OutputStream
  { 
     private OutputStream delegate; 
  
     public EncryptionOutputStream(OutputStream os)
     {
        this.delegate = os; 
     }
     
     /**
      * @see OutputStream#write(int)
      */
     public void write(int a) throws IOException
     { 
        delegate.write(a);
     }
   
     /**
      * @see OutputStream#close()
      */
     public void close() throws IOException
     {
       
       //Flush only. Do not close the stream
       delegate.flush(); 
     }
   
     /**
      * @see OutputStream#flush()
      */
     public void flush() throws IOException
     {
       delegate.flush();
     }
   
     /**
      * @see OutputStream#write(byte[], int, int)
      */
     public void write(byte[] b, int off, int len) throws IOException
     {
        delegate.write(b, off, len);
     }
   
     /**
      * @see OutputStream#write(byte[])
      */
     public void write(byte[] b) throws IOException
     {
        delegate.write(b);
     } 
     
     /**
      * @see Object#equals(Object)
      */
     public boolean equals(Object obj)
     { 
        return delegate.equals(obj);
     }
   
     /**
      * @see Object#hashCode()
      */
     public int hashCode()
     { 
        return delegate.hashCode();
     }  
  }
  
  
  
  1.1      date: 2006/08/16 19:18:30;  author: asaldhana;  state: Exp;JBossRemoting/src/main/org/jboss/remoting/marshal/encryption/KeyGeneratorUtil.java
  
  Index: KeyGeneratorUtil.java
  ===================================================================
  /*
    * JBoss, Home of Professional Open Source
    * Copyright 2005, JBoss Inc., and individual contributors as indicated
    * by the @authors tag. See the copyright.txt in the distribution for a
    * full listing of individual contributors.
    *
    * This is free software; you can redistribute it and/or modify it
    * under the terms of the GNU Lesser General Public License as
    * published by the Free Software Foundation; either version 2.1 of
    * the License, or (at your option) any later version.
    *
    * This software 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
    * Lesser General Public License for more details.
    *
    * You should have received a copy of the GNU Lesser General Public
    * License along with this software; if not, write to the Free
    * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
    * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
    */
  package org.jboss.remoting.marshal.encryption;
  
  import java.io.FileOutputStream;
  import java.io.ObjectOutput;
  import java.io.ObjectOutputStream;
  import java.security.Key;
  
  import javax.crypto.KeyGenerator; 
  
  //$Id: KeyGeneratorUtil.java,v 1.1 2006/08/16 19:18:30 asaldhana Exp $
  
  /**
   *  Generates keys
   *  @author <a href="mailto:Anil.Saldhana at jboss.org">Anil Saldhana</a>
   *  @since  Aug 14, 2006 
   *  @version $Revision: 1.1 $
   */
  public class KeyGeneratorUtil  
  {  
     public void genKeys() throws Exception
     { 
        getKey("DES");
        getKey("DESede"); 
        getKey("AES");
        getKey("RC4"); 
        getKey("Blowfish"); 
     } 
     
     private Key getKey(String algo)
     {
       Key key = null;
       try
       {
          KeyGenerator gen = KeyGenerator.getInstance(algo);
          key = gen.generateKey(); 
          serializeToFile(key,algo);
       }
       catch (Exception e)
       {
          e.printStackTrace();
       } 
       return key;
     }
     
     private void serializeToFile(Key key, String algo) throws Exception
     {
        ObjectOutput out = new ObjectOutputStream(new FileOutputStream(algo+".key"));
        out.writeObject(key);
        out.close();
     } 
     
     public static void main(String[] args)
     {
        KeyGeneratorUtil u = new KeyGeneratorUtil();
        try
        {
           u.genKeys();
        }
        catch (Exception e)
        { 
           e.printStackTrace();
        }
     }
  }
  
  
  



More information about the jboss-cvs-commits mailing list