@@ -27,42 +27,99 @@ make install
27
27
Usage:
28
28
--
29
29
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.
34
34
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.
36
40
37
41
location ^~ /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
41
53
secure_link_hmac_algorithm sha256;
42
54
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.
46
58
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;
49
63
}
50
64
51
- rewrite ^/files/(.$ )$ /files/$1 break;
65
+ rewrite ^/files/(.* )$ /files/$1 break;
52
66
}
53
67
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
56
94
57
- $expire = time() + 3600;
58
- $secret = "my_secret_key" . $expire;
95
+ $timestamp = date("c");
96
+ $expire = 60;
97
+ $secret = "my_very_secret_key";
59
98
$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));
62
103
$hashmac = strtr($hashmac,"+/","-_"));
63
104
$hashmac = str_replace("=","",$hashmac);
64
105
$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
+
66
123
67
124
Contributing:
68
125
--
0 commit comments