Files: df6aa041cba3ba3c1ea7441bc50a6cd2fd1d3e1c / valid.js
4190 bytesRaw
1 | var ssbKeys = require('ssb-keys') |
2 | var isMsg = require('ssb-ref').isMsg |
3 | var u = require('./util') |
4 | |
5 | var invite_key = require('./cap') |
6 | |
7 | function code(err, c) { |
8 | err.code = 'user-invites:'+c |
9 | return err |
10 | } |
11 | |
12 | exports.createInvite = function (seed, host, reveal, private) { |
13 | var keys = ssbKeys.generate(null, seed) //K |
14 | if(keys.id === host) |
15 | throw code(new Error('do not create invite with own public key'), 'user-invites:no-own-goal') |
16 | return ssbKeys.signObj(keys, invite_key, { |
17 | type: 'user-invite', |
18 | invite: keys.id, |
19 | host: host, //sign our own key, to prove we created K |
20 | reveal: reveal ? u.box(reveal, u.hash(u.hash(seed))) : undefined, |
21 | private: private ? u.box(private, u.hash(seed)) : undefined |
22 | }) |
23 | } |
24 | |
25 | exports.verifyInvitePublic = function (msg) { |
26 | if(msg.content.host != msg.author) |
27 | throw code(new Error('host did not match author'), 'host-must-match-author') |
28 | |
29 | if(!ssbKeys.verifyObj(msg.content.invite, invite_key, msg.content)) |
30 | throw code(new Error('invalid invite signature'), 'invite-signature-failed') |
31 | |
32 | //an ordinary message so doesn't use special hmac_key, unless configed to. |
33 | //TODO: import caps from config!!! |
34 | if(!ssbKeys.verifyObj(msg.author, msg)) |
35 | throw code(new Error('invalid host signature'), 'host-signature-failed') |
36 | return true |
37 | } |
38 | |
39 | exports.verifyInvitePrivate = function (msg, seed) { |
40 | exports.verifyInvitePublic(msg) |
41 | if(msg.content.reveal) { |
42 | var reveal = u.unbox(msg.content.reveal, u.hash(u.hash(seed))) |
43 | if(!reveal) throw code(new Error('could not decrypt reveal field'), 'decrypt-reveal-failed') |
44 | } |
45 | if(msg.content.private) { |
46 | var private = u.unbox(msg.content.private, u.hash(seed)) |
47 | if(!private) throw code(new Error('could not decrypt private field'), 'decrypt-private-failed') |
48 | } |
49 | |
50 | return {reveal: reveal, private: private} |
51 | } |
52 | |
53 | exports.createAccept = function (msg, seed, id) { |
54 | exports.verifyInvitePrivate(msg, seed) |
55 | var keys = ssbKeys.generate(null, seed) //K |
56 | if(keys.id != msg.content.invite) |
57 | throw code(new Error('seed does not match invite'), 'seed-must-match-invite') |
58 | var inviteId = '%'+ssbKeys.hash(JSON.stringify(msg, null, 2)) |
59 | return ssbKeys.signObj(keys, invite_key, { |
60 | type: 'user-invite/accept', |
61 | receipt: inviteId, |
62 | id: id, |
63 | key: msg.content.reveal ? u.hash(u.hash(seed)).toString('base64') : undefined |
64 | }) |
65 | } |
66 | |
67 | exports.verifyAcceptOnly = function (accept) { |
68 | if(accept.content.type !== 'user-invite/accept') |
69 | throw code(new Error('accept must be type: "user-invite/accept", was:'+JSON.stringify(accept.content.type)), 'accept-message-type') |
70 | if(!isMsg(accept.content.receipt)) |
71 | throw code(new Error('accept must reference invite message id'), 'accept-reference-invite') |
72 | if(!ssbKeys.verifyObj(accept.content.id, accept)) |
73 | throw code(new Error('acceptance must be signed by claimed key'), 'accept-signature-failed') |
74 | } |
75 | |
76 | exports.verifyAccept = function (accept, invite) { |
77 | if(!invite) throw new Error('invite must be provided') |
78 | |
79 | exports.verifyAcceptOnly(accept) |
80 | |
81 | if(invite.content.type !== 'user-invite') |
82 | throw code(new Error('accept must be type: invite, was:'+accept.content.type), 'user-invites:invite-message-type') |
83 | |
84 | var invite_id = '%'+ssbKeys.hash(JSON.stringify(invite, null, 2)) |
85 | var reveal |
86 | |
87 | if(invite_id !== accept.content.receipt) |
88 | throw code(new Error('acceptance not matched to given invite, got:'+invite_id+' expected:'+accept.content.receipt), 'accept-wrong-invite') |
89 | |
90 | if(accept.author === invite.content.id) |
91 | throw code(new Error('guest must use a new key, not the same seed'), 'guest-key-reuse') |
92 | if(invite.content.reveal) { |
93 | if(!accept.content.key) |
94 | throw code(new Error('accept missing reveal key, when invite has it'), 'accept-must-reveal-key') |
95 | reveal = u.unbox(invite.content.reveal, new Buffer(accept.content.key, 'base64')) |
96 | if(!reveal) throw code(new Error('accept did not correctly reveal invite'), 'decrypt-accept-reveal-failed') |
97 | } |
98 | |
99 | if(!ssbKeys.verifyObj(invite.content.invite, invite_key, accept.content)) |
100 | throw code(new Error('did not verify invite-acceptance contents'), 'accept-invite-signature-failed') |
101 | //an ordinary message, so does not use hmac_key |
102 | return reveal || true |
103 | } |
104 | |
105 |
Built with git-ssb-web