[Schmitzm-commits] r1794 - in trunk/schmitzm-core/src/main/java/de/schmitzm: crypt lang

scm-commit@wald.intevation.org scm-commit at wald.intevation.org
Wed Nov 23 20:19:27 CET 2011


Author: mojays
Date: 2011-11-23 20:19:26 +0100 (Wed, 23 Nov 2011)
New Revision: 1794

Modified:
   trunk/schmitzm-core/src/main/java/de/schmitzm/crypt/CryptUtil.java
   trunk/schmitzm-core/src/main/java/de/schmitzm/lang/ApplicationProps.java
Log:
ApplicationProps: new methods setEncrypted(.) and getStringDecrypted(.) to automatically encrypt/decrypt a value in property file

Modified: trunk/schmitzm-core/src/main/java/de/schmitzm/crypt/CryptUtil.java
===================================================================
--- trunk/schmitzm-core/src/main/java/de/schmitzm/crypt/CryptUtil.java	2011-11-23 17:36:20 UTC (rev 1793)
+++ trunk/schmitzm-core/src/main/java/de/schmitzm/crypt/CryptUtil.java	2011-11-23 19:19:26 UTC (rev 1794)
@@ -10,6 +10,7 @@
 import java.security.GeneralSecurityException;
 import java.security.NoSuchAlgorithmException;
 import java.security.NoSuchProviderException;
+import java.util.Properties;
 
 import javax.crypto.Cipher;
 import javax.crypto.NoSuchPaddingException;
