Revision: 684
          http://stripes.svn.sourceforge.net/stripes/?rev=684&view=rev
Author:   bengunter
Date:     2007-12-13 10:51:44 -0800 (Thu, 13 Dec 2007)

Log Message:
-----------
Fixed STS-459: CryptoUtil should validate its input. A magic number is prefixed 
to the result before encryption and checked for upon decryption. In testing 
this, I also found that most of the time when a bogus value is fed in to 
decrypt it results in a BadPaddingException so I added a try/catch to catch 
that and IllegalBlockSizeException. Those cases plus the case of a bogus input 
that happens to decrypt properly are logged as a warning and null is returned.

Modified Paths:
--------------
    trunk/stripes/src/net/sourceforge/stripes/util/CryptoUtil.java
    trunk/tests/src/net/sourceforge/stripes/util/CryptoUtilTest.java

Modified: trunk/stripes/src/net/sourceforge/stripes/util/CryptoUtil.java
===================================================================
--- trunk/stripes/src/net/sourceforge/stripes/util/CryptoUtil.java      
2007-12-13 15:45:18 UTC (rev 683)
+++ trunk/stripes/src/net/sourceforge/stripes/util/CryptoUtil.java      
2007-12-13 18:51:44 UTC (rev 684)
@@ -16,7 +16,9 @@
 
 import net.sourceforge.stripes.exception.StripesRuntimeException;
 
+import javax.crypto.BadPaddingException;
 import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
 import javax.crypto.KeyGenerator;
 import javax.crypto.SecretKey;
 import javax.servlet.http.HttpServletRequest;
@@ -38,6 +40,8 @@
  * @since Stripes 1.2
  */
 public class CryptoUtil {
+    private static final Log log = Log.getInstance(CryptoUtil.class);
+
     /** The algorithm that is used to encrypt values. */
     public static String ALGORITHM = "AES";
 
@@ -45,9 +49,16 @@
     public static String SESSION_ATTR_SECRET_KEY = "__stripes_secret_key";
 
     /**
+     * Magic number to be prefixed to data before encryption. When a value is 
decrypted, the
+     * resulting byte array must begin with the magic number to ensure that it 
was encrypted with
+     * the current session key. (The "||" part is because they look like 
Stripes.)
+     */
+    public static byte[] MAGIC_NUMBER = new byte[] { Byte.MIN_VALUE, 
Byte.MAX_VALUE, '|', '|' };
+
+    /**
      * Takes in a String, encrypts it and then base64 encodes the resulting 
byte[] so that
      * it can be transmitted and stored as a String.  Can be decrypted by a 
subsequent call
-     * to decrypt(String,Request) in the same session.
+     * to [EMAIL PROTECTED] #decrypt(String, HttpServletRequest)} in the same 
session.
      *
      * @param input the String to encrypt and encode
      * @param request the current request
@@ -59,7 +70,11 @@
         try {
             // First encrypt the String with a Cipher
             Cipher cipher = getCipher(request, Cipher.ENCRYPT_MODE);
-            byte[] output = cipher.doFinal(input.getBytes());
+            byte[] inbytes = input.getBytes();
+            int size = cipher.getOutputSize(MAGIC_NUMBER.length + 
inbytes.length);
+            byte[] output = new byte[size];
+            int index = cipher.update(MAGIC_NUMBER, 0, MAGIC_NUMBER.length, 
output, 0);
+            cipher.doFinal(inbytes, 0, inbytes.length, output, index);
 
             // Then base64 encode the bytes
             return Base64.encodeBytes(output, Base64.URL_SAFE | 
Base64.DONT_BREAK_LINES);
@@ -71,7 +86,7 @@
 
     /**
      * Takes in a base64 encoded and encrypted String that was generated by a 
call
-     * to encrypt(String,Request) and decrypts it.
+     * to [EMAIL PROTECTED] #encrypt(String, HttpServletRequest)} and decrypts 
it.
      *
      * @param input the base64 String to decode and decrypt
      * @param request the current request
@@ -89,9 +104,28 @@
 
         // Then fetch a cipher and decrypt the bytes
         Cipher cipher = getCipher(request, Cipher.DECRYPT_MODE);
-        byte[] output = cipher.doFinal(bytes);
+        byte[] output;
+        try {
+            output = cipher.doFinal(bytes);
+        }
+        catch (IllegalBlockSizeException e) {
+            log.warn("Input was not encrypted with the current session key: ", 
input);
+            return null;
+        }
+        catch (BadPaddingException e) {
+            log.warn("Input was not encrypted with the current session key: ", 
input);
+            return null;
+        }
 
-        return new String(output);
+        // Check for the magic number so we don't eat garbage
+        for (int i = 0; i < MAGIC_NUMBER.length; i++) {
+            if (MAGIC_NUMBER[i] != output[i]) {
+                log.warn("Input was not encrypted with the current session 
key: ", input);
+                return null;
+            }
+        }
+
+        return new String(output, MAGIC_NUMBER.length, output.length - 
MAGIC_NUMBER.length);
     }
 
     /**

Modified: trunk/tests/src/net/sourceforge/stripes/util/CryptoUtilTest.java
===================================================================
--- trunk/tests/src/net/sourceforge/stripes/util/CryptoUtilTest.java    
2007-12-13 15:45:18 UTC (rev 683)
+++ trunk/tests/src/net/sourceforge/stripes/util/CryptoUtilTest.java    
2007-12-13 18:51:44 UTC (rev 684)
@@ -65,4 +65,11 @@
 
         Assert.assertNull(decrypted, "Decrypting null should give back null.");
     }
+    
+    @Test(groups = "fast")
+    public void decryptBogusInputTest() throws Exception {
+        String input = CryptoUtil.encrypt("This is bogus!", getRequest());
+        String decrypted = CryptoUtil.decrypt(input, getRequest());
+        Assert.assertNull(decrypted, "Decrypting a bogus input should give 
back null.");
+    }
 }


This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.

-------------------------------------------------------------------------
SF.Net email is sponsored by:
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services
for just about anything Open Source.
http://ad.doubleclick.net/clk;164216239;13503038;w?http://sf.net/marketplace
_______________________________________________
Stripes-development mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/stripes-development

Reply via email to