{"id":13454512,"url":"https://github.com/auth70/paseto-ts","last_synced_at":"2025-03-24T05:34:01.487Z","repository":{"id":65330596,"uuid":"589680800","full_name":"auth70/paseto-ts","owner":"auth70","description":"PASETO v4 (encrypt, decrypt, sign \u0026 verify) in TypeScript","archived":false,"fork":false,"pushed_at":"2024-03-07T19:25:01.000Z","size":253,"stargazers_count":46,"open_issues_count":3,"forks_count":10,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-03-04T22:47:28.409Z","etag":null,"topics":["decrypt","encrypt","paseto","sign","verify"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/auth70.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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}},"created_at":"2023-01-16T17:25:47.000Z","updated_at":"2025-02-24T05:47:18.000Z","dependencies_parsed_at":"2024-03-07T20:30:44.411Z","dependency_job_id":"9253cc27-b225-4b51-a513-588b88c9f028","html_url":"https://github.com/auth70/paseto-ts","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/auth70%2Fpaseto-ts","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/auth70%2Fpaseto-ts/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/auth70%2Fpaseto-ts/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/auth70%2Fpaseto-ts/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/auth70","download_url":"https://codeload.github.com/auth70/paseto-ts/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245217433,"owners_count":20579291,"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":["decrypt","encrypt","paseto","sign","verify"],"created_at":"2024-07-31T08:00:54.859Z","updated_at":"2025-03-24T05:34:01.107Z","avatar_url":"https://github.com/auth70.png","language":"TypeScript","readme":"![Abacus crow](https://github.com/auth70/paseto-ts/assets/55932282/1fcc9bfd-937f-4892-8fa7-e82870d3ec56)\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/auth70/paseto-ts/actions\"\u003e\u003cimg src=\"https://img.shields.io/github/actions/workflow/status/auth70/paseto-ts/ci.yml?logo=github\" alt=\"build\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://www.npmjs.com/package/paseto-ts\"\u003e\u003cimg src=\"https://img.shields.io/npm/v/paseto-ts\" alt=\"npm\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://www.npmjs.com/package/paseto-ts\"\u003e\u003cimg src=\"https://img.shields.io/npm/types/paseto-ts\" alt=\"npm type definitions\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n# paseto-ts\n\n[PASETO](https://paseto.io) v4 implementation written in TypeScript. Does not require Node.js.\n\nThe code is well-documented and has 100% unit test coverage ensuring it conforms with the best practices laid out in the PASETO implementation guide.\n\nIf you are unfamiliar with PASETO, please see Okta's blog post [\"A Thorough Introduction to PASETO\"](https://developer.okta.com/blog/2019/10/17/a-thorough-introduction-to-paseto).\n\nThe only dependencies are the Blake2b, Ed25519 and XChaCha20 cryptographic primitives, which do not yet exist in the standard Web Crypto API, provided by [stablelib](https://www.stablelib.com). If you wish to use other primitives, feel free to fork the project and implement them; it should be straightforward.\n\n## Installation\n\n```bash\nnpm install --save paseto-ts\n```\n\n**This library is an ES Module! There is no commonjs target as of now. If you require one, feel free to make a pull request.** (tsconfig module/target ES2022)\n\n**Remember:** You need to put `\"type\": \"module\"` in your package.json to enable ESM in Node! If you are getting an export error, this is probably why.\n\n## Supported PASETO versions\n\nVersion     | Purpose\n------------|------------------------------------------------\n`v4.public` | Public-key signatures (`sign` and `verify`)\n`v4.local`  | Symmetric encryption (`encrypt` and `decrypt`)\n\n### Key formats\n\nThis library implements the `k4.local`, `k4.public` and `k4.secret` [PASERK](https://github.com/paseto-standard/paserk) compatible key formats. It does not accept arbitrary key data that is not scoped to a specific purpose. It also does not implement key wrapping or other PASERK features.\n\n## Usage\n\nThe package will not work in commonjs environments without a transpilation step. It has been tested in Node \u003e 16 and modern browsers. As it depends on the Web Crypto API being available, Deno and Bun should work, but are not tested.\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eNote on Node versions under 19\u003c/b\u003e\u003c/summary\u003e\nIf you encounter the error `crypto is not defined` using the `generateKeys` and `encrypt` functions, you need to pass an implementation of the `getRandomValues` function as an option. This is because Node versions under 19 do not have a global `crypto` object.\n\n```ts\nimport * as crypto from 'node:crypto';\nimport { generateKeys } from 'paseto-ts/v4';\n\nconst getRandomValues = (array: Uint8Array): Uint8Array =\u003e {\n    const bytes = crypto.randomBytes(array.length);\n    array.set(bytes);\n    return array;\n};\n\ngenerateKeys('local', { format: 'paserk', getRandomValues });\n```\n\u003c/details\u003e\n\n### Setting token expiry, issued at and not-before times\n\nWhen using the `encrypt` and `sign` functions, the `iat` *(issued at)* and `exp` *(expires at)* claims are added to your payload if they do not exist. By default, the `exp` claim will be set one hour in the future.\n\nYou can disable this behaviour by passing `addIat: false` and/or `addExp: false` as options to create tokens that do not expire.\n\n**You can provide an `exp` and `nbf` *(not before)* claim as a relative time**, e.g. `exp: \"1 hour\"` or `nbf: \"1 day\"`. The `iat` claim only accepts string-formatted ISO dates (e.g. `iat: \"2023-01-01T00:00:00Z\"`).\n\nRegistered claims will be validated against the spec. To disable this behaviour, pass `validatePayload: false` as an option.\n\n### JSON validation\n\nThis library conforms to the best practices laid out in the PASETO implementation guide regarding JSON parsing. It will throw an error if the payload or footer is not valid JSON, if the JSON is too deep or has too many keys. You can disable this behaviour by passing `maxDepth: 0` and/or `maxKeys: 0` to the options object.\n\n## Local (encryption and decryption)\n\n**You use the same key to encrypt and decrypt your message.**\n\nThe PASETO spec requires local and public keys to be separated. Therefore, to use the `encrypt` and `decrypt` functions in this library, `k4.local.` **must** be prepended to the key data to prevent accidental key sharing between local and public functions. Please refer to the table below:\n\n### Local key format\n\nType         | Expected format                                                  | Length\n-------------|------------------------------------------------------------------|------------------\n`PASERK`     | `k4.local.[key data as base64url]`                               | 52 characters\n`Uint8Array` | `[0x6b, 0x34, 0x2e, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x2e, ...key]` | 41 bytes\n\nThere is no functional difference between the two formats; if you are passing the key in from an environment variable, you may prefer to use `PASERK` format. If you are generating the key elsewhere, you may prefer to use `Uint8Array` and prepend the magic bytes yourself.\n\n#### Generate a local key\n\nYou can generate a local key in PASERK format using the `generateKeys` function:\n\n```ts\nimport { generateKeys } from 'paseto-ts/v4';\n\nconst localKey = generateKeys('local');\n// localKey: k4.local.xxx..\n```\n\nIf you need the key as a buffer, you can pass in `buffer` as the second argument:\n\n```ts\nimport { generateKeys } from 'paseto-ts/v4';\n\nconst localKeyBuffer = generateKeys('local', { format: 'buffer' });\n// localKeyBuffer: Uint8Array(41)\n```\n\n### Encrypt a payload\n\n```ts\nimport { encrypt } from 'paseto-ts/v4';\n\ntry {\n\n    const token = await encrypt(\n        // localKey = k4.local.xxx..\n        localKey, // string | Uint8Array\n        // payload = { sub: '1234567890', name: 'John Doe' }\n        payload, // Payload | string | Uint8Array\n        {\n            // Optional: If footer parses to an object, its `kid` and `wpk` claims will be validated.\n            footer, // Footer | string | Uint8Array\n            // Optional: Assertion is a JSON.stringifyable object, string or buffer.\n            assertion, // Assertion | string | Uint8Array\n            // Optional: If true, a default `exp` claim of 1 hour will be added to the payload.\n            addExp, // boolean; defaults to true\n            // Optional: If true, a default `iat` claim of the current time will be added to the payload.\n            addIat, // boolean; defaults to true\n            // Optional: Maximum depth of the JSON in the payload and footer objects (if footer parses to an object)\n            maxDepth, // number; defaults to 32. 0 to disable\n            // Optional: Maximum number of keys in the payload and footer objects (if footer parses to an object)\n            maxKeys, // number; defaults to 128. 0 to disable\n            // Optional: If true, the payload will be validated against the registered claims.\n            validatePayload, // boolean; defaults to true\n            // Optional: crypto.getRandomValues implementation (for Node \u003c 19)\n            getRandomValues, // (array: Uint8Array) =\u003e Uint8Array\n        }\n    );\n\n    // token: v4.local.xxx..\n\n} catch(err) {\n    // err: Error\n}\n```\n\n### Decrypt a token\n\n```ts\nimport { decrypt } from 'paseto-ts/v4';\n\ntry {\n\n    // generic type parameter is optional but will give you type safety on the payload\n    const { payload, footer } = await decrypt\u003c{ foo: string }\u003e( \n        // localKey = k4.local.xxx..\n        localKey, // string | Uint8Array\n        // token = v4.local.xxx..\n        token, // string | Uint8Array\n        {\n            // Optional: Assertion is a JSON.stringifyable object, string or buffer.\n            assertion, // Assertion | string | Uint8Array\n            // Optional: Maximum depth of the JSON in the payload and footer objects (if footer parses to an object)\n            maxDepth, // number; defaults to 32. 0 to disable\n            // Optional: Maximum number of keys in the payload and footer objects (if footer parses to an object)\n            maxKeys, // number; defaults to 128. 0 to disable\n            // Optional: If true, the payload will be validated against the registered claims.\n            validatePayload, // boolean; defaults to true\n        }\n    );\n\n    // payload: { sub: '1234567890', name: 'John Doe', iat: \"2023-01-01T00:00:00.000Z\" }\n    // footer: { kid: 'xxx..', wpk: 'xxx..' }\n\n} catch(err) {\n    // err: Error\n}\n```\n\n## Public (signing and verification)\n\n**You use a secret key to sign your payload, and a public key to verify the generated token.**\n\nThe PASETO spec dictates that you use Ed25519 keys, which are 64 bytes long. To use the `sign` and `verify` functions in this library, `k4.public.` **must** be prepended to the public key data and `k4.secret.` **must** be prepended to the secret key data to prevent accidental key sharing between local and public functions. Please refer to the table below:\n\n### Secret key format\n\nType | Expected format | Length\n-------------|------------------------------------------------------------------|-----------------\n`PASERK`     | `k4.secret.[key data as base64url]`                              | 96 characters\n`Uint8Array` | `[0x6b, 0x34, 0x2e, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, ...key]` | 41 bytes\n\n### Public key format\n\nType         | Expected format                                                  | Length\n-------------|------------------------------------------------------------------|---------------\n`PASERK`     | `k4.public.[key data as base64url]`                              | 53 characters\n`Uint8Array` | `[0x6b, 0x34, 0x2e, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, ...key]` | 41 bytes\n\n#### Generate a secret/public key pair\n\nYou can generate a public/secret key pair in PASERK format using the `generateKeys` function:\n\n```ts\nimport { generateKeys } from 'paseto-ts/v4';\n\nconst { secretKey, publicKey } = generateKeys('public');\n// secretKey: k4.secret.xxx..\n// publicKey: k4.public.xxx..\n```\n\nIf you need the keys as buffers, you can pass in `buffer` as the second argument:\n\n```ts\nimport { generateKeys } from 'paseto-ts/v4';\n\nconst { secretKey, publicKey } = generateKeys('public', { format: 'buffer' });\n// secretKey: Uint8Array(41)\n// publicKey: Uint8Array(41)\n```\n\n### Sign a payload\n\nYou can pass a `Payload` object, a `string` or an `Uint8Array` to the `sign` function. PASETO defines a set of [registered claims](https://github.com/paseto-standard/paseto-spec/blob/master/docs/02-Implementation-Guide/04-Claims.md#registered-claims) that you can use in your payload. Any registered claims are validated.\n\n```ts\nimport { sign } from 'paseto-ts/v4';\n\ntry {\n\n    const token = await sign(\n        // secretKey = k4.secret.xxx..\n        secretKey, // string | Uint8Array\n        // payload = { sub: '1234567890', name: 'John Doe' }\n        payload, // Payload | string | Uint8Array\n        {\n            // Optional: If footer parses to an object, its `kid` and `wpk` claims will be validated.\n            footer, // Footer | string | Uint8Array\n            // Optional: Assertion is a JSON.stringifyable object, string or buffer.\n            assertion, // Assertion | string | Uint8Array\n            // Optional: If true, a default `exp` claim of 1 hour will be added to the payload.\n            addExp, // boolean; defaults to true\n            // Optional: If true, a default `iat` claim of the current time will be added to the payload.\n            addIat, // boolean; defaults to true\n            // Optional: Maximum depth of the JSON in the payload and footer objects (if footer parses to an object)\n            maxDepth, // number; defaults to 32. 0 to disable\n            // Optional: Maximum number of keys in the payload and footer objects (if footer parses to an object)\n            maxKeys, // number; defaults to 128. 0 to disable\n            // Optional: If true, the payload will be validated against the registered claims.\n            validatePayload, // boolean; defaults to true\n        }\n    );\n\n    // token: v4.public.xxx..\n\n} catch(err) {\n    // err: Error\n}\n```\n\n### Verify a token\n\n```ts\nimport { verify } from 'paseto-ts/v4';\n\ntry {\n\n    // generic type parameter is optional but will give you type safety on the payload\n    const { payload, footer } = await verify\u003c{ foo: string }\u003e(  \n        // publicKey = k4.public.xxx..\n        publicKey, // string | Uint8Array\n        // token = v4.public.xxx..\n        token, // string | Uint8Array\n        {\n            // Optional: Assertion is a JSON.stringifyable object, string or buffer.\n            assertion, // Assertion | string | Uint8Array\n            // Optional: Maximum depth of the JSON in the payload and footer objects (if footer parses to an object)\n            maxDepth, // number; defaults to 32. 0 to disable\n            // Optional: Maximum number of keys in the payload and footer objects (if footer parses to an object)\n            maxKeys, // number; defaults to 128. 0 to disable\n            // Optional: If true, the payload will be validated against the registered claims.\n            validatePayload, // boolean; defaults to true\n        }\n    );\n\n    // payload: { sub: '1234567890', name: 'John Doe', iat: \"2023-01-01T00:00:00.000Z\" }\n    // footer: { kid: 'xxx..', wpk: 'xxx..' }\n\n} catch(err) {\n    // err: Error\n}\n```\n\n## Contributing\n\nPull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.\n\n## License\n\nMIT\n","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fauth70%2Fpaseto-ts","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fauth70%2Fpaseto-ts","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fauth70%2Fpaseto-ts/lists"}