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 AMParent: a04dfcd772979f83cc19151bfd4b98c9079ea190
Files changed
test/group.js | added |
test/group.js | ||
---|---|---|
@@ -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