npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

ssb-ephemeral-keys

v1.0.2

Published

Functions for storing and using ephemeral keys on Secure Scuttlebutt

Downloads

2

Readme

Scuttlebot plugin for sending messages using ephemeral keys over Secure Scuttlebutt

Warning: This is an experimental module, use at your own risk

Why?

Scuttlebutt 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.

This module provides a way to do this by creating keypairs which are used just once for a specific message and can then be deleted.

Example - bob sends a message to alice

var sbot = require('scuttlebot')
  .use(require('ssb-ephemeral-keys'))  
  .call(null, config)

const contextMessage = 'alice and bob' // this is included in the shared secret

// alice does this:
const dbKey = 'message from bob'

sbot.ephemeral.generateAndStore(dbKey, (err, pk) => {
  // she sends the public key, pk, in a request to bob

  // bob does this using the public key from alice:
  const message = 'its nice to be important but its more important to be nice'
  sbot.ephemeral.boxMessage(message, pk, contextMessage, (err, boxedMsg) => {

    // he sends the encrypted message, boxedMsg, to alice

    // alice decrypts the message like this:
    sbot.ephemeral.unBoxMessage(dbKey, boxedMsg, contextMessage, (err, msg) => {

      // after reading the message, msg, she deletes it's keypair and it is gone forever...    
      sbot.ephemeral.deleteKeyPair(dbKey, (err) => {
      })
    })
  })
})

Note that both alice and bob must use the same context message.

API

generateAndStore(databaseKey, callback) (async)

This function will generate a keypair, store the secret key to disk, indexed by the given database key and return the public key to be included in a request in the callback.

databaseKey may be a string or an object

boxMessage(message, recipientPublicKey, contextMessage, cb) (async)

This function will generate a keypair, encrypt a given shard to a given ephemeral public key, delete the generated private key, and return the encrypted message encoded as a base64 string in the callback.

The context message is a string which is added to the shared secret so that it may only be used for a specific purpose.

unBoxMessage(databaseKey, encryptedMessage, contextMessage, callback) (async)

This function will grab a stored secret key from disk using the given database key, use it to decrypt a given message and return the result in the callback.

The context message is a string which is added to the shared secret so that it may only be used for a specific purpose.

databaseKey may be a string or an object

deleteKeyPair(databaseKey, callback) (async)

This function will delete a keyPair identified by the given database key

databaseKey may be a string or an object

Security Review

First an ephemeral key is generated, and stored on the local system for later, under an arbitrary key that the user selects. (since ssb is a async system for non-realtime communication it's necessary to store the ephemeral keys)

All keys are curve25519 type.

Encryption

A message is encrypted to a recipientEphemeralKey with a contextMessage. The contextMessage serves to prevent ephemeral messages intended for one purpose unusable for another purpose. A 24 byte random nonce is generated.

A singleUseKey is generated just for encrypting this message. A shared secret is generated, via

// interpret + as concatinate.
sharedSecret = hash(
  singleUseKey.public +
  recipientEphemeralKey.public +
  contextMessage +
  hash(scalarmult(singleUseKey.private, recipientEphemeralKey.public)
)

then that is used to encrypt the message:

cyphertext = secretbox(message, nonce, sharedSecret)

The sharedSecret and singleUseKey are zerod, and nonce + singeUseKey.public + cyphertext is returned.

Decryption

The user has to know which stored ephemeral key is to be used. Probably the stored key should be identified with a message id, since they will need to post it to another peer so that they may encrypt to it.

To decrypt, the user receives

  ephemeral_message = nonce + singeUseKey.public + cyphertext

that is parsed, and from their stored ephemeralKey, (the recipientEphemeralKey that was sent to) they reconstruct the shared secret,

sharedSecret = hash(
  singleUseKey.public +
  recipientEphemeralKey.public +
  contextMessage +
  hash(scalarmult(recipientEphemeralKey.private, singleUseKey.public)
)

and then that is used to decrypt the key.

Comments on security

Although there is nothing wrong with the crypto operations used in this library, It only solves half the problem, and leaves quite a bit of the responsibility of implementing a secure system to the application which uses it. That is to say, it's would be easy for the application to screw things up. For example, by not deleting the key, or reusing the key too many times.