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-validate

v4.1.4

Published

simplified validation for secure-scuttlebutt

Downloads

474

Readme

ssb-validate

validate ssb messages, completely functionally.

this module seeks to replace ssb-feed, and contain the logic to validate ssb messages, but this is implemented functionally, with serializable state. this means, that the states generated when the reference implementation runs can be extracted and used as test cases in other implementations.

example

var validate = require('ssb-validate')
var hmac_key = null
var state = validate.initial()

var msgs = [...] //some source of messages

msgs.forEach(function (msg) {
  try {
    state = validate.append(state, hmac_key, msg)
  } catch (err) {
    console.log(err)
  }
})

writeToDatabase(state.queue, function (err) {
  if(err) throw err

  //these messages are fully accepted now, can remove them from state.
  state.queue = []
})

//state should be saved in some way it can be reconstructed
//so in the future it can be appended to starting from scratch.

architecture

This module describes the validation logic for ssb messages, using a reduce style pattern - state = method(state, argument) . To make it easy to test, the various subcomponents are also exported, but the main method is state = append(state, hmac_key, msg)

state

this module uses a data structure to represent the state of validation. The structure is as follows:

{
  validated: integer,
  queued: integer,
  queue: [kvt...], //messages which have been validated and may now be written to database
  feeds: { //validation state of all feeds
    <feed_id>: {
      id: <msgId: key of last message>,
      timestamp: <timestamp of last message>,
      sequence: integer //
      queue: [kvt...]
    },...
  }
}

note: kvt here represents a msg with key calculated and a recieved timestamp assigned {key: hash(msg), value: msg, timestamp: timestamp()}

api

state = validate.append(state, hmac_key, msg)

Append and validate a message to state. If the message is valid, it will appear at the end of state.queue it may now be written to the database.

hmac_key is optional - if provided, messages are hmac'd with it before signing, which can be used to create a separate network in which messages cannot be copied to the main network. Messages compatible with the main network have hmac_key = null

msg = validate.create(feed_state, keys, hmac_key, content, timestamp)

Create a message that is valid given the current state of the feed (such that it may be passed to append(state, hmac_key, msg). keys is the signing key, as provided by ssbKeys.generate() or ssbKeys.createOrLoadSync(filename)

msg_id = validate.id(msg)

Calculate the message id for a given message.

shortcuts for js mode api

In investigating the possiblity of an entirely web based scuttlebutt, verifying all signatures in javascript had added a lot of overhead. (although now this is not such a problem because of crypto in fast-enough webassembly)

The following methods queues some number of messages and then validates the last signature. It is possible that a specially constructed messages with some invalid signatures, followed by messages with valid signatures could get accepted, but the writer doesn't have any way to know which messages will be accepted, and a 3rd party could not insert invalid messages into another feed, because the signature that is eventually checked wouldn't point to the right previous hash.

However, you can probably consider these methods not necessary. And they could be removed.

var validate = require('ssb-validate')
var hmac_key = null
var state = validate.initial()

var msgs = [...] //some source of messages

//queue messages
msgs.forEach(function (msg) {
  state = validate.queue(state, msg)
  if(state.error) console.error(state.error)
})

//validate messages

for(var feed_id in state.feeds)
  state = validate.validate(state, hmac_key, feed_id)

writeToDatabase(state.queue, function (err) {
  if(err) throw err

  //these messages are fully accepted now, can remove them from state.
  state.queue = []
})

//state should be saved in some way it can be reconstructed
//so in the future it can be appended to starting from scratch.

state = validate.queue(state, msg)

Call checkInvalidCheap and if valid, append to the feed's incoming queue. (state.feeds[id(msg)].queue)

The message is checked to have an incrementing sequence, and correct previous hash, but signature is not checked. (the intention here is for when using javascript crypto, checking every signature is expensive) however, this is not a big problem with wasm crypto.

state = validate.validate(state, feed_id)

Check the signature of the last message in feed_id's incoming queue, and if it is valid, append all messages in that queue. As optimization/shortcut for javascript crypto.

state = validate.appendOOO(state, hmac_key, msg)

This method works the same as append except that it does not check the previous link of the message. This allows one to validate an out of order message or a row of messages not starting from the beginning.

internal api

The following methods are exposed for testing, but are unlikely to be used directly.

state = validate.appendNew(state,hmac_key, keys, content, timestamp)

Wrapper around create and append. used in testing.

state = validate.appendKVT (state, hmac_key, kvt)

Internal details of append - recently this was refactored to avoid calculating the message id twice.

isInvalid = validate.checkInvalidCheap (state, msg)

Perform cheap checks for message validity, but not the signature. return false if the message is valid, and an error (with message) if it's invalid.

isInvalid = validate.checkInvalid (state, hmac_key, msg)

Check signature, returns false if message is valid. returns an error (with message) if the message is invalid.

License

MIT