@@ -25,12 +26,66 @@
  */
 public class CryptUtil {
 
+  /**
+   * An encrypted byte array can not be converted to string by
+   * {@code new String(byte[])} (e.g. to store the encrypted value
+   * in a {@link Properties} file)! This string creation destroys the
+   * encrypted value!<br> 
+   * This method simply converts the byte array (the encrypted string)
+   * to a comma-separated list of the numeric byte values. This string
+   * can riskless stored in {@link Properties} file.<br>
+   * The other way around: {@link #convertWritableStringToEncryptedBytes(String)}
+   * method can be used to convert the comma-separated byte list back to the
+   * byte array (encrypted value).
+   * @param encryptedText encrypted text
+   * @see #convertWritableStringToEncryptedBytes(String)
+   */
+  public static String convertEncryptedBytesToWritableString(byte[] encryptedText) {
+    if ( encryptedText == null )
+      return null;
+    StringBuffer str = new StringBuffer();
+    for (int i=0; i<encryptedText.length; i++) {
+      if (i>0)
+        str.append(',');
+      str.append(encryptedText[i]);
+    }
+    return str.toString();
+  }
+
+  /**
+   * An encrypted byte array can not be converted to string by
+   * {@code new String(byte[])} (e.g. to store the encrypted value
+   * in a {@link Properties} file)! This string creation destroys the
+   * encrypted value!<br>
+   * {@link #convertEncryptedBytesToWritableString(byte[])} converts
+   * the byte array (the encrypted string) to a comma-separated list
+   * of the numeric byte values. This string can stored without risk
+   * in {@link Properties} file.<br>
+   * This method can be used to convert the string (comma-separated byte list)
+   * back to the byte array (encrypted value).
+   * @param byteList comma-separated list of numeric byte values
+   * @see #convertEncryptedBytesToWritableString(byte[])
+   */
+  public static byte[] convertWritableStringToEncryptedBytes(String byteList) {
+    if ( byteList == null )
+      return null;
+    try {
+      String[] strParts = byteList.split(",");
+      byte[]   bytes = new byte[strParts.length];
+      for (int i=0; i<bytes.length; i++)
+        bytes[i] = Byte.parseByte(strParts[i]);
+      return bytes;
+    } catch (Exception err) {
+      throw new IllegalArgumentException("Byte list does not represent an encrypted string generated by convertEncryptedBytesToWritableString(.): "+byteList);
+    }
+  }
+
     /**
      * Creates a DEC cipher.
      * @param cryptMode  {@link Cipher#ENCRYPT_MODE} or {@link Cipher#DECRYPT_MODE}
      * @param keyBytes encryption key
      */
-    public static Cipher getDESCipher(final int cryptMode, final byte[] keyBytes) throws GeneralSecurityException {
+    public static Cipher createDESCipher(final int cryptMode, final byte[] keyBytes) throws GeneralSecurityException {
       assert cryptMode == Cipher.ENCRYPT_MODE || cryptMode == Cipher.DECRYPT_MODE;
       assert keyBytes != null;
       Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
@@ -88,7 +143,7 @@
    */
   public static byte[] cryptBytes(byte[] inputStr, byte[] keyBytes, int cryptMode) {
     try {
-      Cipher cipher = getDESCipher(cryptMode, keyBytes);
+      Cipher cipher = createDESCipher(cryptMode, keyBytes);
       return cryptBytes(inputStr, cipher);
     } catch (Exception err) {
       throw new RuntimeException(err);

Modified: trunk/schmitzm-core/src/main/java/de/schmitzm/lang/ApplicationProps.java
===================================================================
--- trunk/schmitzm-core/src/main/java/de/schmitzm/lang/ApplicationProps.java	2011-11-23 17:36:20 UTC (rev 1793)
+++ trunk/schmitzm-core/src/main/java/de/schmitzm/lang/ApplicationProps.java	2011-11-23 19:19:26 UTC (rev 1794)
@@ -40,9 +40,12 @@
 import java.net.URL;
 import java.util.Properties;
 
+import javax.crypto.Cipher;
+
 import org.apache.commons.io.FileUtils;
 import org.apache.log4j.Logger;
 
+import de.schmitzm.crypt.CryptUtil;
 import de.schmitzm.swing.ExceptionDialog;
 import de.schmitzm.temp.BaseTypeUtil;
 
@@ -67,6 +70,8 @@
   private boolean haveToCloseFOS = false;
   private File propertiesFile = null;
   private Component owner;
+  private Cipher encryptCipher = null;
+  private Cipher decryptCipher = null;
   
   /**
    * Creates a new application properties instance.
@@ -118,7 +123,61 @@
   public void setAutoSave(boolean autoSave) {
     this.autoSave = autoSave;
   }
+  
+  /**
+   * Returns the {@link Cipher} used to encrypt property values.
+   */
+  public Cipher getEncrytionCipher() {
+    return encryptCipher;
+  }
+  
+  /**
+   * Returns the {@link Cipher} used to decrypt property values.
+   */
+  public Cipher getDecrytionCipher() {
+    return decryptCipher;
+  }
+  
+  /**
+   * Sets ciphers used to decrypt and encrypt property values.
+   * @param encryptCipher cipher to encrypt
+   * @param decyptCiper   cipher to decrypt
+   * @see #setEncrypted(Object, Object)
+   * @see #getStringDecrypted(Object, String...)
+   */
+  public void setCipher(Cipher encryptCipher, Cipher decyptCiper) {
+    this.decryptCipher = decyptCiper;
+    this.encryptCipher = encryptCipher;
+  }
 
+  /**
+   * Sets default DES ciphers used to decrypt and encrypt property values.
+   * @param cryptKey key used to encrypt/decrypt
+   * @see #setEncrypted(Object, Object)
+   * @see #getStringDecrypted(Object, String...)
+   */
+  public void setCipher(byte[] cryptKey) {
+    try {
+      setCipher(
+          CryptUtil.createDESCipher(Cipher.ENCRYPT_MODE, cryptKey),
+          CryptUtil.createDESCipher(Cipher.DECRYPT_MODE, cryptKey)
+      );
+    } catch (Exception err) {
+      throw new RuntimeException("Error creating DES Cipher",err);
+    }
+  }
+  
+
+  /**
+   * Sets default DES ciphers used to decrypt and encrypt property values.
+   * @param cryptKey key used to encrypt/decrypt
+   * @see #setEncrypted(Object, Object)
+   * @see #getStringDecrypted(Object, String...)
+   */
+  public void setCipher(String cryptKey) {
+    setCipher(cryptKey.getBytes());
+  }
+  
   //***************************************************
   //************* GETTER ******************************
   //***************************************************
@@ -177,6 +236,24 @@
     return get(key,String.class,defaultValue[0]);
   }
   
+  /**
+   * Returns a property value which was stored encrypted in the map.
+   * @param key properties key
+   * @param defaultValueDecrypted default value (already decrypted!)
+   *                              returned if no value is found for the key
+   */
+  public String getStringDecrypted(KEYS key, String... defaultValueDecrypted) {
+    if ( encryptCipher == null || decryptCipher == null )
+      throw new UnsupportedOperationException("getStringDecrypted(.) can not be used before a cipher is set.");
+
+    String encryptedValue = getString(key);
+    if ( encryptedValue == null )
+      return defaultValueDecrypted.length > 0 ? defaultValueDecrypted[0] : null;
+    byte[] encryptedBytes = CryptUtil.convertWritableStringToEncryptedBytes(encryptedValue);
+    String decryptedValue = CryptUtil.decryptString(encryptedBytes, getDecrytionCipher());
+    return decryptedValue;
+  }
+
   public Character getChar(KEYS key, Character... defaultValue) {
     if ( defaultValue.length == 0 )
       return get(key,Character.class);
@@ -195,7 +272,45 @@
     if ( getAutoSave() )
       store();
   }
-
+  
+  /**
+   * Set a value in the underlying {@link Properties}. The value
+   * is encrypted by the encryption {@link Cipher}.
+   * @see #setCipher(Cipher, Cipher)
+   * @see #setCipher(byte[])
+   * @see #setCipher(String)
+   */
+  public void setEncrypted(KEYS key, Object clearValue) {
+    if ( encryptCipher == null || decryptCipher == null )
+      throw new UnsupportedOperationException("setEncrypted(.) can not be used before a cipher is set.");
+    // NULL can not be encrypted
+    if ( clearValue == null ) {
+      LOGGER.warn("NULL value for key '"+key+"' is stored not-encrypt!");
+      set(key,clearValue);
+      return;
+    }
+    // convert Byte[] to byte[]
+    if ( clearValue instanceof Byte[] ) {
+      Byte[] b = (Byte[])clearValue;
+      clearValue = new byte[b.length];
+      for (int i=0; i<b.length; i++)
+        ((byte[])clearValue)[i] = b[i];
+    }
+    // convert byte[] to String; all others according to
+    // the toString() method
+    if ( clearValue instanceof byte[] )
+      clearValue = new String((byte[])clearValue);
+    else
+      clearValue = clearValue.toString();
+    
+    byte[] encryptBytes = CryptUtil.encryptString((String)clearValue, getEncrytionCipher());
+    // Problem: encrypted bytes can not be stores as String!
+    //          properties.put(key.toString(), encryptBytes) forces
+    //          a crash on store() because cast to String fails!
+    // Solution: store bytes concatenated
+    set(key, CryptUtil.convertEncryptedBytesToWritableString(encryptBytes)); 
+  }
+  
   /////////////////////////////////////////////////////
   ///////////////  Property storage  //////////////////
   /////////////////////////////////////////////////////



More information about the Schmitzm-commits mailing list