├── README.md ├── ex.js ├── index.js ├── package.json └── test └── test.js /README.md: -------------------------------------------------------------------------------- 1 | # hypercore-private-box 2 | 3 | > Encrypt messages that only members of a set of hypercores can decrypt. 4 | 5 | Wraps [private-box](https://github.com/auditdrivencrypto/private-box) to support hypercore (ed25519) keys. 6 | 7 | ## Usage 8 | 9 | ```js 10 | var hbox = require('hypercore-private-box') 11 | var hypercore = require('hypercore') 12 | var ram = require('random-access-memory') 13 | 14 | var core = hypercore(ram, { valueEncoding: 'json' }) 15 | var text = Buffer.from('hello secure world!') 16 | 17 | core.ready(function () { 18 | var ctext = hbox.box(text, core) 19 | console.log(ctext) 20 | var result = hbox.unbox(ctext, core) 21 | console.log(result) 22 | }) 23 | ``` 24 | 25 | outputs 26 | 27 | ``` 28 | 29 | hello secure world! 30 | ``` 31 | 32 | ## API 33 | 34 | ```js 35 | var hbox = require('hypercore-private-box') 36 | ``` 37 | 38 | ### var ctext = hbox.box(buf, recipients) 39 | 40 | Encrypts the buffer `buf` such that only the `recipients` (array of 1-7 hypercores) can decrypt. 41 | 42 | ### var res = hbox.unbox(buf, core) 43 | 44 | Decrypts the ciphertext buffer `buf` using the hypercore `core`. Returns `undefined` if the buffer could not be decrypted. 45 | 46 | ## Install 47 | 48 | With [npm](https://npmjs.org/) installed, run 49 | 50 | ``` 51 | $ npm install hypercore-private-box 52 | ``` 53 | 54 | ## Thanks 55 | 56 | Appreciation goes out to punkmonk (`@EaYYQo5nAQRabB9nxAn5i2uiIZ665b90Qk2U/WHNVE8=.ed25519`) for helping me figure out how sodium works! 57 | 58 | ## License 59 | 60 | ISC 61 | 62 | -------------------------------------------------------------------------------- /ex.js: -------------------------------------------------------------------------------- 1 | var hbox = require('.') 2 | var hypercore = require('hypercore') 3 | var ram = require('random-access-memory') 4 | 5 | var core = hypercore(ram, { valueEncoding: 'json' }) 6 | var text = Buffer.from('hello secure world!') 7 | 8 | core.ready(function () { 9 | var ctext = hbox.box(text, core) 10 | console.log(ctext) 11 | var result = hbox.unbox(ctext, core) 12 | console.log(result.toString()) 13 | }) 14 | 15 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var pb = require('private-box') 2 | var sodium = require('sodium-universal') 3 | 4 | module.exports = { 5 | box: box, 6 | unbox: unbox 7 | } 8 | 9 | // Data buffer, array of hypercore public key buffers 10 | // Returns ciphertext buffer 11 | function box (data, recipients) { 12 | if (!Array.isArray(recipients)) recipients = [recipients] 13 | recipients = recipients.map(function (core) { 14 | var pkbuf = Buffer.alloc(sodium.crypto_box_PUBLICKEYBYTES) 15 | sodium.crypto_sign_ed25519_pk_to_curve25519(pkbuf, core.key) 16 | return pkbuf 17 | }) 18 | return pb.encrypt(data, recipients) 19 | } 20 | 21 | // Encrypted data buffer, hypercore secret key 22 | // Returns decrypted buffer, or undefined if not addressed to the key 23 | function unbox (cdata, core) { 24 | var skbuf = Buffer.alloc(sodium.crypto_box_SECRETKEYBYTES) 25 | sodium.crypto_sign_ed25519_sk_to_curve25519(skbuf, core.secretKey) 26 | return pb.decrypt(cdata, skbuf) 27 | } 28 | 29 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hypercore-private-box", 3 | "description": "Encrypt messages that only members of a set of hypercores can decrypt", 4 | "author": "noffle ", 5 | "version": "1.0.0", 6 | "repository": { 7 | "url": "git://github.com/noffle/hypercore-private-box.git" 8 | }, 9 | "homepage": "https://github.com/noffle/hypercore-private-box", 10 | "bugs": "https://github.com/noffle/hypercore-private-box/issues", 11 | "main": "index.js", 12 | "scripts": { 13 | "test": "tape test/*.js", 14 | "lint": "standard" 15 | }, 16 | "keywords": [], 17 | "dependencies": { 18 | "hypercore": "^7.2.0", 19 | "private-box": "^0.3.0", 20 | "sodium-universal": "^2.0.0" 21 | }, 22 | "devDependencies": { 23 | "random-access-memory": "^3.1.1", 24 | "standard": "~10.0.0", 25 | "tape": "~4.6.2" 26 | }, 27 | "license": "ISC" 28 | } 29 | -------------------------------------------------------------------------------- /test/test.js: -------------------------------------------------------------------------------- 1 | var hbox = require('..') 2 | var hypercore = require('hypercore') 3 | var ram = require('random-access-memory') 4 | var test = require('tape') 5 | 6 | test('simple box + unbox', function (t) { 7 | var core = hypercore(ram, { valueEncoding: 'json' }) 8 | var text = Buffer.from('hello secure world!') 9 | 10 | core.ready(function () { 11 | var ctext = hbox.box(text, core) 12 | var result = hbox.unbox(ctext, core) 13 | t.same(result, text, 'core can decrypt ok') 14 | t.end() 15 | }) 16 | }) 17 | 18 | test('multi-recipient box + unbox', function (t) { 19 | var core1 = hypercore(ram, { valueEncoding: 'json' }) 20 | var core2 = hypercore(ram, { valueEncoding: 'json' }) 21 | var text = Buffer.from('hello secure world!') 22 | 23 | core1.ready(function () { 24 | core2.ready(function () { 25 | var ctext = hbox.box(text, [core1, core2]) 26 | var result1 = hbox.unbox(ctext, core1) 27 | var result2 = hbox.unbox(ctext, core2) 28 | t.same(result1, text, 'core 1 can decrypt ok') 29 | t.same(result2, text, 'core 2 can decrypt ok') 30 | t.end() 31 | }) 32 | }) 33 | }) 34 | 35 | --------------------------------------------------------------------------------