Created
September 11, 2013 00:42
-
-
Save dacrazycoder/6517914 to your computer and use it in GitHub Desktop.
What happens when angry elephants make you pass encrypted objects as url params...
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.test.web.controllers; | |
import java.io.ByteArrayInputStream; | |
import java.io.ByteArrayOutputStream; | |
import java.io.ObjectInput; | |
import java.io.ObjectInputStream; | |
import java.io.ObjectOutput; | |
import java.io.ObjectOutputStream; | |
import java.net.URLEncoder; | |
import java.security.MessageDigest; | |
import java.security.SecureRandom; | |
import java.util.HashMap; | |
import java.util.Map; | |
import javax.crypto.Cipher; | |
import javax.crypto.spec.IvParameterSpec; | |
import javax.crypto.spec.SecretKeySpec; | |
import javax.servlet.http.HttpServletResponse; | |
import org.apache.commons.codec.binary.Base64; | |
import org.springframework.stereotype.Controller; | |
import org.springframework.ui.Model; | |
import org.springframework.web.bind.annotation.PathVariable; | |
import org.springframework.web.bind.annotation.RequestMapping; | |
import org.springframework.web.bind.annotation.RequestMethod; | |
import org.springframework.web.bind.annotation.RequestParam; | |
@Controller | |
public class EncryptedViewController { | |
private String keyString = "adkj@#$02#@adflkj)(*jlj@#$#@LKjasdjlkj<.,mo@#$@#kljlkdsu343"; | |
protected final Logger logger = LoggerFactory.getLogger(this.getClass()); | |
@RequestMapping(value = "/view", method = RequestMethod.GET) | |
public String getDencryptedUrlView(@RequestParam String d, @RequestParam String v) throws Exception { | |
// The data goes out urlEncoded.. but comes in decoded (No Need to url decode on the request) | |
Object obj = decryptObject(d, v); | |
System.out.println("Object Decrypted: "+obj.toString()); | |
return "INDEX"; | |
} | |
@RequestMapping(value = "/{id}", method = RequestMethod.GET) | |
public String getEncryptedUrl(@PathVariable String id) { | |
Map<String,String> map = new HashMap<String,String>(); | |
map.put("id",id); | |
map.put("topSecret","Waffles are tasty"); | |
try { | |
String[] encrypted = encryptObject(map); | |
// url may differ.. based upon project initial context | |
System.out.println("http://localhost:8080/view?d="+encrypted[0]+"&v="+encrypted[1]); | |
}catch(Exception e) { | |
//logger.debug("Unable to encrypt view id: "+id, e); | |
} | |
return "INDEX"; | |
} | |
/** | |
* Encrypts and encodes the Object and IV for url inclusion | |
* @param input | |
* @return | |
* @throws Exception | |
*/ | |
private String[] encryptObject(Object obj) throws Exception { | |
ByteArrayOutputStream stream = new ByteArrayOutputStream(); | |
ObjectOutput out = new ObjectOutputStream(stream); | |
try { | |
// Serialize the object | |
out.writeObject(obj); | |
byte[] serialized = stream.toByteArray(); | |
// Setup the cipher and Init Vector | |
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); | |
byte[] iv = new byte[cipher.getBlockSize()]; | |
new SecureRandom().nextBytes(iv); | |
IvParameterSpec ivSpec = new IvParameterSpec(iv); | |
// Hash the key with SHA-256 and trim the output to 128-bit for the key | |
MessageDigest digest = MessageDigest.getInstance("SHA-256"); | |
digest.update(keyString.getBytes()); | |
byte[] key = new byte[16]; | |
System.arraycopy(digest.digest(), 0, key, 0, key.length); | |
SecretKeySpec keySpec = new SecretKeySpec(key, "AES"); | |
// encrypt | |
cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec); | |
// Encrypt & Encode the input | |
byte[] encrypted = cipher.doFinal(serialized); | |
byte[] base64Encoded = Base64.encodeBase64(encrypted); | |
String base64String = new String(base64Encoded); | |
String urlEncodedData = URLEncoder.encode(base64String,"UTF-8"); | |
// Encode the Init Vector | |
byte[] base64IV = Base64.encodeBase64(iv); | |
String base64IVString = new String(base64IV); | |
String urlEncodedIV = URLEncoder.encode(base64IVString, "UTF-8"); | |
return new String[] {urlEncodedData, urlEncodedIV}; | |
}finally { | |
stream.close(); | |
out.close(); | |
} | |
} | |
/** | |
* Decrypts the String and serializes the object | |
* @param base64Data | |
* @param base64IV | |
* @return | |
* @throws Exception | |
*/ | |
public Object decryptObject(String base64Data, String base64IV) throws Exception { | |
// Decode the data | |
byte[] encryptedData = Base64.decodeBase64(base64Data.getBytes()); | |
// Decode the Init Vector | |
byte[] rawIV = Base64.decodeBase64(base64IV.getBytes()); | |
// Configure the Cipher | |
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); | |
IvParameterSpec ivSpec = new IvParameterSpec(rawIV); | |
MessageDigest digest = MessageDigest.getInstance("SHA-256"); | |
digest.update(keyString.getBytes()); | |
byte[] key = new byte[16]; | |
System.arraycopy(digest.digest(), 0, key, 0, key.length); | |
SecretKeySpec keySpec = new SecretKeySpec(key, "AES"); | |
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec); | |
// Decrypt the data.. | |
byte[] decrypted = cipher.doFinal(encryptedData); | |
// Deserialize the object | |
ByteArrayInputStream stream = new ByteArrayInputStream(decrypted); | |
ObjectInput in = new ObjectInputStream(stream); | |
Object obj = null; | |
try { | |
obj = in.readObject(); | |
}finally { | |
stream.close(); | |
in.close(); | |
} | |
return obj; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment