Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Added some tests. still getting errors though

  • Loading branch information...
commit 92464d0b860ad9275a9a21e81aefba86f3bfa189 1 parent 1be66c0
@lhft lhft authored
Showing with 47 additions and 24 deletions.
  1. +47 −24 src/mochiweb_session.erl
View
71 src/mochiweb_session.erl
@@ -1,21 +1,25 @@
%% @author Asier Azkuenaga Batiz <asier@zebixe.com>
-%% @doc HTTP Cookie sessionn.
+%% @doc HTTP Cookie session. Note that the user name and expiration time travel 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/5,generate_session_cookie/5,check_session_cookie/4]).
-%% @spec generate_session_data(UserName,ExpirationTime,SessionExtraData,FSessionKey : function(A),ServerKey) -> string()
+%% @spec generate_session_data(UserName,ExpirationTime,SessionExtraData : iolist(),FSessionKey : function(A),ServerKey) -> string()
%% @doc generates a secure encrypted string convining all the parameters.
%% The expritation time is considered in seconds
+%% SessionExtraData MUST be of iolist() type
generate_session_data(UserName,ExpirationTime,SessionExtraData,FSessionKey,ServerKey) when is_integer(ExpirationTime)->
+ SessionExtraData2=erlang:term_to_binary(SessionExtraData),
ExpTime=integer_to_list(timestamp_sec(now())+ExpirationTime),
Key=cookie_gen_key(UserName,ExpTime,ServerKey),
- Hmac=cookie_gen_hmac(UserName,ExpTime,SessionExtraData,FSessionKey(UserName),Key),
- EData=cookie_encrypt_data(SessionExtraData,Key),
+ Hmac=cookie_gen_hmac(UserName,ExpTime,SessionExtraData2,FSessionKey(UserName),Key),
+ EData=cookie_encrypt_data(SessionExtraData2,Key),
cookie_encode(iolist_to_binary([ UserName, $,, ExpTime, $,, EData, $,, Hmac ])).
+
%% @spec generate_session_data(UserName,ExpirationTime,SessionExtraData,FSessionKey : function(A),ServerKey) -> mochiweb_cookie()
%% @doc generates a secure encrypted cookie using the generate_session_data function.
generate_session_cookie(UserName,ExpirationTime,SessionExtraData,FSessionKey,ServerKey) when is_integer(ExpirationTime)->
@@ -41,25 +45,30 @@ check_session_cookie([UserName, ExpirationTime1, EData, Hmac],Cookie,ExpirationT
Data=cookie_decrypt_data(EData,Key),
Hmac2=cookie_gen_hmac(UserName,ExpirationTime1,Data,FSessionKey(UserName),Key),
BHmac=list_to_binary(Hmac),
- if ExpTime<ExpirationTime -> {false,[UserName,ExpirationTime1,Data]};
+ if ExpTime<ExpirationTime -> {false,[UserName,ExpirationTime1,erlang:binary_to_term(Data)]};
true ->
- if Hmac2==BHmac -> {true,[UserName,ExpirationTime1,Data]};
- true -> {false,[UserName,ExpirationTime1,Data]}
+ if Hmac2==BHmac -> {true,[UserName,ExpirationTime1,erlang:binary_to_term(Data)]};
+ true -> {false,[UserName,ExpirationTime1,erlang:binary_to_term(Data)]}
end
end;
check_session_cookie(_,_,_,_,_) ->
{false,[]}.
-%% @doc This is the NOT secure version
+
+%% @doc This does not encrypt the whole cookie
cookie_decode (Encoded) when is_binary (Encoded) ->
erlang:binary_to_term (from_base64 (Encoded)).
-cookie_decrypt_data(EData,_Key)->
- %%TODO
- EData.
cookie_encode (Term) ->
to_base64(erlang:term_to_binary (Term, [compressed,{minor_version,1}])).
-cookie_encrypt_data(Data,_Key)->
- %%TODO
- Data.
+
+%% cookie_encrypt_data(Data,Key)-> binary()
+%% Data = Key = iolist() | binary
+cookie_encrypt_data(Data,Key) when is_binary(Data), is_binary(Key)->
+ IV = crypto:rand_bytes(16),
+ [IV] ++ [crypto:aes_cfb_128_encrypt(Key, IV, Data)].
+cookie_decrypt_data(EData,Key) when is_list(EData)->
+ {IV, Crypt} = lists:split(16, EData),
+ crypto:aes_cfb_128_decrypt(Key, list_to_binary(IV),list_to_binary(Crypt)).
+
cookie_gen_key(UserName,ExpirationTime,ServerKey)->
crypto:md5_mac(ServerKey, [UserName, ExpirationTime]).
cookie_gen_hmac(UserName,ExpirationTime,Data,SessionKey,Key)->
@@ -95,22 +104,36 @@ to_base64_char (N) when N >= 52, N =< 61 -> $0 + (N - 52);
to_base64_char (62) -> $_;
to_base64_char (63) -> $-.
-%% @doc Erlang timestamp tuple converted to one number
-timestamp({MGS,S,MIS})->
- MGS*1000000000000+S*1000000+MIS.
+
timestamp_sec({MGS,S,_})->
MGS*1000000+S.
-%%
-%% Tests
-%%
+
-ifdef(TEST).
-include_lib("eunit/include/eunit.hrl").
-generate_session_cookie_test_() ->
- [?_assertEqual({true,["alice",,"alice"]},
- check_session_cookie(generate_session_data("alice",1000,["alice"],fun(A)-> A end,"adfasdfasfs"),
- 1000,fun(A)-> A end,"adfasdfasfs"))
+
+generate_check_session_cookie_test_()->
+ {setup,
+ fun server_key/0, %setup function
+ fun generate_check_session_cookie/1}.
+
+server_key()->
+ ["adfasdfasfs",timestamp_sec(now())].
+
+generate_check_session_cookie([ServerKey,TimeStamp]) ->
+ [?_assertEqual({true,["alice",integer_to_list(TimeStamp+1000),["alice"]]},
+ check_session_cookie(generate_session_data("alice",1000,["alice"],fun(A)-> A end,ServerKey),
+ TimeStamp,fun(A)-> A end,ServerKey)),
+ ?_assertEqual({true,["alice",integer_to_list(TimeStamp+1000),[["sex","female",a]]]},
+ check_session_cookie(generate_session_data("alice",1000,[["sex","female",a]],fun(A)-> A end,ServerKey),
+ TimeStamp,fun(A)-> A end,ServerKey)),
+ ?_assertEqual({true,["alice",integer_to_list(TimeStamp+1000),{tuple,one}]},
+ check_session_cookie(generate_session_data("alice",1000,{tuple,one},fun(A)-> A end,ServerKey),
+ TimeStamp,fun(A)-> A end,ServerKey)),
+ ?_assertEqual({false,["alice",integer_to_list(TimeStamp-1),{tuple,one}]},
+ check_session_cookie(generate_session_data("alice",-1,{tuple,one},fun(A)-> A end,ServerKey),
+ TimeStamp,fun(A)-> A end,ServerKey))%current timestamp newer than cookie, it's expired
].
-endif.
Please sign in to comment.
Something went wrong with that request. Please try again.