Permalink
Browse files

Some formatting applied

  • Loading branch information...
1 parent 68c48b1 commit 1f353ddc15878fd78e01295a0009daaac6619f4d @lhft lhft committed Feb 11, 2013
Showing with 126 additions and 82 deletions.
  1. +126 −82 src/mochiweb_session.erl
View
@@ -1,71 +1,97 @@
%% @author Asier Azkuenaga Batiz <asier@zebixe.com>
-%% @doc HTTP Cookie session. Note that the expiration time travels unencrypted as far as this module concerns.
+%% @doc HTTP Cookie session. Note that the expiration time travels unencrypted
+%% as far as this module concerns.
%% In order to achieve more security, it is adviced to use https
-
-module(mochiweb_session).
--export([generate_session_data/4,generate_session_cookie/4,check_session_cookie/4]).
-
-
-%% @spec generate_session_data(ExpirationTime,Data :: string(),FSessionKey : function(A),ServerKey) -> binary()
-%% @doc generates a secure encrypted binary convining all the parameters.
-%% The expiration time is a number that must be able to be represented on 32 bit.
-generate_session_data(ExpirationTime,Data,FSessionKey,ServerKey) when is_integer(ExpirationTime),is_list(Data), is_function(FSessionKey)->
- BData=ensure_binary(Data),
- ExpTime= integer_to_list(ExpirationTime),
- Key=gen_key(ExpTime,ServerKey),
- Hmac=gen_hmac(ExpTime,BData,FSessionKey(ExpTime),Key),
- EData=encrypt_data(BData,Key),
- base64:encode(<< ExpirationTime:32/integer,Hmac/binary, EData/binary>>).
-
-%% @spec generate_session_data(UserName,ExpirationTime,SessionExtraData,FSessionKey : function(A),ServerKey) -> mochiweb_cookie()
+-export([generate_session_data/4, generate_session_cookie/4,
+ check_session_cookie/4]).
+
+%% @spec generate_session_data(ExpirationTime, Data, FSessionKey, ServerKey)
+%% -> binary()
+%% ExpirationTime = integer(),
+%% Data = string(),
+%% FSessionKey = function(A),
+%% ServerKey = string(),
+%% @doc generates a secure encrypted binary convining all the parameters. The
+%% expiration time is a number represented on 32 bit.
+generate_session_data(ExpirationTime, Data, FSessionKey, ServerKey)
+ when is_integer(ExpirationTime), is_function(FSessionKey)->
+ BData = ensure_binary(Data),
+ ExpTime = integer_to_list(ExpirationTime),
+ Key = gen_key(ExpTime,ServerKey),
+ Hmac = gen_hmac(ExpTime,BData,FSessionKey(ExpTime),Key),
+ EData = encrypt_data(BData,Key),
+ base64:encode(<< ExpirationTime:32/integer, Hmac/binary, EData/binary >>).
+
+%% @spec generate_session_data(UserName, ExpirationTime, SessionExtraData,
+%% FSessionKey,ServerKey) -> mochiweb_cookie()
+%% ExpirationTime = integer(),
+%% Data = string(),
+%% FSessionKey = function(A),
+%% ServerKey = string(),
%% @doc generates a secure encrypted binary convining all the parameters.
-%% The expiration time is a number that must be able to be represented on 32 bit.
-%% This function conveniently generates a mochiweb cookie using the "id" as key and current local time as local time
-generate_session_cookie(ExpirationTime,Data,FSessionKey,ServerKey) when is_integer(ExpirationTime),is_list(Data), is_function(FSessionKey)->
- CookieData=generate_session_data(ExpirationTime,Data,FSessionKey,ServerKey),
- mochiweb_cookies:cookie("id",CookieData,[{max_age,20000},{local_time,calendar:universal_time_to_local_time(calendar:universal_time())}]).
-
-%% @spec cookie_check_session(RawData,ExpirationTime,FSessionKey, ServerKey)->{false,[ExpirationTime,Data]} |
-%% {false,[]} |
-%% {true,[ExpirationTime,Data]},
-%% RawData = binary() ,
-%% ExpirationTime = integer(),
-%% FSessionKey = function(A) ,
-%% ServerKey = string()
+%% The expiration time is a number represented on 32 bit.
+%% This function conveniently generates a mochiweb cookie using the "id"
+%% as key and current local time as local time
+generate_session_cookie(ExpirationTime, Data, FSessionKey, ServerKey)
+ when is_integer(ExpirationTime), is_function(FSessionKey)->
+ CookieData = generate_session_data(ExpirationTime, Data,
+ FSessionKey, ServerKey),
+ mochiweb_cookies:cookie("id", CookieData,
+ [{max_age, 20000},
+ {local_time,
+ calendar:universal_time_to_local_time(
+ calendar:universal_time())}]).
+
+%% @spec cookie_check_session(RawData,ExpirationTime,FSessionKey, ServerKey)->
+%% {false,[ExpirationTime,Data]} |
+%% {false,[]} |
+%% {true,[ExpirationTime,Data]},
+%% RawData = binary() ,
+%% ExpirationTime = integer(),
+%% FSessionKey = function(A) ,
+%% ServerKey = string()
check_session_cookie(undefined,_,_,_) ->
- {false,[]};
+ {false, []};
check_session_cookie([],_,_,_) ->
- {false,[]};
-check_session_cookie(ECookie,ExpirationTime,FSessionKey,ServerKey) when is_binary(ECookie), is_integer(ExpirationTime), is_function(FSessionKey)->
- <<ExpirationTime1:32/integer,BHmac:20/binary,EData/binary>> = base64:decode(ECookie),
- Key=gen_key(integer_to_list(ExpirationTime1),ServerKey),
- Data=decrypt_data(EData,Key),
- Hmac2=gen_hmac(integer_to_list(ExpirationTime1),Data,FSessionKey(integer_to_list(ExpirationTime1)),Key),
- if ExpirationTime1<ExpirationTime -> {false,[ExpirationTime1,binary_to_list(Data)]};
+ {false, []};
+check_session_cookie(ECookie, ExpirationTime, FSessionKey, ServerKey)
+ when is_binary(ECookie), is_integer(ExpirationTime),
+ is_function(FSessionKey)->
+ << ExpirationTime1:32/integer, BHmac:20/binary, EData/binary >> =
+ base64:decode(ECookie),
+ Key = gen_key(integer_to_list(ExpirationTime1), ServerKey),
+ Data = decrypt_data(EData, Key),
+ Hmac2 = gen_hmac(integer_to_list(ExpirationTime1), Data,
+ FSessionKey(integer_to_list(ExpirationTime1)), Key),
+ if ExpirationTime1 < ExpirationTime ->
+ {false, [ExpirationTime1, binary_to_list(Data)]};
true ->
- if Hmac2==BHmac -> {true,[ExpirationTime1,binary_to_list(Data)]};
- true -> {false,[ExpirationTime1,binary_to_list(Data)]}
+ if Hmac2 == BHmac ->
+ {true, [ExpirationTime1, binary_to_list(Data)]};
+ true ->
+ {false, [ExpirationTime1, binary_to_list(Data)]}
end
end.
ensure_binary(B) when is_binary(B) ->
B;
ensure_binary(L) when is_list(L) ->
- iolist_to_binary(L). %note, iolist_to_binary is better, since we might use something like mochijson2 here
+ iolist_to_binary(L).
-encrypt_data(Data,Key) ->
+encrypt_data(Data, Key) ->
IV = crypto:rand_bytes(16),
- Crypt=crypto:aes_cfb_128_encrypt(Key, IV, Data),
- <<IV/binary,Crypt/binary>>.
-decrypt_data(<<IV:16/binary,Crypt/binary>>,Key) ->
- crypto:aes_cfb_128_decrypt(Key, IV,Crypt).
+ Crypt = crypto:aes_cfb_128_encrypt(Key, IV, Data),
+ << IV/binary, Crypt/binary >>.
+decrypt_data(<< IV:16/binary, Crypt/binary >>, Key) ->
+ crypto:aes_cfb_128_decrypt(Key, IV, Crypt).
-gen_key(ExpirationTime,ServerKey)->
+gen_key(ExpirationTime, ServerKey)->
crypto:md5_mac(ServerKey, [ExpirationTime]).
-gen_hmac(ExpirationTime,Data,SessionKey,Key)->
- crypto:sha_mac(Key,[ExpirationTime,Data,SessionKey]).
+gen_hmac(ExpirationTime, Data, SessionKey, Key)->
+ crypto:sha_mac(Key, [ExpirationTime, Data, SessionKey]).
-ifdef(TEST).
@@ -79,38 +105,56 @@ generate_check_session_cookie_test_()->
server_key()->%setup function
["adfasdfasfs",30000].
-generate_check_session_cookie([ServerKey,TimeStamp]) ->
- [?_assertEqual({true,[TimeStamp+1000,"alice"]},
- check_session_cookie(generate_session_data(TimeStamp+1000,"alice",fun(A)-> A end,ServerKey),
- TimeStamp,fun(A)-> A end,ServerKey)),
- ?_assertEqual({true,[TimeStamp+1000,"alice and"]},
- check_session_cookie(generate_session_data(TimeStamp+1000,"alice and",fun(A)-> A end,ServerKey),
- TimeStamp,fun(A)-> A end,ServerKey)),
-
-
- ?_assertEqual({true,[TimeStamp+1000,"alice and"]},
- check_session_cookie(generate_session_data(TimeStamp+1000,"alice and",fun(A)-> A end,ServerKey),
- TimeStamp,fun(A)-> A end,ServerKey)),
-
-
- ?_assertEqual({true,[TimeStamp+1000,"alice and bob"]},
- check_session_cookie(generate_session_data(TimeStamp+1000,"alice and bob",fun(A)-> A end,ServerKey),
- TimeStamp,fun(A)-> A end,ServerKey)),
- ?_assertEqual({true,[TimeStamp+1000,"alice jlkjfkjsdfg sdkfjgldsjgl"]},
- check_session_cookie(generate_session_data(TimeStamp+1000,"alice jlkjfkjsdfg sdkfjgldsjgl",fun(A)-> A end,ServerKey),
- TimeStamp,fun(A)-> A end,ServerKey)),
- ?_assertEqual({true,[TimeStamp+1000,"alice .'¡'ç+-$%/(&\""]},
- check_session_cookie(generate_session_data(TimeStamp+1000,"alice .'¡'ç+-$%/(&\"",fun(A)-> A end,ServerKey),
- TimeStamp,fun(A)-> A end,ServerKey)),
- ?_assertEqual({true,[TimeStamp+1000,"alice456689875"]},
- check_session_cookie(generate_session_data(TimeStamp+1000,["alice","456689875"],fun(A)-> A end,ServerKey),
- TimeStamp,fun(A)-> A end,ServerKey)),
- ?_assertError(function_clause,
- check_session_cookie(generate_session_data(TimeStamp+1000,{tuple,one},fun(A)-> A end,ServerKey),
- TimeStamp,fun(A)-> A end,ServerKey)),
- ?_assertEqual({false,[TimeStamp-1,"bob"]},
- check_session_cookie(generate_session_data(TimeStamp-1,"bob",fun(A)-> A end,ServerKey),
- TimeStamp,fun(A)-> A end,ServerKey))%current timestamp newer than cookie, it's expired
+generate_check_session_cookie([ServerKey, TS]) ->
+ [?_assertEqual(
+ {true, [TS+1000, "alice"]},
+ check_session_cookie(
+ generate_session_data(TS+1000, "alice", fun(A)-> A end, ServerKey),
+ TS, fun(A)-> A end, ServerKey)),
+ ?_assertEqual(
+ {true, [TS+1000, "alice and"]},
+ check_session_cookie(
+ generate_session_data(TS+1000, "alice and", fun(A)-> A end, ServerKey),
+ TS, fun(A)-> A end, ServerKey)),
+ ?_assertEqual(
+ {true, [TS+1000, "alice and"]},
+ check_session_cookie(
+ generate_session_data(TS+1000, "alice and", fun(A)-> A end, ServerKey),
+ TS, fun(A)-> A end,ServerKey)),
+ ?_assertEqual(
+ {true, [TS+1000, "alice and bob"]},
+ check_session_cookie(
+ generate_session_data(TS+1000, "alice and bob",
+ fun(A)-> A end, ServerKey),
+ TS, fun(A)-> A end, ServerKey)),
+ ?_assertEqual(
+ {true, [TS+1000, "alice jlkjfkjsdfg sdkfjgldsjgl"]},
+ check_session_cookie(
+ generate_session_data(TS+1000, "alice jlkjfkjsdfg sdkfjgldsjgl",
+ fun(A)-> A end, ServerKey),
+ TS, fun(A)-> A end, ServerKey)),
+ ?_assertEqual(
+ {true, [TS+1000, "alice .'¡'ç+-$%/(&\""]},
+ check_session_cookie(
+ generate_session_data(TS+1000, "alice .'¡'ç+-$%/(&\""
+ ,fun(A)-> A end, ServerKey),
+ TS, fun(A)-> A end, ServerKey)),
+ ?_assertEqual(
+ {true,[TS+1000,"alice456689875"]},
+ check_session_cookie(
+ generate_session_data(TS+1000, ["alice","456689875"],
+ fun(A)-> A end, ServerKey),
+ TS, fun(A)-> A end, ServerKey)),
+ ?_assertError(
+ function_clause,
+ check_session_cookie(
+ generate_session_data(TS+1000, {tuple,one},
+ fun(A)-> A end, ServerKey),
+ TS, fun(A)-> A end,ServerKey)),
+ ?_assertEqual(
+ {false, [TS-1, "bob"]},
+ check_session_cookie(
+ generate_session_data(TS-1, "bob", fun(A)-> A end,ServerKey),
+ TS, fun(A)-> A end, ServerKey))
].
-
-endif.

0 comments on commit 1f353dd

Please sign in to comment.