Go to the documentation of this file.00001
00002 package crypto;
00003
00004 import java.io.IOException;
00005 import java.io.UnsupportedEncodingException;
00006 import java.security.InvalidParameterException;
00007 import java.security.NoSuchAlgorithmException;
00008
00009 import javax.crypto.Cipher;
00010 import javax.crypto.KeyGenerator;
00011 import javax.crypto.NoSuchPaddingException;
00012 import javax.crypto.SecretKey;
00013 import javax.crypto.spec.IvParameterSpec;
00014
00015 import utils.Base64;
00016 import utils.Log;
00017
00018
00019
00020
00021
00022
00023
00024 public class SymmetricCipher
00025 {
00026
00027
00028
00029
00030 private final static String mode = "/CBC";
00031
00032
00033
00034
00035
00036 private final static String padding = "/PKCS5Padding";
00037
00038
00039
00040
00041 private Cipher cipher = null;
00042
00043
00044
00045
00046 private SecretKey secretKey = null;
00047
00048
00049
00050
00051
00052
00053 private String verificator = null;
00054
00055
00056
00057
00058 public SymmetricCipher( SecretKey secretKey, String verificator )
00059 {
00060 this.secretKey = secretKey;
00061 this.verificator = verificator;
00062
00063 try
00064 {
00065 this.cipher = Cipher.getInstance( secretKey.getAlgorithm () + mode + padding );
00066
00067 Log.trace( "New remote symmetric cipher: " + this.cipher.getAlgorithm () );
00068 }
00069 catch( NoSuchAlgorithmException e )
00070 {
00071 Log.exception( Log.ERROR, e );
00072 }
00073 catch( NoSuchPaddingException e )
00074 {
00075 Log.exception( Log.ERROR, e );
00076 }
00077
00078 if ( this.cipher == null ) {
00079 this.secretKey = null;
00080 }
00081 }
00082
00083
00084
00085
00086 public SymmetricCipher( String algorithm, int keySize, boolean attnReport )
00087 {
00088 this.secretKey = null;
00089
00090 try
00091 {
00092 KeyGenerator keyGen = KeyGenerator.getInstance( algorithm );
00093 keyGen.init( keySize );
00094 this.secretKey = keyGen.generateKey ();
00095
00096 this.cipher = Cipher.getInstance( secretKey.getAlgorithm () + mode + padding );
00097
00098 Log.trace( "New local symmetric cipher: " + this.cipher.getAlgorithm () );
00099
00100 if ( attnReport ) {
00101 Log.attn( "New symmetric cipher: " + algorithm + "/" + keySize );
00102 }
00103 }
00104 catch( InvalidParameterException e )
00105 {
00106 Log.exception( Log.ERROR, e );
00107 if ( attnReport ) {
00108 Log.attn( "Error: Invalid parameter: " + e.getMessage () );
00109 }
00110 }
00111 catch( NoSuchAlgorithmException e )
00112 {
00113 Log.exception( Log.ERROR, e );
00114 if ( attnReport ) {
00115 Log.attn( "Error: No such algorithm: " + e.getMessage () );
00116 }
00117 }
00118 catch( NoSuchPaddingException e )
00119 {
00120 Log.exception( Log.ERROR, e );
00121 if ( attnReport ) {
00122 Log.attn( "Error: No such padding: " + e.getMessage () );
00123 }
00124 }
00125
00126 if ( this.cipher == null ) {
00127 this.secretKey = null;
00128 }
00129 }
00130
00131
00132
00133
00134 public SecretKey getSecretKey ()
00135 {
00136 return secretKey;
00137 }
00138
00139
00140
00141
00142 public boolean isActive ()
00143 {
00144 return this.cipher != null;
00145 }
00146
00147
00148
00149
00150 public boolean isVerified ()
00151 {
00152 return this.verificator != null;
00153 }
00154
00155
00156
00157
00158
00159
00160 public String getVerificatorName ()
00161 {
00162 return this.verificator;
00163 }
00164
00165
00166
00167
00168 public String getAlgorithmDesc ()
00169 {
00170 if ( secretKey == null ) {
00171 return "[Inactive]";
00172 }
00173
00174 return this.secretKey.getAlgorithm ();
00175 }
00176
00177
00178
00179
00180
00181 public byte[] encrypt( int randomPreambleLen, byte[] plainText )
00182 {
00183 if ( this.cipher == null ) {
00184 return null;
00185 }
00186
00187
00188 byte[] preamble = new byte[ randomPreambleLen ];
00189 for ( int i = 0; i < randomPreambleLen; ++i ) {
00190 preamble[i] = (byte)( Math.random () * 0x100 - 0x100 );
00191 }
00192
00193
00194 byte[] ivBytes = new byte[8];
00195 IvParameterSpec ivSpec = new IvParameterSpec( ivBytes );
00196
00197 byte[] cipherText = null;
00198
00199 synchronized( this.cipher )
00200 {
00201 try
00202 {
00203 this.cipher.init( Cipher.ENCRYPT_MODE, this.secretKey, ivSpec );
00204
00205 int ptLength = ivBytes.length + preamble.length + plainText.length;
00206 cipherText = new byte[ cipher.getOutputSize( ptLength ) ];
00207
00208 int ctLength = cipher.update( ivBytes, 0, ivBytes.length, cipherText, 0 );
00209
00210 ctLength += cipher.update( preamble, 0, preamble.length, cipherText, ctLength );
00211
00212 ctLength += cipher.update( plainText, 0, plainText.length, cipherText, ctLength );
00213
00214 ctLength += cipher.doFinal( cipherText, ctLength );
00215 }
00216 catch( Exception e )
00217 {
00218 Log.exception( Log.PDU, e );
00219 }
00220 }
00221
00222 return cipherText;
00223 }
00224
00225
00226
00227
00228 public byte[] decrypt( int randomPreambleLen, byte[] cipherText )
00229 {
00230 if ( this.cipher == null ) {
00231 return null;
00232 }
00233
00234 byte[] plainText = null;
00235
00236 synchronized( this.cipher )
00237 {
00238 try
00239 {
00240 byte[] ivBytes = new byte[8];
00241 IvParameterSpec ivSpec = new IvParameterSpec( ivBytes );
00242
00243 this.cipher.init( Cipher.DECRYPT_MODE, this.secretKey, ivSpec );
00244
00245 byte[] buf = new byte[ cipher.getOutputSize( cipherText.length ) ];
00246
00247 int bufLen = cipher.update( cipherText, 0, cipherText.length, buf, 0 );
00248
00249 bufLen += cipher.doFinal( buf, bufLen );
00250
00251
00252
00253 plainText = new byte[ bufLen - ivBytes.length - randomPreambleLen ];
00254
00255 System.arraycopy( buf, ivBytes.length + randomPreambleLen, plainText, 0, plainText.length );
00256 }
00257 catch( Exception e )
00258 {
00259 Log.exception( Log.PDU, e );
00260 }
00261 }
00262
00263 return plainText;
00264 }
00265
00266
00267
00268
00269
00270 public String encrypt( String plainText )
00271 {
00272 String encodedCipherText = null;
00273
00274
00275
00276 try
00277 {
00278 byte[] plainBin = ( "[BEGIN]" + plainText ).getBytes( "UTF8" );
00279
00280 byte[] cipherText = this.encrypt( 256, plainBin );
00281
00282 if ( cipherText != null )
00283 {
00284 encodedCipherText = Base64.encodeBytes( cipherText );
00285 }
00286 }
00287 catch( UnsupportedEncodingException e )
00288 {
00289 Log.exception( Log.TRACE, e );
00290 }
00291
00292 return encodedCipherText;
00293 }
00294
00295
00296
00297
00298
00299 public String decrypt( String encodedCipherText )
00300 {
00301 String clearText = null;
00302
00303 try
00304 {
00305 byte[] cipherText = Base64.decode( encodedCipherText );
00306 byte[] data = this.decrypt( 256, cipherText );
00307 if ( data != null )
00308 {
00309 String msg = new String( data, "UTF8" );
00310 if ( msg.startsWith( "[BEGIN]" ) )
00311 {
00312 clearText = msg.substring( 7 );
00313 }
00314 }
00315 }
00316 catch( UnsupportedEncodingException e )
00317 {
00318 Log.exception( Log.TRACE, e );
00319 }
00320 catch( IOException e )
00321 {
00322 Log.exception( Log.TRACE, e );
00323 }
00324
00325 return clearText;
00326 }
00327 }