{"id":13697819,"url":"https://github.com/nginx-modules/ngx_http_hmac_secure_link_module","last_synced_at":"2025-06-12T20:03:36.411Z","repository":{"id":15913967,"uuid":"18655654","full_name":"nginx-modules/ngx_http_hmac_secure_link_module","owner":"nginx-modules","description":"HMAC Secure Link module for NGINX.","archived":false,"fork":false,"pushed_at":"2023-05-27T22:08:16.000Z","size":43,"stargazers_count":70,"open_issues_count":3,"forks_count":20,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-06-12T20:03:07.470Z","etag":null,"topics":["authentication","blake2","expiration-period","gost","hash","hashing-algorithm","hmac","iso-8601","legacy","lifetime","module","nginx","openssl","rfc-2104","security","sha3","sha512","sm3","timestamp","unix-timestamp"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"unlicense","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nginx-modules.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2014-04-10T23:32:09.000Z","updated_at":"2025-05-30T14:39:11.000Z","dependencies_parsed_at":"2024-03-31T23:44:25.294Z","dependency_job_id":null,"html_url":"https://github.com/nginx-modules/ngx_http_hmac_secure_link_module","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/nginx-modules/ngx_http_hmac_secure_link_module","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nginx-modules%2Fngx_http_hmac_secure_link_module","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nginx-modules%2Fngx_http_hmac_secure_link_module/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nginx-modules%2Fngx_http_hmac_secure_link_module/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nginx-modules%2Fngx_http_hmac_secure_link_module/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nginx-modules","download_url":"https://codeload.github.com/nginx-modules/ngx_http_hmac_secure_link_module/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nginx-modules%2Fngx_http_hmac_secure_link_module/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":259521513,"owners_count":22870446,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["authentication","blake2","expiration-period","gost","hash","hashing-algorithm","hmac","iso-8601","legacy","lifetime","module","nginx","openssl","rfc-2104","security","sha3","sha512","sm3","timestamp","unix-timestamp"],"created_at":"2024-08-02T18:01:03.325Z","updated_at":"2025-06-12T20:03:36.368Z","avatar_url":"https://github.com/nginx-modules.png","language":"C","funding_links":[],"categories":["Third Modules"],"sub_categories":["C Modules"],"readme":"Nginx HMAC Secure Link Module\n=============================\n\nDescription:\n============\n\nThe Nginx HMAC secure link module enhances the security and functionality of the standard secure link module.  \nSecure token is created using secure HMAC construction with an arbitrary hash algorithm supported by OpenSSL, e.g.:\n`blake2b512`, `blake2s256`, `gost`, `md4`, `md5`, `mdc2`, `rmd160`, `sha1`, `sha224`, `sha256`,\n`sha3-224`, `sha3-256`, `sha3-384`, `sha3-512`, `sha384`, `sha512`, `sha512-224`, `sha512-256`, `shake128`, `shake256`, `sm3`.\n\nFurthermore, secure token is created as described in RFC2104, that is,\n`H(secret_key XOR opad,H(secret_key XOR ipad, message))` instead of a simple `MD5(secret_key,message, expire)`.\n\nInstallation:\n=============\n\nYou'll need to re-compile Nginx from source to include this module.  \nModify your compile of Nginx by adding the following directive (modified to suit your path of course):\n\nStatic module (built-in nginx binary)\n\n    ./configure --add-module=/absolute/path/to/ngx_http_hmac_secure_link_module\n\nDynamic nginx module `ngx_http_hmac_secure_link_module.so` module\n\n    ./configure --with-compat --add-dynamic-module=/absolute/path/to/ngx_http_hmac_secure_link_module\n\nBuild Nginx\n\n    make\n    make install\n\nUsage:\n======\n\nMessage 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`.\n\nFor 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.\n\nIt 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.\n\nConfiguration example for server side.\n\n```nginx\nlocation ^~ /files/ {\n    # Variable to be passed are secure token, timestamp, expiration period (optional)\n    secure_link_hmac \"$arg_st,$arg_ts,$arg_e\";\n\n    # Secret key\n    secure_link_hmac_secret \"my_secret_key\";\n\n    # Message to be verified\n    secure_link_hmac_message \"$uri|$arg_ts|$arg_e\";\n\n    # Cryptographic hash function to be used\n    secure_link_hmac_algorithm sha256;\n\n    # In production environment, we should not reveal to potential attacker\n    # why hmac authentication has failed\n    # - If the hash is incorrect then $secure_link_hmac is a NULL string.\n    # - If the hash is correct but the link has already expired then $secure_link_hmac is \"0\".\n    # - If the hash is correct and the link has not expired then $secure_link_hmac is \"1\".\n    if ($secure_link_hmac != \"1\") {\n        return 404;\n    }\n\n    rewrite ^/files/(.*)$ /files/$1 break;\n}\n```\n\nApplication side should use a standard hash_hmac function to generate hash, which then needs to be base64url encoded. Example in Perl below.\n\n#### Variable $data contains secure token, timestamp in ISO 8601 format, and expiration period in seconds\n\n```nginx\nperl_set $secure_token '\n    sub {\n        use Digest::SHA qw(hmac_sha256_base64);\n        use POSIX qw(strftime);\n\n        my $now = time();\n        my $key = \"my_very_secret_key\";\n        my $expire = 60;\n        my $tz = strftime(\"%z\", localtime($now));\n        $tz =~ s/(\\d{2})(\\d{2})/$1:$2/;\n        my $timestamp = strftime(\"%Y-%m-%dT%H:%M:%S\", localtime($now)) . $tz;\n        my $r = shift;\n        my $data = $r-\u003euri;\n        my $digest = hmac_sha256_base64($data . \"|\" . $timestamp . \"|\" . $expire,  $key);\n        $digest =~ tr(+/)(-_);\n        $data = \"st=\" . $digest . \"\u0026ts=\" . $timestamp . \"\u0026e=\" . $expire;\n        return $data;\n    }\n';\n```\n\nA similar function in PHP\n\n```php\n$secret = 'my_very_secret_key';\n$expire = 60;\n$algo = 'sha256';\n$timestamp = date('c');\n$unixtimestamp = time();\n$stringtosign = \"/files/top_secret.pdf|{$unixtimestamp}|{$expire}\";\n$hashmac = base64_encode(hash_hmac($algo, $stringtosign, $secret, true));\n$hashmac = strtr($hashmac, '+/', '-_');\n$hashmac = str_replace('=', '', $hashmac);\n$host = $_SERVER['HTTP_HOST'];\n$loc = \"https://{$host}/files/top_secret.pdf?st={$hashmac}\u0026ts={$unixtimestamp}\u0026e={$expire}\";\n```\n\nUsing Unix timestamp in Node.js\n\n```javascript\nconst crypto = require(\"crypto\");\nconst secret = 'my_very_secret_key';\nconst expire = 60;\nconst unixTimestamp = Math.round(Date.now() / 1000.);\nconst stringToSign = `/files/top_secret.pdf|${unixTimestamp}|${expire}`;\nconst hashmac = crypto.createHmac('sha256', secret).update(stringToSign).digest('base64')\n      .replace(/=/g, '')\n      .replace(/\\+/g, '-')\n      .replace(/\\//g, '_');\nconst loc = `https://host/files/top_secret.pdf?st=${hashmac}\u0026ts=${unixTimestamp}\u0026e=${expire}`;\n```\n\nBash version\n\n```shell\n#!/bin/bash\n\nSECRET=\"my_super_secret\"\nTIME_STAMP=\"$(date -d \"today + 0 minutes\" +%s)\";\nEXPIRES=\"3600\"; # seconds\nURL=\"/file/my_secret_file.txt\"\nST=\"$URL|$TIME_STAMP|$EXPIRES\"\nTOKEN=\"$(echo -n $ST | openssl dgst -sha256 -hmac $SECRET -binary | openssl base64 | tr +/ -_ | tr -d =)\"\n\necho \"http://127.0.0.1$URL?st=$TOKEN\u0026ts=$TIME_STAMP\u0026e=$EXPIRES\"\n```\n\nIt is also possible to use this module with a Nginx acting as proxy server.\n\nThe 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.\n\n```nginx\nlocation ^~ /backend_location/ {\n    set $expire 60;\n\n    secure_link_hmac_message \"$uri|$time_iso8601|$expire\";\n    secure_link_hmac_secret \"my_very_secret_key\";\n    secure_link_hmac_algorithm sha256;\n\n    proxy_pass \"http://backend_server$uri?st=$secure_link_hmac_token\u0026ts=$time_iso8601\u0026e=$expire\";\n}\n```\n\n\nEmbedded Variables\n==================\n* `$secure_link_hmac` -\n* `$secure_link_hmac_token` -\n* `$secure_link_hmac_expires` - The lifetime of a link passed in a request.\n\n\nContributing:\n=============\n\nGit source repositories: http://github.com/nginx-modules/ngx_http_hmac_secure_link_module/tree/master\n\nPlease feel free to fork the project at GitHub and submit pull requests or patches.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnginx-modules%2Fngx_http_hmac_secure_link_module","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnginx-modules%2Fngx_http_hmac_secure_link_module","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnginx-modules%2Fngx_http_hmac_secure_link_module/lists"}