Browse Source

first stab at secure bogbook (sbb)

english
Ev Bogue 3 years ago
parent
commit
1d11adf294
  1. 87
      bog.js
  2. 89
      gossip.js
  3. 1
      index.html
  4. 17
      package-lock.json
  5. 1
      package.json
  6. 86
      server.js
  7. 6
      views.js

87
bog.js

@ -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
}
}

89
gossip.js

@ -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())
})
}
}
})

1
index.html

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

17
package-lock.json generated

@ -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",

1
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",

86
server.js

@ -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 })
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 */)
})
}
}
var wserve = new WS.Server({ port: 8080 })
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))
})
})
})
})

6
views.js

@ -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 () {

Loading…
Cancel
Save