• Main Page
  • Related Pages
  • Packages
  • Classes
  • Files
  • File List

crypto/CipherEngine.java

Go to the documentation of this file.
00001 
00002 /**
00003  *  Application-wide cryptographic functions 
00004  */
00005 package crypto;
00006 
00007 import java.io.File;
00008 import java.io.IOException;
00009 import java.security.SignedObject;
00010 
00011 import utils.Log;
00012 
00013 /**
00014  *  Common ciphering engine (for the whole application) providing:
00015  *  
00016  *   - Asymmetric ciphering: used for signing/verification and 
00017  *     encryption/decryption of secret key used in symmetric ciphering.
00018  *     
00019  *   - Symmetric ciphering: used for encryption/decryption of PDUs and 
00020  *     secret chat text messages.
00021  */
00022 public class CipherEngine 
00023 {
00024     /**
00025      *  Asymmetric cipher used to encrypt secret keys
00026      */
00027     private static AsymmetricCipher privateCipher = null;
00028 
00029     /** 
00030      *  The default cipher algorithm for data (PDUs and secret chat messages)
00031      */
00032     private final static String myCipherAlgorithm = "Blowfish";
00033     
00034     /** 
00035      *  The default key size for cipher algorithm 
00036      */
00037     private final static int myCipherKeySize = 32; // Start velue for reduced CPU usage
00038 
00039     /**
00040      *  Subdirectory of the user.home where private key is stored
00041      */
00042     private static final String defaultPrivateKeyDirectory = ".mykf";
00043 
00044     /**
00045      *  Full path of the directory holding our private key
00046      */
00047     private static String myPrivateKeyPath = "";
00048 
00049     /**
00050      *  Symmetric cipher used to encrypt data (PDUs and secret chat messages)
00051      */
00052     private static SymmetricCipher myPduCipher = null;
00053     
00054     /**
00055      *  Returns path to the directory holding our private key
00056      */
00057     public static String getPrivateKeyDirectory ()
00058     {
00059         return myPrivateKeyPath;
00060     }
00061 
00062     /**
00063      *  Returns serialized signed public key (used for encryption of datagrams) as 
00064      *  Base64 string.
00065      */
00066     public static String getSignedPublicKey ()
00067     {
00068         if ( privateCipher == null ) {
00069             return null;
00070         }
00071         
00072         return privateCipher.getSerializedAndSignedPublicKey ();
00073     }
00074 
00075     /**
00076      *  Returns serialized named public key encoded as Base64 string.
00077      */
00078     public static String getNamedPublicKey ()
00079     {
00080         if ( privateCipher == null ) {
00081             return null;
00082         }
00083         
00084         return privateCipher.getNamedPublicKey ();
00085     }
00086 
00087     /**
00088      *  Returns local symmetric ciphering engine
00089      */
00090     public static SymmetricCipher getCipher ()
00091     {
00092         return myPduCipher;
00093     }
00094 
00095     /**
00096      *  Returns secret key signed with our private key
00097      */
00098     public static SignedObject getSignedSecretKey ()
00099     {
00100         if ( privateCipher == null ) {
00101             return null;
00102         }
00103         
00104         return privateCipher.signObject( myPduCipher.getSecretKey () );
00105     }
00106     
00107     /**
00108      *  Reconstructs secret key from Base64 respresentation of encrypted 
00109      *  (using our public key) serialized secret key and verifies signature
00110      *  of the remote peer.
00111      */
00112     public static SymmetricCipher deserializeEncryptedSecretKey( String encryptedSecret )
00113     {
00114         if ( privateCipher == null ) {
00115             return null;
00116         }
00117         
00118         return privateCipher.deserializeEncryptedSecretKey( encryptedSecret );
00119     }
00120     
00121     /**
00122      *  Loads authorized public keys and initializes asymmetric and symmetric 
00123      *  ciphering engines, where:
00124      *  
00125      *   - Asymmetric ciphering is used for verification and encryption/decryption of
00126      *     secret key used in symmetric ciphering.
00127      *   - Symmetric ciphering is used for encryption/decryption of PDUs and 
00128      *     secret chat text messages.
00129      *  
00130      *  Initialization is non-blocking and performed in separate worker thread.
00131      */
00132     public static void initialize ()
00133     {
00134         /* Create directory that will hold private key. Also change permissions using 
00135          * native OS 'chmod' command (ignoring Windows), so that no one but the 
00136          * owner might read its contents.
00137          */
00138         try
00139         {
00140             myPrivateKeyPath = "";
00141             
00142             String dirPath = System.getProperty( "user.home" )
00143                            + System.getProperty( "file.separator" )
00144                            + defaultPrivateKeyDirectory;
00145 
00146             File directory = new File( dirPath );
00147 
00148             if (  ! directory.exists () ) {
00149                 directory.mkdir ();
00150             }
00151 
00152             if (  directory.exists () )
00153             {
00154                 myPrivateKeyPath = dirPath + System.getProperty( "file.separator" );
00155                 
00156                 String osName = System.getProperty( "os.name" ).toLowerCase();
00157                 if ( ! osName.matches( "^.*windows.*$" ) ) 
00158                 {
00159                     try 
00160                     {
00161                         Runtime.getRuntime().exec( new String[] { "chmod", "go=", dirPath } );
00162                     }
00163                     catch( IOException e ) 
00164                     {
00165                         Log.trace( "Failed to do chmod; OS = " + osName );
00166                         Log.exception( Log.TRACE, e );
00167                     }
00168                 }
00169             }
00170         }
00171         catch( Exception e )
00172         {
00173             Log.exception( Log.ERROR, e );
00174         }
00175             
00176         Log.trace( "Private Key directory: " + myPrivateKeyPath );
00177 
00178         /* Initialize (load or generate) private/public keys and
00179          * generate secret key in worker thread, then load authorized public keys. 
00180          */
00181         Runnable nonBlockingInitThread = new Runnable () 
00182         {
00183             @Override
00184             public void run() 
00185             {
00186                 /* Instantiate our ciphers first...
00187                  */
00188                 if ( myPduCipher == null ) {
00189                     myPduCipher = new SymmetricCipher( 
00190                             myCipherAlgorithm, myCipherKeySize, /*report*/ false );
00191                 }
00192 
00193                 if ( privateCipher == null ) {
00194                     privateCipher = new AsymmetricCipher ();
00195                 }
00196                 
00197                 /* ...then load authorized public keys
00198                  */
00199                 PublicEncryptor.loadAuthorizedPublicKeys ();
00200             }
00201         };
00202 
00203         ( new Thread( nonBlockingInitThread, "CipherEngine" ) ).start ();
00204     }
00205     
00206     /**
00207      *  Reloads only authorized public keys
00208      */
00209     public static void reloadAuthorizedPublicKeys ()
00210     {
00211         PublicEncryptor.loadAuthorizedPublicKeys ();
00212     }
00213     
00214     /**
00215      *  Generates new symmetric secret key.
00216      *  
00217      *  @return true if generated cipher may be used (i.e. false in case of error)
00218      */
00219     public static boolean generateNewSecret( String algorithm, int keySize, boolean verbose )
00220     {
00221         if ( algorithm == null || algorithm.isEmpty () ) {
00222             algorithm = myCipherAlgorithm;
00223         }
00224 
00225         if ( keySize <= 0 ) {
00226             keySize = myCipherKeySize;
00227         }
00228 
00229         myPduCipher = new SymmetricCipher( algorithm, keySize, verbose );
00230         
00231         return myPduCipher.isActive ();
00232     }
00233 }

Generated on Thu Dec 16 2010 14:44:42 for VoIP Kryptofon by  doxygen 1.7.2