{"id":15390233,"url":"https://github.com/gajus/sguid","last_synced_at":"2025-04-15T21:26:58.973Z","repository":{"id":57357467,"uuid":"80725511","full_name":"gajus/sguid","owner":"gajus","description":"Signed Globally Unique Identifier (SGUID) generator.","archived":false,"fork":false,"pushed_at":"2022-09-08T16:29:40.000Z","size":14,"stargazers_count":34,"open_issues_count":2,"forks_count":4,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-04-14T02:49:51.120Z","etag":null,"topics":["guid","security","signing"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gajus.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}},"created_at":"2017-02-02T13:06:01.000Z","updated_at":"2024-01-14T14:25:22.000Z","dependencies_parsed_at":"2022-09-26T16:33:13.098Z","dependency_job_id":null,"html_url":"https://github.com/gajus/sguid","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gajus%2Fsguid","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gajus%2Fsguid/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gajus%2Fsguid/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gajus%2Fsguid/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gajus","download_url":"https://codeload.github.com/gajus/sguid/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249156091,"owners_count":21221710,"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":["guid","security","signing"],"created_at":"2024-10-01T15:05:02.294Z","updated_at":"2025-04-15T21:26:58.955Z","avatar_url":"https://github.com/gajus.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# SGUID\n\n[![Travis build status](http://img.shields.io/travis/gajus/sguid/master.svg?style=flat-square)](https://travis-ci.org/gajus/sguid)\n[![Coveralls](https://img.shields.io/coveralls/gajus/sguid.svg?style=flat-square)](https://coveralls.io/github/gajus/sguid)\n[![NPM version](http://img.shields.io/npm/v/sguid.svg?style=flat-square)](https://www.npmjs.org/package/sguid)\n[![Canonical Code Style](https://img.shields.io/badge/code%20style-canonical-blue.svg?style=flat-square)](https://github.com/gajus/canonical)\n[![Twitter Follow](https://img.shields.io/twitter/follow/kuizinas.svg?style=social\u0026label=Follow)](https://twitter.com/kuizinas)\n\nSigned Globally Unique Identifier (SGUID) generator.\n\n* [Implementation](#implementation)\n* [Use case](#use-case)\n* [API](#api)\n* [Usage](#Usage)\n* [Generating key pair](#generating-key-pair)\n\n## Implementation\n\n* SGUID uses [Ed25519 public-key signature system](https://github.com/dchest/tweetnacl-js/blob/master/README.md#signatures).\n* The resulting signature is encoded using URL-safe base64 encoding.\n\n## Use case\n\nSGUID is used to mitigate certain types of DDoS attacks.\n\n* [Protecting APIs from the DDoS attacks by signing the resource identifiers](https://medium.com/@gajus/protecting-apis-from-the-ddos-attacks-by-signing-the-pks-c1eca7cc7725#.7b5czcv5h)\n\n## API\n\n```js\ntype SguidPayloadType = {|\n  id: number | string,\n  namespace: string,\n  type: string\n|};\n\n/**\n* @throws InvalidSguidError Throws if signed message cannot be opened.\n* @throws UnexpectedNamespaceValueError Throws if the namespace contained in the payload does not match the expected namespace.\n* @throws UnexpectedResourceTypeNameValueError Throws if the resource type name contained in the payload does not match the expected resource type name.\n*/\ntype FromSguidType = (publicKey: string, expectedNamespace: string, expectedResourceTypeName: string, sguid: string) =\u003e SguidPayloadType;\n\n/**\n * @param secretKey {@see https://github.com/gajus/sguid#generating-secret-key}\n * @param namespace A namespace of the GUID (e.g. company name or the application name).\n * @param type A resource type name (e.g. article).\n * @param id Resource identifier.\n */\ntype ToSguidType = (secretKey: string, namespace: string, type: string, id: number | string) =\u003e string;\n\n```\n\n## Usage\n\n```js\nimport {\n  fromSguid,\n  toSguid,\n} from 'sguid';\n\nconst secretKey = '6h2K+JuGfWTrs5Lxt+mJw9y5q+mXKCjiJgngIDWDFy23TWmjpfCnUBdO1fDzi6MxHMO2nTPazsnTcC2wuQrxVQ==';\nconst publicKey = 't01po6Xwp1AXTtXw84ujMRzDtp0z2s7J03AtsLkK8VU=';\nconst namespace = 'gajus';\nconst resourceTypeName = 'article';\nconst resourceIdentifier = 1;\n\nconst sguid = toSguid(secretKey, namespace, resourceTypeName, resourceIdentifier);\n\n// \"pbp3h9nTr0wPboKaWrg_Q77KnZW1-rBkwzzYJ0Px9Qvbq0KQvcfuR2uCRCtijQYsX98g1F50k50x5YKiCgnPAnsiaWQiOjEsIm5hbWVzcGFjZSI6ImdhanVzIiwidHlwZSI6ImFydGljbGUifQ\"\n\nconst payload = fromSguid(publicKey, namespace, resourceTypeName, sguid);\n\n// {\n//   \"id\": 1,\n//   \"namespace\": \"gajus\",\n//   \"type\": \"article\"\n// }\n\n```\n\n\n## Handling errors\n\n`fromSguid` method can throw the following errors.\n\n|Error constructor name|Description|\n|---|---|\n|`InvalidSguidError`|Throws if signed message cannot be opened.|\n|`UnexpectedNamespaceValueError`|Throws if the namespace contained in the payload does not match the expected namespace.|\n|`UnexpectedResourceTypeNameValueError`|Throws if the resource type name contained in the payload does not match the expected resource type name.|\n\nError constructors can be imported from `sguid` package.\n\n`UnexpectedNamespaceValueError` and `UnexpectedResourceTypeNameValueError` extend from `InvalidSguidError`. It is enough to check if an error object is an instance of `InvalidSguidError` to assert that an error is a result of an invalid SGUID.\n\n```js\nimport {\n  fromSguid,\n  InvalidSguidError\n} from 'sguid';\n\ntry {\n  fromSguid(initializationVectorValue, namespace, resourceTypeName, sguid);\n} catch (error) {\n  if (error instanceof InvalidSguidError) {\n    // Handle error.\n  }\n\n  // Re-throw other errors.\n  throw error;\n}\n\n```\n\n## Generating key pair\n\nSguid provides a CLI utility `sguid new-key-pair` to generate a key pair\n\n```bash\n$ npm install sguid -g\n$ sguid new-key-pair\n```\n\nIf you need to generate the key pair programmatically, use [`nacl.sign.keyPair()`](https://github.com/dchest/tweetnacl-js/blob/master/README.md#naclsignkeypair).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgajus%2Fsguid","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgajus%2Fsguid","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgajus%2Fsguid/lists"}