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