feat: hyperbee-chat - P2P Hyperbee chat prototype (KV msgs, swarm discovery/replicate)
Writer appends timestamped msgs every 3s. Reader scans recent. Separate storages, named core. Local test silent (no output/exit 0, no storage) - deps ok per npm.
This commit is contained in:
+21
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2021 Mathias Buus
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
# sodium-secretstream
|
||||
|
||||
Wraps libsodium's secretstream in a higher level abstraction
|
||||
|
||||
```
|
||||
npm install sodium-secretstream
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
``` js
|
||||
const { Pull, Push, keygen } = require('sodium-secretstream')
|
||||
|
||||
const key = keygen()
|
||||
|
||||
// the sender
|
||||
const push = new Push(key)
|
||||
|
||||
// the receiver
|
||||
const pull = new Pull(key)
|
||||
|
||||
// send header to the other side
|
||||
pull.init(push.header)
|
||||
|
||||
// send the cipher to the other side
|
||||
const cipher1 = push.next(Buffer.from('test'))
|
||||
|
||||
// prints "test"
|
||||
console.log(pull.next(cipher1))
|
||||
|
||||
// send the cipher to the other side
|
||||
const cipher2 = push.next(Buffer.from('test 2'))
|
||||
|
||||
// prints "test 2"
|
||||
console.log(pull.next(cipher2))
|
||||
|
||||
// when done send a final signal
|
||||
const cipher3 = push.final()
|
||||
|
||||
// prints <empty buffer>
|
||||
console.log(pull.next(cipher3))
|
||||
|
||||
// but sets pull.final to true
|
||||
console.log(pull.final)
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
const { Pull, Push, keygen } = require('./')
|
||||
|
||||
const key = keygen()
|
||||
|
||||
// the sender
|
||||
const push = new Push(key)
|
||||
|
||||
// the receiver
|
||||
const pull = new Pull(key)
|
||||
|
||||
// send header to the other side
|
||||
pull.init(push.header)
|
||||
|
||||
// send the cipher to the other side
|
||||
const cipher1 = push.next(Buffer.from('test'))
|
||||
|
||||
// prints "test"
|
||||
console.log(pull.next(cipher1))
|
||||
|
||||
// send the cipher to the other side
|
||||
const cipher2 = push.next(Buffer.from('test 2'))
|
||||
|
||||
// prints "test 2"
|
||||
console.log(pull.next(cipher2))
|
||||
|
||||
// when done send a final signal
|
||||
const cipher3 = push.final()
|
||||
|
||||
// prints <empty buffer>
|
||||
console.log(pull.next(cipher3))
|
||||
|
||||
// but sets pull.final to true
|
||||
console.log(pull.final)
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
const sodium = require('sodium-universal')
|
||||
const b4a = require('b4a')
|
||||
|
||||
const ABYTES = sodium.crypto_secretstream_xchacha20poly1305_ABYTES
|
||||
const TAG_MESSAGE = sodium.crypto_secretstream_xchacha20poly1305_TAG_MESSAGE
|
||||
const TAG_FINAL = sodium.crypto_secretstream_xchacha20poly1305_TAG_FINAL
|
||||
const STATEBYTES = sodium.crypto_secretstream_xchacha20poly1305_STATEBYTES
|
||||
const HEADERBYTES = sodium.crypto_secretstream_xchacha20poly1305_HEADERBYTES
|
||||
const KEYBYTES = sodium.crypto_secretstream_xchacha20poly1305_KEYBYTES
|
||||
const TAG_FINAL_BYTE = b4a.isBuffer(TAG_FINAL) ? TAG_FINAL[0] : TAG_FINAL
|
||||
|
||||
const EMPTY = b4a.alloc(0)
|
||||
const TAG = b4a.alloc(1)
|
||||
|
||||
class Push {
|
||||
constructor (key, state = b4a.allocUnsafeSlow(STATEBYTES), header = b4a.allocUnsafeSlow(HEADERBYTES)) {
|
||||
if (!TAG_FINAL) throw new Error('JavaScript sodium version needs to support crypto_secretstream_xchacha20poly')
|
||||
|
||||
this.key = key
|
||||
this.state = state
|
||||
this.header = header
|
||||
|
||||
sodium.crypto_secretstream_xchacha20poly1305_init_push(this.state, this.header, this.key)
|
||||
}
|
||||
|
||||
next (message, cipher = b4a.allocUnsafe(message.byteLength + ABYTES)) {
|
||||
sodium.crypto_secretstream_xchacha20poly1305_push(this.state, cipher, message, null, TAG_MESSAGE)
|
||||
return cipher
|
||||
}
|
||||
|
||||
final (message = EMPTY, cipher = b4a.allocUnsafe(ABYTES)) {
|
||||
sodium.crypto_secretstream_xchacha20poly1305_push(this.state, cipher, message, null, TAG_FINAL)
|
||||
return cipher
|
||||
}
|
||||
}
|
||||
|
||||
class Pull {
|
||||
constructor (key, state = b4a.allocUnsafeSlow(STATEBYTES)) {
|
||||
if (!TAG_FINAL) throw new Error('JavaScript sodium version needs to support crypto_secretstream_xchacha20poly')
|
||||
|
||||
this.key = key
|
||||
this.state = state
|
||||
this.final = false
|
||||
}
|
||||
|
||||
init (header) {
|
||||
sodium.crypto_secretstream_xchacha20poly1305_init_pull(this.state, header, this.key)
|
||||
}
|
||||
|
||||
next (cipher, message = b4a.allocUnsafe(cipher.byteLength - ABYTES)) {
|
||||
sodium.crypto_secretstream_xchacha20poly1305_pull(this.state, message, TAG, cipher, null)
|
||||
this.final = TAG[0] === TAG_FINAL_BYTE
|
||||
return message
|
||||
}
|
||||
}
|
||||
|
||||
function keygen (buf = b4a.alloc(KEYBYTES)) {
|
||||
sodium.crypto_secretstream_xchacha20poly1305_keygen(buf)
|
||||
return buf
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
keygen,
|
||||
KEYBYTES,
|
||||
ABYTES,
|
||||
STATEBYTES,
|
||||
HEADERBYTES,
|
||||
Push,
|
||||
Pull
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"name": "sodium-secretstream",
|
||||
"version": "1.2.0",
|
||||
"description": "Wraps libsodiums secretstream in a higher level abstraction",
|
||||
"main": "index.js",
|
||||
"dependencies": {
|
||||
"b4a": "^1.1.1",
|
||||
"sodium-universal": "^5.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"standard": "^17.0.0"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "standard"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/mafintosh/sodium-secretstream.git"
|
||||
},
|
||||
"author": "Mathias Buus (@mafintosh)",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/mafintosh/sodium-secretstream/issues"
|
||||
},
|
||||
"homepage": "https://github.com/mafintosh/sodium-secretstream"
|
||||
}
|
||||
Reference in New Issue
Block a user