package cooky; import java.io.ByteArrayOutputStream; import java.util.Arrays; import javax.crypto.Mac; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; /** * HMAC (Key-Hashed Message Authentication Code) http://www.ietf.org/rfc/rfc2104.txt * http://www.cse.msu.edu/~alexliu/publications/Cookie/cookie.pdf */ public class CookieEncryption { private static final SecretKey SERVER_KEY = new SecretKeySpec("MyServerPassword".getBytes(), "HmacMD5"); private static final byte SEPARATOR = (byte) ';'; protected Mac mac; protected ByteArrayOutputStream output = new ByteArrayOutputStream(); public CookieEncryption() throws Exception { mac = Mac.getInstance("HmacMD5"); } protected byte[] hmac(final SecretKey key, final byte[]... arrays) throws Exception { mac.init(key); for (byte[] array : arrays) { mac.update(array); } return mac.doFinal(); } public byte[] generateCookieValue(final byte[] username, final byte[] expiresOn, final byte[] data, final byte[] sessionKey) throws Exception { SecretKey k = new SecretKeySpec(hmac(SERVER_KEY, username, expiresOn), "HmacMD5"); byte[] encryptedData = encrypt(data, k); byte[] hash = hmac(k, username, expiresOn, data, sessionKey); output.reset(); output.write(username); output.write(SEPARATOR); output.write(expiresOn); output.write(SEPARATOR); output.write(encryptedData); output.write(SEPARATOR); output.write(hash); return output.toByteArray(); } private byte[] encrypt(final byte[] data, final SecretKey k) { // TODO: do real encryption return data; } private byte[] decrypt(final byte[] data, final SecretKey k) { // TODO: do real decryption return data; } public boolean authenticateCookieValue(final byte[] cookieValue, final byte[] sessionKey) throws Exception { int[] separators = new int[] { -1, -1, -1 }; SecretKey k; byte[] username; byte[] expiresOn; byte[] encryptedData; byte[] decryptedData; byte[] hash; byte[] cookieHash; for (int i = 0, j = 0; i < cookieValue.length; i++) { if (cookieValue[i] == SEPARATOR) { separators[j++] = i; } } username = new byte[separators[0]]; System.arraycopy(cookieValue, 0, username, 0, username.length); expiresOn = new byte[separators[1] - separators[0] - 1]; System.arraycopy(cookieValue, separators[0] + 1, expiresOn, 0, expiresOn.length); encryptedData = new byte[separators[2] - separators[1] - 1]; System.arraycopy(cookieValue, separators[1] + 1, encryptedData, 0, encryptedData.length); cookieHash = new byte[cookieValue.length - separators[2] - 1]; System.arraycopy(cookieValue, separators[2] + 1, cookieHash, 0, cookieHash.length); k = new SecretKeySpec(hmac(SERVER_KEY, username, expiresOn), "HmacMD5"); decryptedData = decrypt(encryptedData, k); hash = hmac(k, username, expiresOn, decryptedData, sessionKey); return Arrays.equals(hash, cookieHash); } }