diff options
| author | Ev Bogue <ev@evbogue.com> | 2019-09-03 11:30:06 -0500 | 
|---|---|---|
| committer | Ev Bogue <ev@evbogue.com> | 2019-09-03 11:30:06 -0500 | 
| commit | 1d11adf294433b1cf9a3376806d52fe6e1aea0bd (patch) | |
| tree | 761e8255f45591dafd7137c03f9e439a6bf0db57 | |
| parent | 3f1a179d003556d96b3bd9538ad65f5266bc7569 (diff) | |
first stab at secure bogbook (sbb)
| -rw-r--r-- | bog.js | 87 | ||||
| -rw-r--r-- | gossip.js | 89 | ||||
| -rw-r--r-- | index.html | 1 | ||||
| -rw-r--r-- | package-lock.json | 17 | ||||
| -rw-r--r-- | package.json | 1 | ||||
| -rw-r--r-- | server.js | 84 | ||||
| -rw-r--r-- | views.js | 6 | 
7 files changed, 115 insertions, 170 deletions
| @@ -1,3 +1,12 @@ + +// so bog.js works in node.js and the browser +if ((typeof process !== 'undefined') && (process.release.name === 'node')) { +  var fs = require('fs') +  var nacl = require('tweetnacl') +      nacl.util = require('tweetnacl-util') +  var ed2curve = require('ed2curve') +} +  // bog.open -- opens a signature and returns content if you pass a signature and a public key  // EX:  open(msg).then(content => { console.log(content) }) @@ -15,29 +24,64 @@ async function open (msg) {  // bog.keys -- gets your public/private keypair, generates one if there is none  // EX: keys().then(key => { console.log(key)}) -async function keys (key) {  -  var keypair = await localforage.getItem('id') -  if (keypair != null) { -    return keypair -  } else { + +function generatekey () { +  var keypair = { +    publicKey : '@/' +  } +  console.log('generating new keypair') +  while (keypair.publicKey.includes('/')) {      var genkey = nacl.sign.keyPair() -    var keypair = { -      publicKey: '@' + nacl.util.encodeBase64(genkey.publicKey), -      privateKey: nacl.util.encodeBase64(genkey.secretKey) -    } -    if (keypair.publicKey.includes('/')) { -      console.log('TRYING AGAIN') -      setTimeout(function () { -        location.reload() -      }, 10) +    keypair.publicKey = '@' + nacl.util.encodeBase64(genkey.publicKey), +    keypair.privateKey = nacl.util.encodeBase64(genkey.secretKey) +  } +  return keypair +} + +async function keys () { +  try { +    if (fs) { +      var keypair = JSON.parse(fs.readFileSync(__dirname + '/keypair'))      } else { -      localforage.setItem('id', keypair) +      var keypair = await localforage.getItem('id') +      if (keypair === null) { +        var keypair = generatekey() +        localforage.setItem('id', keypair) +      } +    } +  } catch (err) { +    var keypair = generatekey() +    if (fs) { +      fs.writeFileSync(__dirname + '/keypair', JSON.stringify(keypair), 'UTF-8')      } - -    return keypair     } +  return keypair +} + +// bog.box -- encrypts a message to a pubkey + +async function box (msg, recp, keys) { +  var nonce = nacl.randomBytes(nacl.box.nonceLength) +  var message = nacl.util.decodeUTF8(msg) +  var encrypted = nacl.box(message, nonce, ed2curve.convertPublicKey(nacl.util.decodeBase64(recp.substring(1))), ed2curve.convertSecretKey(nacl.util.decodeBase64(keys.privateKey))) +  var nonceMsg = nacl.util.encodeBase64(nonce) + nacl.util.encodeBase64(encrypted) +  return nonceMsg   } +//bog.unbox -- decrypts a message sent to our pubkey +async function unbox (boxed, sender, keys) { +  console.log(sender) +  console.log(keys.privateKey) +  console.log(boxed) +  var nonceMsg = nacl.util.decodeBase64(boxed) +  var nonce = nonceMsg.slice(0, nacl.box.nonceLength) +  var msg = nonceMsg.slice(nacl.box.nonceLength, nonceMsg.length) +  //var message = nacl.box.open(msg, nonce, ed2curve.convertPublicKey(sender.substring(1)), ed2curve.convertSecretKey(nacl.util.decodeBase64(keys.privateKey))) +  var message = nacl.box.open(msg, nonce, ed2curve.convertPublicKey(nacl.util.decodeBase64(sender.substring(1))), ed2curve.convertSecretKey(nacl.util.decodeBase64(keys.privateKey))) +  return message +} + +  // bog.get -- iterates over log and returns a post.  // EX: get('%x5T7KZ5haR2F59ynUuCggwEdFXlLHEtFoBQIyKYppZYerq9oMoIqH76YzXQpw2DnYiM0ugEjePXv61g3E4l/Gw==').then(msg => { console.log(msg)}) @@ -216,4 +260,11 @@ async function publish (post, keys, preview) {    }  } - +if ((typeof process !== 'undefined') && (process.release.name === 'node')) { +  module.exports = { +    keys, +    open, +    box, +    unbox +  } +} @@ -7,7 +7,7 @@ function sync (subs, keys) {        console.log(servers)        wsServers = servers      } else { -      servers = ['ws://localhost:8080/', 'ws://bogbook.com/'] +      servers = ['ws://localhost:8080/~@OXJ7Ma1eu8HOEakF+TW9yk1k09FbOqUSyMVneXWdLaM=']        localforage.setItem('pubs', servers)        console.log(servers)        wsServers = servers @@ -17,92 +17,33 @@ function sync (subs, keys) {        wsServers.forEach(function (server, index) {          setTimeout(function () {            console.log('SYNCING WITH: ' + server + ' to fetch ' + sub) -          var ws = new WebSocket(server + sub) +          var split = server.split('~') +          var serverurl = split[0] +          var serverpub = split[1] +          var ws = new WebSocket(serverurl)            bog(sub).then(srclog => {              if (srclog) {                open(srclog[0]).then(msg => { -                console.log(msg) -                var req = { -                  src: sub, -                  seq: msg.seq -                }                  ws.onopen = function () { -                  ws.send(JSON.stringify(req)) +                  var message = JSON.stringify(msg) +                  // if we have a log then send the latest log and see if we get anything back  +                  box(message, serverpub, keys).then(boxed => { +                    var obj = { +                      requester: keys.publicKey, +                      box: boxed +                    } +                    ws.send(JSON.stringify(obj)) +                  })                  }                  ws.onmessage = function (message) { -                  var serverMsg = JSON.parse(message.data) -                  if (msg.seq === serverMsg.seq) { -                  } else if (msg.seq > serverMsg.seq) { -                    var diff = msg.seq - serverMsg.seq -                    var sendlog = srclog.slice(0, diff) -                    var send = { -                      src: sub, -                      log: sendlog -                      //requester: keys.publicKey -                    } -                    ws.send(JSON.stringify(send)) -                  } else { -                    if (serverMsg.log) { -                      var scroller = document.getElementById('scroller') -                      var logFromServer = JSON.parse(message.data) -                      newlog = logFromServer.log - -                      bog().then(log => { -                        for (var i = newlog.length; i-- > 0; ) { -                          var pubkey = nacl.util.decodeBase64(newlog[i].author.substring(1)) -                          var sig = nacl.util.decodeBase64(newlog[i].signature) -                          var opened = JSON.parse(nacl.util.encodeUTF8(nacl.sign.open(sig, pubkey))) -                          log.unshift(opened) -                          opened.key = newlog[i].key -                          scroller.insertBefore(render(opened, keys), scroller.childNodes[2]) - -                          if (i === 0) { -                            console.log('saved log') -                            log.sort((a, b) => a.timestamp - b.timestamp) -                            localforage.setItem(sub, newlog.concat(srclog)) -                            localforage.setItem('log', log.reverse())  -                          } -                        } -                      })  -                    }          -                  }                  }                })              } else if (srclog === null) { -              var req = { -                src: sub, -                seq: null -              } -                ws.onopen = function () { -                ws.send(JSON.stringify(req)) +                console.log('NO LOG IN CLIENT')                }                ws.onmessage = function (message) { -                var openedlog = [] -                var scroller = document.getElementById('scroller') -                var logFromServer = JSON.parse(message.data) -                log = logFromServer.log - -                localforage.setItem(sub, log) - -                for (var i = log.length; i-- > 0; ) { -                  console.log(log[i]) -                  var pubkey = nacl.util.decodeBase64(log[i].author.substring(1)) -                  var sig = nacl.util.decodeBase64(log[i].signature) -                  var opened = JSON.parse(nacl.util.encodeUTF8(nacl.sign.open(sig, pubkey))) -                  console.log(opened) -                  opened.key = log[i].key -                  openedlog.push(opened) -                  scroller.insertBefore(render(opened, keys), scroller.childNodes[2]) -                } - -                bog().then(log => { -                  var newlog = openedlog.concat(log) -                  newlog.sort((a, b) => a.timestamp - b.timestamp) -                  localforage.setItem('log', newlog.reverse()) -                }) -                }              }            }) @@ -9,6 +9,7 @@    <body>      <script src="./lib/nacl.min.js"></script>      <script src="./lib/nacl-util.min.js"></script> +    <script src="./lib/ed2curve.min.js"></script>      <script src="./lib/localforage.min.js"></script>      <script src="./lib/diff.js"></script>      <script src="./lib/marked.min.js"></script> diff --git a/package-lock.json b/package-lock.json index c483e84..c2de81e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@  {    "name": "bogbook", -  "version": "1.3.0", +  "version": "1.4.0",    "lockfileVersion": 1,    "requires": true,    "dependencies": { @@ -27,6 +27,21 @@          "url-join": "^4.0.0"        }      }, +    "ed2curve": { +      "version": "0.2.1", +      "resolved": "https://registry.npmjs.org/ed2curve/-/ed2curve-0.2.1.tgz", +      "integrity": "sha1-Iuaqo1aePE2/Tu+ilhLsMp5YGQw=", +      "requires": { +        "tweetnacl": "0.x.x" +      }, +      "dependencies": { +        "tweetnacl": { +          "version": "0.14.5", +          "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", +          "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" +        } +      } +    },      "ee-first": {        "version": "1.1.1",        "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", diff --git a/package.json b/package.json index 0cc0d4f..7d83efc 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@    "license": "MIT",    "dependencies": {      "ecstatic": "^4.1.2", +    "ed2curve": "^0.2.1",      "open": "^6.2.0",      "tweetnacl": "^1.0.1",      "tweetnacl-util": "^0.15.0", @@ -12,81 +12,23 @@ open('http://localhost:8089')  // ws server (8080) -var WebSocket = require('ws') +var bog = require('./bog') +var WS = require('ws')  var fs = require('fs')  var nacl = require('tweetnacl')      nacl.util = require('tweetnacl-util') -var wserver = new WebSocket.Server({ port: 8080 }) +var wserve = new WS.Server({ port: 8080 }) -wserver.on('connection', function (ws) { -  ws.on('message', function (message) { -    var req = JSON.parse(message) -    if (req.seq) { -      if (fs.existsSync(__dirname + '/bogs/' + req.src)) { -        fs.readFile(__dirname + '/bogs/' + req.src, 'UTF-8', function (err, data) { -          if (data) { -            var log = JSON.parse(data) -            var pubkey = nacl.util.decodeBase64(req.src.substring(1)) -            var sig = nacl.util.decodeBase64(log[0].signature) -            var opened = JSON.parse(nacl.util.encodeUTF8(nacl.sign.open(sig, pubkey))) - -            var res = { -              feed: req.src, -              seq: opened.seq -            } -            ws.send(JSON.stringify(res)) -            if(res.seq > req.seq) { -              console.log('Sending diff of' + req.src /*+ ' to ' + req.requester*/) -              var diff = res.seq - req.seq -              var sendlog = log.slice(0, diff) -              var send = { -                src: req.src, -                log: sendlog -              } -              ws.send(JSON.stringify(send)) -            } -          } -        }) -      } else { -        var res = { -          feed: req.src, -          seq: null -        } -        ws.send(JSON.stringify(res)) -      } -    } else if (req.seq === null) { -      if (fs.existsSync(__dirname + '/bogs/' + req.src)) {  -        fs.readFile(__dirname + '/bogs/' + req.src, 'UTF-8', function (err, data) { -          var log = JSON.parse(data) -          var res = { -            src: req.src, -            log -          } -          console.log('Sending full log of ' + req.src /*+ ' to ' + req.requester*/ ) -          ws.send(JSON.stringify(res)) -        }) -      } -    } -    if (req.log) { -      if (fs.existsSync(__dirname + '/bogs/' + req.src)) { -        fs.readFile(__dirname + '/bogs/' + req.src, 'UTF-8', function (err, data) { -          var serverlog = JSON.parse(data) - -          var newlog = req.log.concat(serverlog) - -          fs.writeFile(__dirname + '/bogs/' + req.src, JSON.stringify(newlog), 'UTF-8', function (err, success) { -            console.log('Appending diff of ' + req.src /*+ ' from ' + req.requester + ' and saved to server'*/) -          }) - -        }) -      } else { -        fs.writeFile(__dirname + '/bogs/' + req.src, JSON.stringify(req.log), 'UTF-8', function (err, success) { -          if (err) throw err -          else -            console.log('Saved new log of ' + req.src /*+ ' that was sent from ' + req.requester */) -        }) -      } -    } +bog.keys().then(key => { +  wserve.on('connection', function (ws) { +    ws.on('message', function (message) { +      var req = JSON.parse(message) +      console.log(message) +      bog.unbox(req.box, req.requester, key).then(unboxed => { +        console.log(nacl.util.encodeUTF8(unboxed)) +      }) +    })    })  }) + @@ -85,12 +85,6 @@ function profilePage (src, keys) {      }    }) -  /*profile.appendChild(h('button', { -    onclick: function () { -      sync(src, keys) -    } -  }, ['Sync feed']))*/ -    profile.appendChild(h('button', {      onclick: function () {        localforage.removeItem(src).then(function () { | 
