git ssb

1+

Dominic / ssb-private-groups



Tree: 7ff37da828525e6feaaf0963446b10fbe5af99f8

Files: 7ff37da828525e6feaaf0963446b10fbe5af99f8 / test / group.js

4181 bytesRaw
1var chloride = require('chloride')
2var crypto = require('crypto')
3var tape = require('tape')
4var group_box = require('group-box')
5var u = require('../util')
6var ssbKeys = require('ssb-keys')
7
8var Scuttlebot = require('ssb-server')
9 .use(require('../'))
10
11function hash (s) {
12 return chloride.crypto_hash_sha256(Buffer.from(s, 'utf8'))
13}
14
15var alice = Scuttlebot({
16 temp: true,
17 keys: ssbKeys.generate(null, hash('alice_secret1'))
18})
19
20var bob = alice.createFeed(ssbKeys.generate(null, hash('bob_secret1')))
21
22function 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
30function toBuffer(s) {
31 return Buffer.isBuffer(s) ? s : Buffer.from(s, 'base64')
32}
33
34function scalarmult (pk,sk) {
35 return chloride.crypto_scalarmult(toBuffer(pk), toBuffer(sk))
36}
37var alice_keys = generate(hash('alice_secret2'))
38var bob_keys = generate(hash('bob_secret2'))
39
40var alice_prev, bob_prev
41
42tape('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
63function 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
71tape('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
144tape('cleanup', function (t) {
145 alice.close()
146 t.end()
147})
148
149

Built with git-ssb-web