{"id":13607221,"url":"https://github.com/SocketDev/wormhole-crypto","last_synced_at":"2025-04-12T11:31:47.460Z","repository":{"id":41956576,"uuid":"358381069","full_name":"SocketDev/wormhole-crypto","owner":"SocketDev","description":"Streaming encryption for Wormhole.app, based on Encrypted Content-Encoding for HTTP (RFC 8188)","archived":false,"fork":false,"pushed_at":"2023-02-18T18:08:35.000Z","size":61,"stargazers_count":627,"open_issues_count":11,"forks_count":42,"subscribers_count":13,"default_branch":"master","last_synced_at":"2025-04-11T22:45:58.345Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","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/SocketDev.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":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2021-04-15T20:13:35.000Z","updated_at":"2025-04-07T05:54:35.000Z","dependencies_parsed_at":"2024-01-14T06:21:59.426Z","dependency_job_id":"ef9dd075-02c0-488f-8eb6-b81804b659a3","html_url":"https://github.com/SocketDev/wormhole-crypto","commit_stats":{"total_commits":51,"total_committers":5,"mean_commits":10.2,"dds":0.5882352941176471,"last_synced_commit":"c25a0d91e1d5df33b1ce64a6bedf5ca746b0cdde"},"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SocketDev%2Fwormhole-crypto","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SocketDev%2Fwormhole-crypto/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SocketDev%2Fwormhole-crypto/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SocketDev%2Fwormhole-crypto/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/SocketDev","download_url":"https://codeload.github.com/SocketDev/wormhole-crypto/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248560168,"owners_count":21124605,"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":[],"created_at":"2024-08-01T19:01:16.651Z","updated_at":"2025-04-12T11:31:46.539Z","avatar_url":"https://github.com/SocketDev.png","language":"JavaScript","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"readme":"# wormhole-crypto \n\n[![Socket Badge](https://socket.dev/api/badge/npm/package/wormhole-crypto)](https://socket.dev/npm/package/wormhole-crypto)\n[![ci][ci-image]][ci-url] [![npm][npm-image]][npm-url] [![downloads][downloads-image]][downloads-url] [![javascript style guide][standard-image]][standard-url]\n\n[ci-image]: https://img.shields.io/github/workflow/status/SocketDev/wormhole-crypto/ci/master\n[ci-url]: https://github.com/SocketDev/wormhole-crypto/actions\n[npm-image]: https://img.shields.io/npm/v/wormhole-crypto.svg\n[npm-url]: https://npmjs.org/package/wormhole-crypto\n[downloads-image]: https://img.shields.io/npm/dm/wormhole-crypto.svg\n[downloads-url]: https://npmjs.org/package/wormhole-crypto\n[standard-image]: https://img.shields.io/badge/code_style-standard-brightgreen.svg\n[standard-url]: https://standardjs.com\n\n### Streaming encryption for Wormhole.app, based on [Encrypted Content-Encoding for HTTP (RFC 8188)](https://tools.ietf.org/html/rfc8188)\n\nThis package is used by [Wormhole.app](https://wormhole.app).\n\n## Install\n\n```bash\nnpm install wormhole-crypto\n```\n\n## Usage\n\nHere's a quick example of how to use this package to turn a plaintext WHATWG\nreadable stream into an encrypted stream.\n\n```js\nimport { Keychain } from 'wormhole-crypto'\n\n// Create a new keychain. Since no arguments are specified, the key and salt\n// are generated.\nconst keychain = new Keychain()\n\n// Get a WHATWG stream somehow, from fetch(), from a Blob(), etc.\nconst stream = getStream()\n\n// Create an encrypted version of that stream\nconst encryptedStream = await keychain.encryptStream(stream)\n\n// Normally you'd now use `encryptedStream`, e.g. in fetch(), etc.\n// However, for this example, we'll just decrypt the stream immediately\nconst plaintextStream = await keychain.decryptStream(encryptedStream)\n\n// Now, you can use `plaintextStream` and it will be identical to if you had\n// used `stream`.\n```\n\n## API\n\n### `new Keychain([key, [salt]])`\n\nType: `Class`\n\nReturns: `Keychain`\n\nCreate a new keychain object. The keychain can be used to create encryption streams, decryption streams, and to encrypt or decrypt a \"metadata\" buffer.\n\n#### `key`\n\nType: `Uint8Array | string | null`\n\nDefault: `null`\n\nThe main key. This should be 16 bytes in length. If a `string` is given,\nthen it should be a base64-encoded string. If the argument is `null`, then a\nkey will be automatically generated.\n\n#### `salt`\n\nType: `Uint8Array | string | null`\n\nDefault: `null`\n\nThe salt. This should be 16 bytes in length. If a `string` is given,\nthen it should be a base64-encoded string. If this argument is `null`, then a\nsalt will be automatically generated.\n\n### `keychain.key`\n\nType: `Uint8Array`\n\nThe main key.\n\n### `keychain.keyB64`\n\nType: `string`\n\nThe main key as a base64-encoded string.\n\n### `keychain.salt`\n\nType: `Uint8Array`\n\nThe salt.\n\nImplementation note: The salt is used to derive the (internal) metadata key and\nauthentication token.\n\n### `keychain.saltB64`\n\nType: `string`\n\nThe salt as a base64-encoded string.\n\n### `keychain.authToken()`\n\nType: `Function`\n\nReturns: `Promise[Uint8Array]`\n\nReturns a `Promise` which resolves to the authentication token. By default, the\nauthentication token is automatically derived from the main key using\nHKDF SHA-256.\n\nIn Wormhole, the authentication token is used to communicate with the server and\nprove that the client has permission to fetch data for a room. Without a valid\nauthentication token, the server will not return the encrypted room metadata or\nallow downloading the encrypted file data.\n\nSince the authentication token is derived from the main key, the client presents\nit to the Wormhole server as a \"reader token\" to prove that it is in possession\nof the main key without revealing the main key to the server.\n\nFor destructive operations, like modifying the room, the client instead presents\na \"writer token\", which is not derived from the main key but is provided by the\nserver to the room creator who overrides the keychain authentication token by\ncalling `keychain.setAuthToken(authToken)` with the \"writer token\".\n\n### `keychain.authTokenB64()`\n\nType: `Function`\n\nReturns: `Promise[string]`\n\nReturns a `Promise` that resolves to the authentication token as a\nbase64-encoded string.\n\n### `keychain.authHeader()`\n\nType: `Function`\n\nReturns: `Promise[string]`\n\nReturns a `Promise` that resolves to the HTTP header value to be provided to the\nWormhole server. It contains the authentication token.\n\n### `keychain.setAuthToken(authToken)`\n\nType: `Function`\n\nReturns: `undefined`\n\nUpdate the keychain authentication token to `authToken`.\n\n#### `authToken`\n\nType: `Uint8Array | string | null`\n\nDefault: `null`\n\nThe authentication token. This should be 16 bytes in length. If a `string` is\ngiven, then it should be a base64-encoded string. If this argument is `null`,\nthen an authentication token will be automatically generated.\n\n### `keychain.encryptStream(stream)`\n\nType: `Function`\n\nReturns: `Promise[ReadableStream]`\n\nReturns a `Promise` that resolves to a `ReadableStream` encryption stream that\nconsumes the data in `stream` and returns an encrypted version. Data is\nencrypted with [Encrypted Content-Encoding for HTTP (RFC 8188)](https://tools.ietf.org/html/rfc8188).\n\n#### `stream`\n\nType: `ReadableStream`\n\nA WHATWG readable stream used as a data source for the encrypted stream.\n\n### `keychain.decryptStream(encryptedStream)`\n\nType: `Function`\n\nReturns: `Promise[ReadableStream]`\n\nReturns a `Promise` that resolves to a `ReadableStream` decryption stream that\nconsumes the data in `encryptedStream` and returns a plaintext version.\n\n### `keychain.decryptStreamRange(offset, length, totalEncryptedLength)`\n\nType: `Function`\n\nReturns: `Promise[{ ranges, decrypt }]`\n\nReturns a `Promise` that resolves to a object containing `ranges`, which is an array of\nobjects containing `offset` and `length` integers specifying the encrypted byte ranges\nthat are needed to decrypt the client's specified range, and a `decrypt` function.\n\nOnce the client has gathered a stream for each byte range in `ranges`, the client\nshould call `decrypt(streams)`, where `streams` is an array of `ReadableStream` objects,\none for each of the requested ranges. `decrypt` will then return a `ReadableStream`\ncontaining the plaintext data for the client's desired byte range.\n\n#### `encryptedStream`\n\nType: `ReadableStream`\n\nA WHATWG readable stream used as a data source for the plaintext stream.\n\n### `keychain.encryptMeta(meta)`\n\nType: `Function`\n\nReturns: `Promise[Uint8Array]`\n\nReturns a `Promise` that resolves to an encrypted version of `meta`. The\nmetadata is encrypted with AES-GCM.\n\nImplementation note: The metadata key is automatically derived from the main\nkey using HKDF SHA-256. The value is not user-controlled.\n\nImplementation note: The initialization vector (IV) is automatically generated\nand included in the encrypted output. No need to generate it or to manage it\nseparately from the encrypted output.\n\n#### `meta`\n\nType: `Uint8Array`\n\nThe metadata buffer to encrypt.\n\n### `keychain.decryptMeta(encryptedMeta)`\n\nType: `Function`\n\nReturns: `Promise[Uint8Array]`\n\nReturns a `Promise` that resolves to a decrypted version of `encryptedMeta`.\n\n#### `encryptedMeta`\n\nType: `Uint8Array`\n\nThe encrypted metadata buffer to decrypt.\n\n### `plaintextSize(encryptedSize)`\n\nType: `Function`\n\nReturns: `Number`\n\nGiven an encrypted size, return the corresponding plaintext size.\n\n### `encryptedSize(plaintextSize)`\n\nType: `Function`\n\nReturns: `Number`\n\nGiven a plaintext size, return the corresponding encrypted size.\n\n## License\n\nMIT. Copyright (c) [Socket Inc](https://socket.dev)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FSocketDev%2Fwormhole-crypto","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FSocketDev%2Fwormhole-crypto","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FSocketDev%2Fwormhole-crypto/lists"}