{"id":28958789,"url":"https://github.com/hanadalee/ngx_http_auth_hash_module","last_synced_at":"2025-06-23T23:32:23.970Z","repository":{"id":298341165,"uuid":"918711166","full_name":"HanadaLee/ngx_http_auth_hash_module","owner":"HanadaLee","description":"Secure Link Hash module for NGINX.","archived":false,"fork":false,"pushed_at":"2025-06-10T15:11:37.000Z","size":20,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-06-10T16:36:25.025Z","etag":null,"topics":["nginx","nginx-module"],"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/HanadaLee.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,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-01-18T16:54:57.000Z","updated_at":"2025-06-10T15:24:59.000Z","dependencies_parsed_at":null,"dependency_job_id":"b8086327-9fed-42af-8b5b-825dfa00a7e1","html_url":"https://github.com/HanadaLee/ngx_http_auth_hash_module","commit_stats":null,"previous_names":["hanadalee/ngx_http_auth_hash_module"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/HanadaLee/ngx_http_auth_hash_module","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HanadaLee%2Fngx_http_auth_hash_module","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HanadaLee%2Fngx_http_auth_hash_module/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HanadaLee%2Fngx_http_auth_hash_module/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HanadaLee%2Fngx_http_auth_hash_module/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/HanadaLee","download_url":"https://codeload.github.com/HanadaLee/ngx_http_auth_hash_module/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HanadaLee%2Fngx_http_auth_hash_module/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":261575298,"owners_count":23179491,"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":["nginx","nginx-module"],"created_at":"2025-06-23T23:30:42.879Z","updated_at":"2025-06-23T23:32:23.957Z","avatar_url":"https://github.com/HanadaLee.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"Nginx Secure Link HASH Module\n=============================\n\nDescription:\n============\n\nThe Nginx secure link HASH module enhances the security and functionality of the standard secure link module.\nSecure token is created using secure HASH 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\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_auth_hash_module\n\nDynamic nginx module `ngx_http_auth_hash_module.so` module\n\n    ./configure --with-compat --add-dynamic-module=/absolute/path/to/ngx_http_auth_hash_module\n\nBuild Nginx\n\n    make\n    make install\n\nUsage:\n======\n\nMessage to be hashed is defined by `auth_hash_message`, `secret_key` is given by `auth_hash_secret`, and hashing algorithm H is defined by `auth_hash_algorithm`.\n\nFor improved security, the time or a timestamp (depending on the date format specified by format parameter) should be appended to the message to be hashed.\n\nIt is possible to create links with limited lifetime. This is defined by optional parameters range_start or range_end. If the expiration period is not specified, a link has the unlimited lifetime.\n\nConfiguration example for server side.\n\n```nginx\nlocation ^~ /files/ {\n    # Enables the feature, if disabled, $auth_hash will always be empty\n    auth_hash on;\n\n    # Set the time value used for checking.\n    # You can set the expiration time range, the format of the time value, and the time zone of the time value\n    auth_hash_check_time $arg_ts range_end=$arg_e format=%s;\n\n    # Set the token value used for checking\n    # Available formats are hex (default), base64, base64url and bin\n    auth_hash_check_token $arg_st format=hex;\n\n    # Secret key\n    auth_hash_secret \"my_secret_key\";\n\n    # Message to be verified\n    auth_hash_message \"$uri|$arg_ts|$arg_e|$auth_hash_secret\";\n\n    # Cryptographic hash function to be used\n    auth_hash_algorithm sha256;\n\n    # In production environment, we should not reveal to potential attacker\n    # why hash authentication has failed\n    # - If the hash is incorrect then $auth_hash is a NULL string.\n    # - If the hash is correct and the link has not expired then $auth_hash is \"1\".\n    if ($auth_hash != \"1\") {\n        return 403;\n    }\n\n    rewrite ^/files/(.*)$ /files/$1 break;\n}\n```\n\nApplication side should use a standard hash function to generate hash, which then needs to be hex or 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(sha256_base64);\n        use POSIX qw(strftime);\n\n        my $now = time();\n        my $secret = \"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\n        # hex\n        my $string_to_hash = $data . \"|\" . $timestamp . \"|\" . $expire . \"|\" . $secret;\n        my $digest_binary = sha256($string_to_hash);\n        my $digest = unpack(\"H*\", $digest_binary);\n\n        # base64url\n        # my $digest = sha256_base64($data . \"|\" . $timestamp . \"|\" . $expire . \"|\" . $secret);\n        # $digest =~ tr/+/_/;\n        # $digest =~ s/=+$//;\n\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}|{$secret}\";\n// hex\n$hash = bin2hex(hash($algo, $stringtosign, true));\n// base64url\n// $hash = base64_encode(hash($algo, $stringtosign, true));\n// $hash = strtr($hash, '+/', '-_');\n// $hash = str_replace('=', '', $hash);\n$host = $_SERVER['HTTP_HOST'];\n$loc = \"https://{$host}/files/top_secret.pdf?st={$hash}\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}|${secret}`;\n// hex\nconst hash = crypto.createHash('sha256').update(stringToSign).digest('hex')\n// base64url\n// const hash = crypto.createHash('sha256').update(stringToSign).digest('base64')\n//       .replace(/=/g, '')\n//       .replace(/\\+/g, '-')\n//       .replace(/\\//g, '_');\nconst loc = `https://host/files/top_secret.pdf?st=${hash}\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|$SECRET\"\n# hex\nTOKEN=\"$(echo -n $ST | openssl dgst -sha256 | awk '{print $1}')\"\n# Base64url\n# TOKEN=\"$(echo -n $ST | openssl dgst -sha256 -binary | openssl base64 | tr +/ -_ | tr -d =)\"\n\necho \"http://127.0.0.1$URL?st=$TOKEN\u0026ts=$TIME_STAMP\u0026e=$EXPIRES\"\n```\n\nEmbedded Variables\n==================\n* `$auth_hash` - If the hash is correct and the link has not expired then $auth_hash is \"1\". Otherwise, it is null.\n* `$auth_hash_secret` - The value of the auth_hash_secret directive \n\n\nContributing:\n=============\n\nGit source repositories: http://github.com/hanadalee/ngx_http_auth_hash_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%2Fhanadalee%2Fngx_http_auth_hash_module","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhanadalee%2Fngx_http_auth_hash_module","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhanadalee%2Fngx_http_auth_hash_module/lists"}