/
keys-responders.js
139 lines (118 loc) · 4.16 KB
/
keys-responders.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
// @flow
import type { Account as OlmAccount } from '@commapp/olm';
import t, { type TUnion, type TInterface } from 'tcomb';
import type {
OlmSessionInitializationInfo,
GetOlmSessionInitializationDataResponse,
GetSessionPublicKeysArgs,
} from 'lib/types/request-types.js';
import {
type SessionPublicKeys,
sessionPublicKeysValidator,
} from 'lib/types/session-types.js';
import { ServerError } from 'lib/utils/errors.js';
import { tShape, tNull } from 'lib/utils/validation-utils.js';
import { fetchSessionPublicKeys } from '../fetchers/key-fetchers.js';
import { verifyClientSupported } from '../session/version.js';
import type { Viewer } from '../session/viewer.js';
import { fetchCallUpdateOlmAccount } from '../updaters/olm-account-updater.js';
import { validateAccountPrekey } from '../utils/olm-utils.js';
type AccountKeysSet = {
+identityKeys: string,
...OlmSessionInitializationInfo,
};
export const getSessionPublicKeysInputValidator: TInterface<GetSessionPublicKeysArgs> =
tShape<GetSessionPublicKeysArgs>({
session: t.String,
});
type GetSessionPublicKeysResponse = SessionPublicKeys | null;
export const getSessionPublicKeysResponseValidator: TUnion<GetSessionPublicKeysResponse> =
t.union([sessionPublicKeysValidator, tNull]);
async function getSessionPublicKeysResponder(
viewer: Viewer,
request: GetSessionPublicKeysArgs,
): Promise<GetSessionPublicKeysResponse> {
if (!viewer.loggedIn) {
return null;
}
return await fetchSessionPublicKeys(request.session);
}
async function retrieveAccountKeysSet(
account: OlmAccount,
): Promise<AccountKeysSet> {
const identityKeys = account.identity_keys();
await validateAccountPrekey(account);
const prekey = account.prekey();
// Until transfer of prekeys to the identity service is implemented
// prekeys will be marked as published each time it is accessed
// to establish olm notifs session to mitigate the risk of prekeys
// being in use for long enough to cause security concerns
account.mark_prekey_as_published();
const prekeySignature = account.prekey_signature();
if (!prekeySignature) {
throw new ServerError('prekey_validation_failure');
}
account.generate_one_time_keys(1);
const oneTimeKey = account.one_time_keys();
account.mark_keys_as_published();
return { identityKeys, oneTimeKey, prekey, prekeySignature };
}
async function getOlmSessionInitializationDataResponder(
viewer: Viewer,
): Promise<GetOlmSessionInitializationDataResponse> {
await verifyClientSupported(viewer);
const {
identityKeys: notificationsIdentityKeys,
prekey: notificationsPrekey,
prekeySignature: notificationsPrekeySignature,
oneTimeKey: notificationsOneTimeKey,
} = await fetchCallUpdateOlmAccount('notifications', retrieveAccountKeysSet);
const contentAccountCallback = async (account: OlmAccount) => {
const {
identityKeys: contentIdentityKeys,
oneTimeKey,
prekey,
prekeySignature,
} = await retrieveAccountKeysSet(account);
const identityKeysBlob = {
primaryIdentityPublicKeys: JSON.parse(contentIdentityKeys),
notificationIdentityPublicKeys: JSON.parse(notificationsIdentityKeys),
};
const identityKeysBlobPayload = JSON.stringify(identityKeysBlob);
const signedIdentityKeysBlob = {
payload: identityKeysBlobPayload,
signature: account.sign(identityKeysBlobPayload),
};
return {
signedIdentityKeysBlob,
oneTimeKey,
prekey,
prekeySignature,
};
};
const {
signedIdentityKeysBlob,
prekey: contentPrekey,
prekeySignature: contentPrekeySignature,
oneTimeKey: contentOneTimeKey,
} = await fetchCallUpdateOlmAccount('content', contentAccountCallback);
const notifInitializationInfo = {
prekey: notificationsPrekey,
prekeySignature: notificationsPrekeySignature,
oneTimeKey: notificationsOneTimeKey,
};
const contentInitializationInfo = {
prekey: contentPrekey,
prekeySignature: contentPrekeySignature,
oneTimeKey: contentOneTimeKey,
};
return {
signedIdentityKeysBlob,
contentInitializationInfo,
notifInitializationInfo,
};
}
export {
getSessionPublicKeysResponder,
getOlmSessionInitializationDataResponder,
};