{"id":28396214,"url":"https://github.com/ssbc/ssb-ephemeral-keys","last_synced_at":"2026-03-14T22:37:55.559Z","repository":{"id":33921921,"uuid":"159536363","full_name":"ssbc/ssb-ephemeral-keys","owner":"ssbc","description":"Methods for encrypting messages with ephemeral keys over Secure Scuttlebutt ","archived":false,"fork":false,"pushed_at":"2022-12-02T21:40:30.000Z","size":380,"stargazers_count":3,"open_issues_count":6,"forks_count":0,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-06-09T15:53:58.474Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ssbc.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-11-28T17:02:02.000Z","updated_at":"2023-07-19T22:21:02.000Z","dependencies_parsed_at":"2023-01-15T03:22:19.025Z","dependency_job_id":null,"html_url":"https://github.com/ssbc/ssb-ephemeral-keys","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/ssbc/ssb-ephemeral-keys","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ssbc%2Fssb-ephemeral-keys","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ssbc%2Fssb-ephemeral-keys/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ssbc%2Fssb-ephemeral-keys/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ssbc%2Fssb-ephemeral-keys/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ssbc","download_url":"https://codeload.github.com/ssbc/ssb-ephemeral-keys/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ssbc%2Fssb-ephemeral-keys/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":260090059,"owners_count":22957173,"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":"2025-05-31T21:37:25.776Z","updated_at":"2026-03-14T22:37:50.525Z","avatar_url":"https://github.com/ssbc.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\nScuttlebot plugin for sending messages using ephemeral keys over Secure Scuttlebutt\n\n**Warning:** This is an experimental module, use at your own risk\n\n## Why? \n\nScuttlebutt messages cannot be deleted.  But sometimes we might want to send information to someone which we don't want to leave in the logs indefinitely, regardless of whether it is encrypted.  This is to give 'forward security' to account for the situation that a private key might be compromised in the future.\n\nThis module provides a way to do this by creating keypairs which are used just once for a specific message and can then be deleted. \n\n## Example - bob sends a message to alice\n\n```js\nvar sbot = require('scuttlebot')\n  .use(require('ssb-ephemeral-keys'))  \n  .call(null, config)\n\nconst contextMessage = 'alice and bob' // this is included in the shared secret\n\n// alice does this:\nconst dbKey = 'message from bob'\n\nsbot.ephemeral.generateAndStore(dbKey, (err, pk) =\u003e {\n  // she sends the public key, pk, in a request to bob\n\n  // bob does this using the public key from alice:\n  const message = 'its nice to be important but its more important to be nice'\n  sbot.ephemeral.boxMessage(message, pk, contextMessage, (err, boxedMsg) =\u003e {\n\n    // he sends the encrypted message, boxedMsg, to alice\n\n    // alice decrypts the message like this:\n    sbot.ephemeral.unBoxMessage(dbKey, boxedMsg, contextMessage, (err, msg) =\u003e {\n\n      // after reading the message, msg, she deletes it's keypair and it is gone forever...    \n      sbot.ephemeral.deleteKeyPair(dbKey, (err) =\u003e {\n      })\n    })\n  })\n})\n```\n\nNote that both alice and bob must use the same context message.\n\n## API\n\n### `generateAndStore(databaseKey, callback)` (async)\n\nThis function will generate a keypair, store the secret key\nto disk, indexed by the given database key and return\nthe public key to be included in a request in the callback.\n\ndatabaseKey may be a string or an object\n\n### `boxMessage(message, recipientPublicKey, contextMessage, cb)` (async)\n\nThis function will generate a keypair, encrypt a given shard to\na given ephemeral public key, delete the generated private key, \nand return the encrypted message encoded as a base64 string in the callback.\n \nThe context message is a string which is added to the shared\nsecret so that it may only be used for a specific purpose.\n\n### `unBoxMessage(databaseKey, encryptedMessage, contextMessage, callback)` (async)\n\nThis function will grab a stored secret key from disk using the\ngiven database key, use it to decrypt a given message and return the\nresult in the callback.\n\nThe context message is a string which is added to the shared\nsecret so that it may only be used for a specific purpose.\n\ndatabaseKey may be a string or an object\n\n### `deleteKeyPair(databaseKey, callback)` (async)\n\nThis function will delete a keyPair identified by the given database key\n\ndatabaseKey may be a string or an object\n\n## Security Review\n\nFirst an ephemeral key is generated, and stored on the local system for later, under an arbitrary\nkey that the user selects. (since ssb is a async system for non-realtime communication it's necessary to store the ephemeral keys)\n\nAll keys are `curve25519` type.\n\n### Encryption\n\nA `message` is encrypted to a `recipientEphemeralKey` with a `contextMessage`.\nThe `contextMessage` serves to prevent ephemeral messages intended for one purpose\nunusable for another purpose. A 24 byte random `nonce` is generated.\n\nA `singleUseKey` is generated just for encrypting this message. A shared secret is generated,\nvia\n\n```\n// interpret + as concatinate.\nsharedSecret = hash(\n  singleUseKey.public +\n  recipientEphemeralKey.public +\n  contextMessage +\n  hash(scalarmult(singleUseKey.private, recipientEphemeralKey.public)\n)\n```\n\nthen that is used to encrypt the message:\n\n``` js\ncyphertext = secretbox(message, nonce, sharedSecret)\n```\n\nThe `sharedSecret` and `singleUseKey` are zerod,\nand `nonce + singeUseKey.public + cyphertext` is returned.\n\n### Decryption\n\nThe user has to know which stored ephemeral key is to be used.\nProbably the stored key should be identified with a message id,\nsince they will need to post it to another peer so that they may encrypt to it.\n\nTo decrypt, the user receives\n\n``` js\n  ephemeral_message = nonce + singeUseKey.public + cyphertext\n```\nthat is parsed, and from their stored ephemeralKey, (the `recipientEphemeralKey` that was sent to)\nthey reconstruct the shared secret,\n\n``` js\nsharedSecret = hash(\n  singleUseKey.public +\n  recipientEphemeralKey.public +\n  contextMessage +\n  hash(scalarmult(recipientEphemeralKey.private, singleUseKey.public)\n)\n```\nand then that is used to decrypt the key.\n\n### Comments on security\n\nAlthough there is nothing wrong with the crypto operations used in this library,\nIt only solves half the problem, and leaves quite a bit of the responsibility of\nimplementing a secure system to the application which uses it. That is to say,\nit's would be easy for the application to screw things up. For example,\nby not deleting the key, or reusing the key too many times.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fssbc%2Fssb-ephemeral-keys","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fssbc%2Fssb-ephemeral-keys","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fssbc%2Fssb-ephemeral-keys/lists"}