Skip to content

Commit c7240fc

Browse files
Ununniliumdenji
authored andcommitted
Added support for Unix Timestamp (#9)
1 parent b0072cf commit c7240fc

File tree

2 files changed

+65
-41
lines changed

2 files changed

+65
-41
lines changed

README.md

+16-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ Usage:
3636

3737
Message to be hashed is defined by `secure_link_hmac_message`, `secret_key` is given by `secure_link_hmac_secret`, and hashing algorithm H is defined by `secure_link_hmac_algorithm`.
3838

39-
For improved security the timestamp in ISO 8601 format should be appended to the message to be hashed.
39+
For improved security the timestamp in ISO 8601 the format `2017-12-08T07:54:59+00:00` (one possibility according to ISO 8601) or as `Unix Timestamp` should be appended to the message to be hashed.
4040

4141
It is possible to create links with limited lifetime. This is defined by an optional parameter. If the expiration period is zero or it is not specified, a link has the unlimited lifetime.
4242

@@ -111,6 +111,21 @@ $host = $_SERVER['HTTP_HOST'];
111111
$loc = "https://{$host}/files/top_secret.pdf?st={$hashmac}&ts={$timestamp}&e={$expire}";
112112
```
113113

114+
Using Unix timestamp in Node.js
115+
116+
```javascript
117+
const crypto = require("crypto");
118+
const secret = 'my_very_secret_key';
119+
const expire = 60;
120+
const unixTimestamp = Math.round(Date.now() / 1000.);
121+
const stringToSign = `/files/top_secret.pdf${unixTimestamp}${expire}`;
122+
const hashmac = crypto.createHmac('sha256', secret).update(stringToSign).digest('base64')
123+
.replace(/=/g, '')
124+
.replace(/\+/g, '-')
125+
.replace(/\//g, '_');
126+
const loc = `https://host/files/top_secret.pdf?st=${hashmac}&ts=${unixTimestamp}&e=${expire}`;
127+
```
128+
114129
It is also possible to use this module with a Nginx acting as proxy server.
115130

116131
The string to be signed is defined in `secure_link_hmac_message`, the `secure_link_hmac_token` variable contains then a secure token to be passed to backend server.

ngx_http_hmac_secure_link_module.c

+49-40
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ ngx_http_secure_link_variable(ngx_http_request_t *r,
124124
u_char hash_buf[EVP_MAX_MD_SIZE], hmac_buf[EVP_MAX_MD_SIZE];
125125
u_int hmac_len;
126126
time_t timestamp, expires, gmtoff;
127+
unsigned long long conv_timestamp;
127128
int year, month, mday, hour, min, sec, gmtoff_hour, gmtoff_min;
128129
char gmtoff_sign;
129130

@@ -156,50 +157,58 @@ ngx_http_secure_link_variable(ngx_http_request_t *r,
156157
"secure link timestamp: \"%*s\"",
157158
sizeof("1970-09-28T12:00:00+06:00")-1, p);
158159

159-
/* Parse timestamp in ISO8601 format */
160-
if (sscanf((char *)p, "%4d-%02d-%02dT%02d:%02d:%02d%c%02i:%02i",
161-
(ngx_tm_year_t *) &year, (ngx_tm_mon_t *) &month,
162-
(ngx_tm_mday_t *) &mday, (ngx_tm_hour_t *) &hour,
163-
(ngx_tm_min_t *) &min, (ngx_tm_sec_t *) &sec,
164-
&gmtoff_sign, &gmtoff_hour, &gmtoff_min) < 9) {
165-
goto not_found;
166-
}
160+
/* Try if p is UNIX timestamp*/
161+
if (sscanf((char *)p, "%llu", &conv_timestamp) == 1) {
162+
timestamp = (time_t)conv_timestamp;
167163

168-
/* Put February last because it has leap day */
169-
month -= 2;
170-
if (month <= 0) {
171-
month += 12;
172-
year -= 1;
173-
}
164+
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
165+
"secure link timestamp: \"%T\"", timestamp);
166+
} else {
167+
/* Parse timestamp in ISO8601 format */
168+
if (sscanf((char *)p, "%4d-%02d-%02dT%02d:%02d:%02d%c%02i:%02i",
169+
(ngx_tm_year_t *) &year, (ngx_tm_mon_t *) &month,
170+
(ngx_tm_mday_t *) &mday, (ngx_tm_hour_t *) &hour,
171+
(ngx_tm_min_t *) &min, (ngx_tm_sec_t *) &sec,
172+
&gmtoff_sign, &gmtoff_hour, &gmtoff_min) < 9) {
173+
goto not_found;
174+
}
174175

175-
/* Gauss' formula for Gregorian days since March 1, 1 BC */
176-
/* Taken from ngx_http_parse_time.c */
177-
timestamp = (time_t) (
178-
/* days in years including leap years since March 1, 1 BC */
179-
365 * year + year / 4 - year / 100 + year / 400
180-
/* days before the month */
181-
+ 367 * month / 12 - 30
182-
/* days before the day */
183-
+ mday - 1
184-
/*
185-
* 719527 days were between March 1, 1 BC and March 1, 1970,
186-
* 31 and 28 days were in January and February 1970
187-
*/
188-
- 719527 + 31 + 28) * 86400 + hour * 3600 + min * 60 + sec;
189-
190-
/* Determine the time offset with respect to GMT */
191-
gmtoff = 3600 * gmtoff_hour + 60 * gmtoff_min;
192-
193-
if (gmtoff_sign == '+') {
194-
timestamp -= gmtoff;
195-
}
176+
/* Put February last because it has leap day */
177+
month -= 2;
178+
if (month <= 0) {
179+
month += 12;
180+
year -= 1;
181+
}
196182

197-
if (gmtoff_sign == '-') {
198-
timestamp += gmtoff;
199-
}
183+
/* Gauss' formula for Gregorian days since March 1, 1 BC */
184+
/* Taken from ngx_http_parse_time.c */
185+
timestamp = (time_t) (
186+
/* days in years including leap years since March 1, 1 BC */
187+
365 * year + year / 4 - year / 100 + year / 400
188+
/* days before the month */
189+
+ 367 * month / 12 - 30
190+
/* days before the day */
191+
+ mday - 1
192+
/*
193+
* 719527 days were between March 1, 1 BC and March 1, 1970,
194+
* 31 and 28 days were in January and February 1970
195+
*/
196+
- 719527 + 31 + 28) * 86400 + hour * 3600 + min * 60 + sec;
197+
198+
/* Determine the time offset with respect to GMT */
199+
gmtoff = 3600 * gmtoff_hour + 60 * gmtoff_min;
200+
201+
if (gmtoff_sign == '+') {
202+
timestamp -= gmtoff;
203+
}
200204

201-
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
202-
"secure link timestamp: \"%T\"", timestamp);
205+
if (gmtoff_sign == '-') {
206+
timestamp += gmtoff;
207+
}
208+
209+
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
210+
"secure link timestamp: \"%T\"", timestamp);
211+
}
203212

204213
if (timestamp <= 0) {
205214
goto not_found;

0 commit comments

Comments
 (0)