git ssb

1+

Dominic / ssb-private-groups



Commit 4de96c011f2e32da25a86df102a8af549f39d44c

create a group, add a message to it, add someone to the group and have them decrypt that message!

Dominic Tarr committed on 12/29/2018, 8:32:36 AM
Parent: a04dfcd772979f83cc19151bfd4b98c9079ea190

Files changed

test/group.jsadded
test/group.jsView
@@ -1,0 +1,148 @@
1 +var chloride = require('chloride')
2 +var crypto = require('crypto')
3 +var tape = require('tape')
4 +var group_box = require('group-box')
5 +var u = require('../util')
6 +var ssbKeys = require('ssb-keys')
7 +
8 +var Scuttlebot = require('ssb-server')
9 + .use(require('../'))
10 +
11 +function hash (s) {
12 + return chloride.crypto_hash_sha256(Buffer.from(s, 'utf8'))
13 +}
14 +
15 +var alice = Scuttlebot({
16 + temp: true,
17 + keys: ssbKeys.generate(null, hash('alice_secret1'))
18 +})
19 +
20 +var bob = alice.createFeed(ssbKeys.generate(null, hash('bob_secret1')))
21 +
22 +function generate (seed) {
23 + var keys = chloride.crypto_box_seed_keypair(seed)
24 + return {
25 + public: keys.publicKey.toString('base64')+'.curve25519',
26 + private: keys.secretKey.toString('base64')
27 + }
28 +}
29 +
30 +function toBuffer(s) {
31 + return Buffer.isBuffer(s) ? s : Buffer.from(s, 'base64')
32 +}
33 +
34 +function scalarmult (pk,sk) {
35 + return chloride.crypto_scalarmult(toBuffer(pk), toBuffer(sk))
36 +}
37 +var alice_keys = generate(hash('alice_secret2'))
38 +var bob_keys = generate(hash('bob_secret2'))
39 +
40 +var alice_prev, bob_prev
41 +
42 +tape('first message cannot be encrypted', function (t) {
43 + alice.privateGroups.addCurvePair(alice_keys, function (err) {
44 + if(err) throw err
45 + alice.publish({
46 + type: 'private-msg-key',
47 + key: alice_keys.public
48 + }, function (err, data) {
49 + if(err) throw err
50 + alice_prev = data.key
51 + bob.publish({
52 + type: 'private-msg-key',
53 + key: bob_keys.public
54 + }, function (err, data) {
55 + bob_prev = data.key
56 + if(err) throw err
57 + t.end()
58 + })
59 + })
60 + })
61 +})
62 +
63 +function encrypt (content, prev, keys) {
64 + return group_box.box(
65 + Buffer.from(JSON.stringify(content), 'utf8'),
66 + Buffer.isBuffer(prev) ? prev : u.id2Buffer(prev),
67 + keys
68 + ).toString('base64')+'.box2'
69 +}
70 +
71 +tape('bob creates a group', function (t) {
72 + var content = {
73 + type: 'event',
74 + text: "alice's surprise birthday"
75 + }
76 + //hot wiring group_box here!
77 + //todo: make group-box fully deterministic, so payload_key
78 + //may be passed in.
79 + var en_key = crypto.randomBytes(32)
80 + var ctxt = encrypt(content, bob_prev, [en_key])
81 + var nonce = u.id2Buffer(bob_prev)
82 + var group_key = group_box.unboxKey(u.ctxt2Buffer(ctxt), nonce, [en_key], 8)
83 +
84 + t.notEqual(group_key, en_key)
85 + t.ok(group_key, 'message can be decrypted')
86 +
87 + //create a group
88 + bob.publish(
89 + ctxt,
90 + function (err, data) {
91 + if(err) throw err
92 + t.ok(data.key)
93 + var group_id = data.key
94 + nonce = u.id2Buffer(data.key)
95 + var theme = {
96 + type:'post', text: 'Theme: dress up as your favorite TLA'
97 + }
98 + //a message for the group
99 + bob.publish(encrypt(theme, data.key, [
100 + u.hmac(Buffer.concat([nonce, u.id2Buffer(group_id)]), group_key)
101 + ]), function (err, data) {
102 + if(err) throw err
103 + var msg_in_group = data.key
104 +
105 + var group_msg_key = u.hmac(Buffer.concat([nonce, u.id2Buffer(group_id)]), group_key)
106 + var keys = [bob_keys, alice_keys].map(function (key) {
107 + return scalarmult(bob_keys.private, key.public)
108 + })
109 +
110 + //message inviting alice to the group
111 + bob.publish(
112 + encrypt({
113 + type: 'entrust',
114 + group: group_id,
115 + unbox: group_key.toString('base64')
116 + }, data.key, keys.concat([group_msg_key])),
117 + function (err, data) {
118 + if(err) throw err
119 + var invite_id = data.key
120 + t.ok(data)
121 + alice.get({id: invite_id, private: true}, function (err, msg) {
122 + if(err) throw err
123 + t.equal(msg.content.group, group_id)
124 + t.equal(msg.content.unbox, group_key.toString('base64'))
125 + alice.privateGroups.addGroupKey({
126 + id: msg.content.group,
127 + unbox: msg.content.unbox
128 + }, function (err) {
129 + if(err) throw err
130 + alice.get({private: true, id: msg_in_group}, function (err, msg) {
131 + if(err) throw err
132 + t.deepEqual(msg.content, theme)
133 + t.end()
134 + })
135 + })
136 + })
137 + }
138 + )
139 + })
140 + }
141 + )
142 +})
143 +
144 +tape('cleanup', function (t) {
145 + alice.close()
146 + t.end()
147 +})
148 +

Built with git-ssb-web