@@ -27,42 +27,99 @@ make install
2727Usage:
2828--
2929
30- Message to be hashed is defined by secure_link_hmac_message, secret_key
31- is given by secure_link_hmac_secret, and hashing algorithm H is defined
32- by secure_link_hmac_algorithm. The expiration timestamp can be either
33- appended to secret key, or message to be hashed, or both .
30+ Message to be hashed is defined by secure_link_hmac_message, secret_key
31+ is given by secure_link_hmac_secret, and hashing algorithm H is defined
32+ by secure_link_hmac_algorithm. For improved security the timestamp in
33+ ISO 8601 format should be appended to the message to be hashed.
3434
35- Configuration example below.
35+ It is possible to create links with limited lifetime. This is defined by
36+ an optional parameter. If the expiration period is zero or it is not specified,
37+ a link has the unlimited lifetime.
38+
39+ Configuration example for server side.
3640
3741location ^~ /files/ {
38- secure_link $arg_st,$arg_e;
39- secure_link_hmac_secret my_secret_key$arg_e;
40- secure_link_hmac_message $uri;
42+
43+ # Variable to be passed are secure token, timestamp, expiration period (optional)
44+ secure_link $arg_st,$arg_ts,$arg_e;
45+
46+ # Secret key
47+ secure_link_hmac_secret my_secret_key;
48+
49+ # Message to be verified
50+ secure_link_hmac_message $uri$arg_ts$arg_e;
51+
52+ # Cryptographic hash function to be used
4153 secure_link_hmac_algorithm sha256;
4254
43- if ( $secure_link = "") {
44- return 403;
45- }
55+ # If the hash is incorrect then $secure_link is a null string.
56+ # If the hash is correct but the link has already expired then $secure_link is zero.
57+ # If the hash is correct and the link has not expired then $secure_link is one.
4658
47- if ($secure_link = "0") {
48- return 410;
59+ # In production environment, we should not reveal to potential attacker
60+ # why hmac authentication has failed
61+ if ($secure_link != "1") {
62+ return 404;
4963 }
5064
51- rewrite ^/files/(.$ )$ /files/$1 break;
65+ rewrite ^/files/(.* )$ /files/$1 break;
5266}
5367
54- Application side should use a standard hash_hmac function to generate
55- hash, which then needs to be base64 encoded. Example in PHP
68+ Application side should use a standard hash_hmac function to generate hash, which
69+ then needs to be base64url encoded. Example in Perl below.
70+
71+ # Variable $data contains secure token, timestamp in ISO 8601 format, and expiration
72+ # period in seconds
73+ perl_set $secure_token '
74+ sub {
75+ use Digest::SHA qw(hmac_sha256_base64);
76+ use POSIX qw(strftime);
77+
78+ my $now = time();
79+ my $tz = strftime("%z", localtime($now));
80+ $tz =~ s/(\d{2})(\d{2})/$1:$2/;
81+ my $timestamp = strftime("%Y-%m-%dT%H:%M:%S", localtime($now)) . $tz;
82+ my $expire = 60;
83+ my $key = "my_very_secret_key";
84+ my $r = shift;
85+ my $data = $r->uri;
86+ my $digest = hmac_sha256_base64($data . $timestamp . $expire, $key);
87+ $digest =~ tr(+/)(-_);
88+ $data = "st=" . $digest . "&ts=" . $timestamp . "&e=" . $expire;
89+ return $data;
90+ }
91+ ';
92+
93+ A similar function in PHP
5694
57- $expire = time() + 3600;
58- $secret = "my_secret_key" . $expire;
95+ $timestamp = date("c");
96+ $expire = 60;
97+ $secret = "my_very_secret_key";
5998 $algo = "sha256";
60- $path = "/files/top_secret.pdf";
61- $hashmac = base64_encode(hash_hmac($algo,$path,$secret,true));
99+
100+ $stringtosign = "/files/top_secret.pdf" . $timestamp . $expire;
101+
102+ $hashmac = base64_encode(hash_hmac($algo,$stringtosign,$secret,true));
62103 $hashmac = strtr($hashmac,"+/","-_"));
63104 $hashmac = str_replace("=","",$hashmac);
64105 $host = $_SERVER['HTTP_HOST'];
65- $loc = "https://" . $host . "/files/top_secret.pdf" . "?st=" . $hashmac . "&e=" . $expire;
106+ $loc = "https://" . $host . "/files/top_secret.pdf" . "?st=" . $hashmac . "&ts=" . $timestamp . "&e=" . $expire;
107+
108+ It is also possible to use this module with a Nginx acting as proxy server.
109+
110+ The string to be signed is defined in secure_link_hmac_message, the secure_link_token
111+ variable contains then a secure token to be passed to backend server.
112+
113+ location ^~ /backend_location/ {
114+ set $expire 60;
115+
116+ secure_link_hmac_message $uri$time_iso8601$expire;
117+ secure_link_hmac_secret "my_very_secret_key";
118+ secure_link_hmac_algorithm sha256;
119+
120+ proxy_pass http://backend_server_ip_$uri?st=$secure_link_token&ts=$time_iso8601&e=$expire;
121+ }
122+
66123
67124Contributing:
68125--
0 commit comments