--- /dev/null
+package be.nikiroo.utils;
+
+import java.util.Date;
+
+public class CookieUtils {
+ /**
+ * The number of seconds for the period (we accept the current or the
+ * previous period as valid for a cookie, via "offset").
+ */
+ static public int GRACE_PERIOD = 3600 * 1000; // between 1 and 2h
+
+ /**
+ * Generate a new cookie value from the user (email) and an offset.
+ * <p>
+ * You should use an offset of "0" when creating the cookie, and an offset
+ * of "0" or "-1" if required when checking for the value (the idea is to
+ * allow a cookie to persist across two timespans; if not, the cookie will
+ * be expired the very second we switch to a new timespan).
+ *
+ * @param value
+ * the value to generate a cookie for -- you must be able to
+ * regenerate it in order to check it later
+ * @param offset
+ * the offset (should be 0 for creating, 0 then -1 if needed for
+ * checking)
+ *
+ * @return the new cookie
+ */
+ static public String generateCookie(String value, int offset) {
+ long unixTime = (long) Math.floor(new Date().getTime() / GRACE_PERIOD)
+ + offset;
+ return HashUtils.sha512(value + Long.toString(unixTime));
+ }
+
+ /**
+ * Check the given cookie.
+ *
+ * @param value
+ * the value to generate a cookie for -- you must be able to
+ * regenerate it in order to check it later
+ * @param cookie
+ * the cookie to validate
+ *
+ * @return TRUE if it is correct
+ */
+ static public boolean validateCookie(String value, String cookie) {
+ if (cookie != null)
+ cookie = cookie.trim();
+
+ String newCookie = generateCookie(value, 0);
+ if (!newCookie.equals(cookie)) {
+ newCookie = generateCookie(value, -1);
+ }
+
+ return newCookie.equals(cookie);
+ }
+}
--- /dev/null
+package be.nikiroo.utils;
+
+import java.io.UnsupportedEncodingException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+/**
+ * Small class to easily hash some values in a few different ways.
+ * <p>
+ * Does <b>not</b> handle the salt itself, you have to add it yourself.
+ *
+ * @author niki
+ */
+public class HashUtils {
+ /**
+ * Hash the given value.
+ *
+ * @param value
+ * the value to hash
+ *
+ * @return the hash that can be used to confirm a value
+ *
+ * @throws RuntimeException
+ * if UTF-8 support is not available (!) or SHA-512 support is
+ * not available
+ * @throws NullPointerException
+ * if email or pass is NULL
+ */
+ static public String sha512(String value) {
+ return hash("SHA-512", value);
+ }
+
+ /**
+ * Hash the given value.
+ *
+ * @param value
+ * the value to hash
+ *
+ * @return the hash that can be used to confirm the a value
+ *
+ * @throws RuntimeException
+ * if UTF-8 support is not available (!) or MD5 support is not
+ * available
+ * @throws NullPointerException
+ * if email or pass is NULL
+ */
+ static public String md5(String value) {
+ return hash("MD5", value);
+ }
+
+ /**
+ * Hash the given value.
+ *
+ * @param algo
+ * the hash algorithm to use ("MD5" and "SHA-512" are supported)
+ * @param value
+ * the value to hash
+ *
+ * @return the hash that can be used to confirm a value
+ *
+ * @throws RuntimeException
+ * if UTF-8 support is not available (!) or the algorithm
+ * support is not available
+ * @throws NullPointerException
+ * if email or pass is NULL
+ */
+ static private String hash(String algo, String value) {
+ try {
+ MessageDigest md = MessageDigest.getInstance(algo);
+ md.update(value.getBytes("UTF-8"));
+ byte byteData[] = md.digest();
+
+ StringBuffer hexString = new StringBuffer();
+ for (int i = 0; i < byteData.length; i++) {
+ String hex = Integer.toHexString(0xff & byteData[i]);
+ if (hex.length() % 2 == 1)
+ hexString.append('0');
+ hexString.append(hex);
+ }
+
+ return hexString.toString();
+ } catch (NoSuchAlgorithmException e) {
+ throw new RuntimeException(algo + " hashing not available", e);
+ } catch (UnsupportedEncodingException e) {
+ throw new RuntimeException(
+ "UTF-8 encoding is required in a compatible JVM", e);
+ }
+ }
+}