UNPKG

ssb-keyring

Version:

A persistence store for encryption keys for scuttlebutt. It's purpose is to make easy to answer box2 encryption/ decryption questions.

109 lines (93 loc) 2.56 kB
const pull = require('pull-stream') const { read } = require('pull-level') const { directMessageKey } = require('ssb-private-group-keys') const bfe = require('ssb-bfe') const URI = require('ssb-uri2') const { keySchemes } = require('private-group-spec') function normalise (id) { if (id.startsWith('@')) return URI.fromFeedSigil(id) else return id } function getDbId (myId, theirId) { return normalise(myId) + '<>' + normalise(theirId) } const DM_KEYS = 'dm' module.exports = function DirectMessage (db) { // This map contains two schemas: // * `myLeafId<>theirLeafId` => directMessageKey // * `xRootId<>yLeafId` => xLeafId let cache = new Map() const api = { load (cb) { readPersisted((err, pairs) => { if (err) return cb(err) cache = new Map(pairs) cb(null) }) }, add (myId, theirId, myDhKeys, theirDhKeys, cb) { if (!cache) throw new Error('keyring not ready') const dbId = getDbId(myId, theirId) if (cache.has(dbId)) { if (cb) cb() return false } const x = { dh: myDhKeys.toBFE(), id: bfe.encode(myId) } const y = { dh: theirDhKeys.toBFE(), id: bfe.encode(theirId) } const dmKey = directMessageKey( x.dh.secret, x.dh.public, x.id, y.dh.public, y.id ) dmKey.scheme = keySchemes.feed_id_metafeed_dm cache.set(dbId, dmKey) db.put([DM_KEYS, dbId], dmKey, cb) return true }, addTriangle (xRootId, xLeafId, yLeafId, cb) { if (!cache) throw new Error('keyring not ready') const dbId = getDbId(xRootId, yLeafId) if (cache.has(dbId)) { if (cb) cb() return false } xLeafId = normalise(xLeafId) cache.set(dbId, xLeafId) db.put([DM_KEYS, dbId], xLeafId, cb) return true }, get (myId, theirId) { const dbId = getDbId(myId, theirId) return cache.get(dbId) }, triangulate (xRootId, yLeafId) { const dbId = getDbId(xRootId, yLeafId) return cache.get(dbId) }, has (myId, theirId) { const dbId = getDbId(myId, theirId) return cache.has(dbId) } } return api function readPersisted (cb) { pull( read(db, { gt: [DM_KEYS, null], lt: [DM_KEYS + '~', undefined] }), pull.map(({ key, value: info }) => { return [normalise(key[1]), info] }), pull.collect((err, pairs) => { if (err) return cb(err) cb(null, pairs) }) ) } }