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.

75 lines (65 loc) 2.05 kB
const pull = require('pull-stream') const { read } = require('pull-level') const { toBuffer, isPOBoxId } = require('../util') const POBOX = 'pobox' module.exports = function POBox (db, dm) { let cache // Map: groupId => group.info const api = { load (cb) { readPersisted((err, map) => { if (err) return cb(err) cache = map cb(null) }) }, add (poBoxId, info, cb) { if (!cache) throw new Error('keyring not ready') if (cache.has(poBoxId)) { if (cb) cb() return false } if (!isPOBoxId(poBoxId)) return cb(new Error(`expected a poBoxId, got ${poBoxId}`)) if (!info.key) return cb(new Error('expected info.key')) // TODO <<< store public/secret keys in BFE format, along with ID in BFE format ??? try { // 32 bytes, where 32 === sodium-universal's crypto_scalarmult_SCALARBYTES info.key = toBuffer(info.key, 32) } catch (e) { return cb(e) } cache.set(poBoxId, info) db.put([POBOX, poBoxId, Date.now()], info, cb) return true // TODO store entity poBox is associated with too? // - groupId (so only reindex the group lobby feed? // - fusionId }, has (poboxId) { if (!cache) throw new Error('keyring not ready') return cache.has(poboxId) }, get (poboxId) { if (!cache) throw new Error('keyring not ready') return cache.get(poboxId) }, list () { if (!cache) throw new Error('keyring not ready') return Array.from(cache.keys()) } } return api function readPersisted (cb) { pull( read(db, { lt: [POBOX + '~', undefined, undefined], // "group~" is just above "group" in charwise sort gt: [POBOX, null, null] }), pull.map(({ key, value: info }) => { const [_, poBoxId, createdAt] = key // eslint-disable-line return [poBoxId, info] }), pull.collect((err, pairs) => { if (err) return cb(err) cb(null, new Map(pairs)) }) ) } }