Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F3241577
D10876.id36498.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
15 KB
Referenced Files
None
Subscribers
None
D10876.id36498.diff
View Options
diff --git a/keyserver/src/updaters/olm-account-updater.js b/keyserver/src/updaters/olm-account-updater.js
--- a/keyserver/src/updaters/olm-account-updater.js
+++ b/keyserver/src/updaters/olm-account-updater.js
@@ -43,7 +43,12 @@
picklingKey,
pickledAccount,
});
- const result = await callback(account, picklingKey);
+ let result;
+ try {
+ result = await callback(account, picklingKey);
+ } catch (e) {
+ throw new ServerError(e.message);
+ }
const updatedAccount = account.pickle(picklingKey);
const [transactionResult] = await dbQuery(
diff --git a/keyserver/src/user/login.js b/keyserver/src/user/login.js
--- a/keyserver/src/user/login.js
+++ b/keyserver/src/user/login.js
@@ -3,10 +3,9 @@
import type { Account as OlmAccount } from '@commapp/olm';
import { getRustAPI } from 'rust-node-addon';
-import { getOneTimeKeyValuesFromBlob } from 'lib/shared/crypto-utils.js';
-import { ONE_TIME_KEYS_NUMBER } from 'lib/types/identity-service-types.js';
import { getCommConfig } from 'lib/utils/comm-config.js';
import { ServerError } from 'lib/utils/errors.js';
+import { retrieveAccountKeysSet } from 'lib/utils/olm-utils.js';
import {
saveIdentityInfo,
@@ -15,40 +14,9 @@
} from './identity.js';
import { getMessageForException } from '../responders/utils.js';
import { fetchCallUpdateOlmAccount } from '../updaters/olm-account-updater.js';
-import {
- getAccountPrekeysSet,
- validateAccountPrekey,
-} from '../utils/olm-utils.js';
type UserCredentials = { +username: string, +password: string };
-export type AccountKeysSet = {
- +identityKeys: string,
- +prekey: string,
- +prekeySignature: string,
- +oneTimeKeys: $ReadOnlyArray<string>,
-};
-
-function retrieveAccountKeysSet(account: OlmAccount): AccountKeysSet {
- const identityKeys = account.identity_keys();
-
- validateAccountPrekey(account);
- const { prekey, prekeySignature } = getAccountPrekeysSet(account);
-
- if (!prekeySignature || !prekey) {
- throw new ServerError('invalid_prekey');
- }
-
- let oneTimeKeys = getOneTimeKeyValuesFromBlob(account.one_time_keys());
-
- if (oneTimeKeys.length < ONE_TIME_KEYS_NUMBER) {
- account.generate_one_time_keys(ONE_TIME_KEYS_NUMBER);
- oneTimeKeys = getOneTimeKeyValuesFromBlob(account.one_time_keys());
- }
-
- return { identityKeys, oneTimeKeys, prekey, prekeySignature };
-}
-
// After register or login is successful
function markKeysAsPublished(account: OlmAccount) {
account.mark_prekey_as_published();
diff --git a/keyserver/src/utils/olm-utils.js b/keyserver/src/utils/olm-utils.js
--- a/keyserver/src/utils/olm-utils.js
+++ b/keyserver/src/utils/olm-utils.js
@@ -12,7 +12,11 @@
import { getOneTimeKeyValuesFromBlob } from 'lib/shared/crypto-utils.js';
import { olmEncryptedMessageTypes } from 'lib/types/crypto-types.js';
import { ServerError } from 'lib/utils/errors.js';
-import { values } from 'lib/utils/objects.js';
+import {
+ getAccountPrekeysSet,
+ shouldForgetPrekey,
+ shouldRotatePrekey,
+} from 'lib/utils/olm-utils.js';
import {
fetchCallUpdateOlmAccount,
@@ -25,49 +29,6 @@
+pickledAccount: string,
};
-const maxPublishedPrekeyAge = 30 * 24 * 60 * 60 * 1000;
-const maxOldPrekeyAge = 24 * 60 * 60 * 1000;
-
-function getLastPrekeyPublishTime(account: OlmAccount): Date {
- const olmLastPrekeyPublishTime = account.last_prekey_publish_time();
-
- // Olm uses seconds, while in Node we need milliseconds.
- return new Date(olmLastPrekeyPublishTime * 1000);
-}
-
-function shouldRotatePrekey(account: OlmAccount): boolean {
- // Our fork of Olm only remembers two prekeys at a time.
- // If the new one hasn't been published, then the old one is still active.
- // In that scenario, we need to avoid rotating the prekey because it will
- // result in the old active prekey being discarded.
- if (account.unpublished_prekey()) {
- return false;
- }
-
- const currentDate = new Date();
- const lastPrekeyPublishDate = getLastPrekeyPublishTime(account);
-
- return (
- currentDate.getTime() - lastPrekeyPublishDate.getTime() >=
- maxPublishedPrekeyAge
- );
-}
-
-function shouldForgetPrekey(account: OlmAccount): boolean {
- // Our fork of Olm only remembers two prekeys at a time.
- // We have to hold onto the old one until the new one is published.
- if (account.unpublished_prekey()) {
- return false;
- }
-
- const currentDate = new Date();
- const lastPrekeyPublishDate = getLastPrekeyPublishTime(account);
-
- return (
- currentDate.getTime() - lastPrekeyPublishDate.getTime() >= maxOldPrekeyAge
- );
-}
-
async function createPickledOlmAccount(): Promise<PickledOlmAccount> {
await olm.init();
const account = new olm.Account();
@@ -139,15 +100,6 @@
return cachedOLMUtility;
}
-function validateAccountPrekey(account: OlmAccount) {
- if (shouldRotatePrekey(account)) {
- account.generate_prekey();
- }
- if (shouldForgetPrekey(account)) {
- account.forget_old_prekey();
- }
-}
-
async function uploadNewOneTimeKeys(numberOfKeys: number) {
const [rustAPI, identityInfo, deviceID] = await Promise.all([
getRustAPI(),
@@ -192,16 +144,6 @@
return JSON.parse(accountInfo.account.identity_keys()).ed25519;
}
-function getAccountPrekeysSet(account: OlmAccount): {
- +prekey: string,
- +prekeySignature: ?string,
-} {
- const prekeyMap = JSON.parse(account.prekey()).curve25519;
- const [prekey] = values(prekeyMap);
- const prekeySignature = account.prekey_signature();
- return { prekey, prekeySignature };
-}
-
async function validateAndUploadAccountPrekeys(
contentAccount: OlmAccount,
notifAccount: OlmAccount,
@@ -267,10 +209,8 @@
getOlmUtility,
unpickleOlmAccount,
unpickleOlmSession,
- validateAccountPrekey,
uploadNewOneTimeKeys,
getContentSigningKey,
- getAccountPrekeysSet,
validateAndUploadAccountPrekeys,
publishPrekeysToIdentity,
};
diff --git a/lib/flow-typed/npm/@commapp/olm_vx.x.x.js b/lib/flow-typed/npm/@commapp/olm_vx.x.x.js
new file mode 100644
--- /dev/null
+++ b/lib/flow-typed/npm/@commapp/olm_vx.x.x.js
@@ -0,0 +1,182 @@
+// flow-typed signature: 085f002da86534cfd8cee47ffa99dd67
+// flow-typed version: <<STUB>>/@commapp/olm_v3.2.4/flow_v0.182.0
+
+declare module '@commapp/olm' {
+
+/*
+Copyright 2020 The Matrix.org Foundation C.I.C.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+ declare export class Account {
+ constructor(): void;
+ free(): void;
+ create(): void;
+ identity_keys(): string;
+ sign(message: string | Uint8Array): string;
+ one_time_keys(): string;
+ mark_keys_as_published(): void;
+ max_number_of_one_time_keys(): number;
+ generate_one_time_keys(number_of_keys: number): void;
+ remove_one_time_keys(session: Session): void;
+ generate_prekey(): void;
+ prekey(): string;
+ unpublished_prekey(): ?string;
+ prekey_signature(): ?string;
+ forget_old_prekey(): void;
+ mark_prekey_as_published(): void;
+ last_prekey_publish_time(): number;
+ generate_fallback_key(): void;
+ fallback_key(): string;
+ unpublished_fallback_key(): string;
+ forget_old_fallback_key(): void;
+ pickle(key: string | Uint8Array): string;
+ unpickle(key: string | Uint8Array, pickle: string): void;
+ }
+
+ declare export type EncryptResult = {
+ +type: 0 | 1, // 0: PreKey, 1: Message
+ +body: string,
+ };
+ declare export class Session {
+ constructor(): void;
+ free(): void;
+ pickle(key: string | Uint8Array): string;
+ unpickle(key: string | Uint8Array, pickle: string): void;
+ create_outbound(
+ account: Account,
+ their_identity_key: string,
+ their_signing_key: string,
+ their_prekey: string,
+ their_prekey_signature: string,
+ their_one_time_key: string,
+ ): void;
+ create_inbound(account: Account, one_time_key_message: string): void;
+ create_inbound_from(
+ account: Account,
+ identity_key: string,
+ one_time_key_message: string,
+ ): void;
+ session_id(): string;
+ has_received_message(): boolean;
+ matches_inbound(one_time_key_message: string): boolean;
+ matches_inbound_from(
+ identity_key: string,
+ one_time_key_message: string,
+ ): boolean;
+ encrypt(plaintext: string): EncryptResult;
+ decrypt(message_type: number, message: string): string;
+ describe(): string;
+ }
+
+ declare export class Utility {
+ constructor(): void;
+ free(): void;
+ sha256(input: string | Uint8Array): string;
+ ed25519_verify(
+ key: string,
+ message: string | Uint8Array,
+ signature: string,
+ ): void;
+ }
+
+ declare export type DecryptResult = {
+ +message_index: string,
+ +plaintext: string,
+ };
+
+ declare export class InboundGroupSession {
+ constructor(): void;
+ free(): void;
+ pickle(key: string | Uint8Array): string;
+ unpickle(key: string | Uint8Array, pickle: string): void;
+ create(session_key: string): string;
+ import_session(session_key: string): string;
+ decrypt(message: string): DecryptResult;
+ session_id(): string;
+ first_known_index(): number;
+ export_session(message_index: number): string;
+ }
+
+ declare export class OutboundGroupSession {
+ constructor(): void;
+ free(): void;
+ pickle(key: string | Uint8Array): string;
+ unpickle(key: string | Uint8Array, pickle: string): void;
+ create(): void;
+ encrypt(plaintext: string): string;
+ session_id(): string;
+ session_key(): string;
+ message_index(): number;
+ }
+
+ declare export type PkEncryptionEncryptResult = {
+ +ciphertext: string,
+ +mac: string,
+ +ephemeral: string,
+ };
+
+ declare export class PkEncryption {
+ constructor(): void;
+ free(): void;
+ set_recipient_key(key: string): void;
+ encrypt(plaintext: string): PkEncryptionEncryptResult;
+ }
+
+ declare export class PkDecryption {
+ constructor(): void;
+ free(): void;
+ init_with_private_key(key: Uint8Array): string;
+ generate_key(): string;
+ get_private_key(): Uint8Array;
+ pickle(key: string | Uint8Array): string;
+ unpickle(key: string | Uint8Array, pickle: string): string;
+ decrypt(ephemeral_key: string, mac: string, ciphertext: string): string;
+ }
+
+ declare export class PkSigning {
+ constructor(): void;
+ free(): void;
+ init_with_seed(seed: Uint8Array): string;
+ generate_seed(): Uint8Array;
+ sign(message: string): string;
+ }
+
+ declare export class SAS {
+ constructor(): void;
+ free(): void;
+ get_pubkey(): string;
+ set_their_key(their_key: string): void;
+ generate_bytes(info: string, length: number): Uint8Array;
+ calculate_mac(input: string, info: string): string;
+ calculate_mac_fixed_base64(input: string, info: string): string;
+ calculate_mac_long_kdf(input: string, info: string): string;
+ }
+
+ declare export function init(opts?: Object): Promise<void>;
+
+ declare export function get_library_version(): [number, number, number];
+
+ declare export var PRIVATE_KEY_LENGTH: number;
+
+ declare export default {
+ init: typeof init,
+ get_library_version: typeof get_library_version,
+ PRIVATE_KEY_LENGTH: typeof PRIVATE_KEY_LENGTH,
+ Account: typeof Account,
+ Utility: typeof Utility,
+ Session: typeof Session,
+ };
+
+}
diff --git a/lib/package.json b/lib/package.json
--- a/lib/package.json
+++ b/lib/package.json
@@ -35,6 +35,7 @@
"webpack": "^5.76.0"
},
"dependencies": {
+ "@commapp/olm": "0.1.0",
"@rainbow-me/rainbowkit": "^1.1.1",
"dateformat": "^3.0.3",
"emoji-regex": "^10.2.1",
diff --git a/lib/utils/olm-utils.js b/lib/utils/olm-utils.js
new file mode 100644
--- /dev/null
+++ b/lib/utils/olm-utils.js
@@ -0,0 +1,103 @@
+// @flow
+
+import type { Account as OlmAccount } from '@commapp/olm';
+
+import { values } from './objects.js';
+import { getOneTimeKeyValuesFromBlob } from '../shared/crypto-utils.js';
+import { ONE_TIME_KEYS_NUMBER } from '../types/identity-service-types.js';
+
+const maxPublishedPrekeyAge = 30 * 24 * 60 * 60 * 1000;
+const maxOldPrekeyAge = 24 * 60 * 60 * 1000;
+
+type AccountKeysSet = {
+ +identityKeys: string,
+ +prekey: string,
+ +prekeySignature: string,
+ +oneTimeKeys: $ReadOnlyArray<string>,
+};
+
+function validateAccountPrekey(account: OlmAccount) {
+ if (shouldRotatePrekey(account)) {
+ account.generate_prekey();
+ }
+ if (shouldForgetPrekey(account)) {
+ account.forget_old_prekey();
+ }
+}
+
+function shouldRotatePrekey(account: OlmAccount): boolean {
+ // Our fork of Olm only remembers two prekeys at a time.
+ // If the new one hasn't been published, then the old one is still active.
+ // In that scenario, we need to avoid rotating the prekey because it will
+ // result in the old active prekey being discarded.
+ if (account.unpublished_prekey()) {
+ return false;
+ }
+
+ const currentDate = new Date();
+ const lastPrekeyPublishDate = getLastPrekeyPublishTime(account);
+
+ return (
+ currentDate.getTime() - lastPrekeyPublishDate.getTime() >=
+ maxPublishedPrekeyAge
+ );
+}
+
+function shouldForgetPrekey(account: OlmAccount): boolean {
+ // Our fork of Olm only remembers two prekeys at a time.
+ // We have to hold onto the old one until the new one is published.
+ if (account.unpublished_prekey()) {
+ return false;
+ }
+
+ const currentDate = new Date();
+ const lastPrekeyPublishDate = getLastPrekeyPublishTime(account);
+
+ return (
+ currentDate.getTime() - lastPrekeyPublishDate.getTime() >= maxOldPrekeyAge
+ );
+}
+
+function getLastPrekeyPublishTime(account: OlmAccount): Date {
+ const olmLastPrekeyPublishTime = account.last_prekey_publish_time();
+
+ // Olm uses seconds, while the Date() constructor expects milliseconds.
+ return new Date(olmLastPrekeyPublishTime * 1000);
+}
+
+function getAccountPrekeysSet(account: OlmAccount): {
+ +prekey: string,
+ +prekeySignature: ?string,
+} {
+ const prekeyMap = JSON.parse(account.prekey()).curve25519;
+ const [prekey] = values(prekeyMap);
+ const prekeySignature = account.prekey_signature();
+ return { prekey, prekeySignature };
+}
+
+function retrieveAccountKeysSet(account: OlmAccount): AccountKeysSet {
+ const identityKeys = account.identity_keys();
+
+ validateAccountPrekey(account);
+ const { prekey, prekeySignature } = getAccountPrekeysSet(account);
+
+ if (!prekeySignature || !prekey) {
+ throw new Error('invalid_prekey');
+ }
+
+ let oneTimeKeys = getOneTimeKeyValuesFromBlob(account.one_time_keys());
+
+ if (oneTimeKeys.length < ONE_TIME_KEYS_NUMBER) {
+ account.generate_one_time_keys(ONE_TIME_KEYS_NUMBER);
+ oneTimeKeys = getOneTimeKeyValuesFromBlob(account.one_time_keys());
+ }
+
+ return { identityKeys, oneTimeKeys, prekey, prekeySignature };
+}
+
+export {
+ retrieveAccountKeysSet,
+ getAccountPrekeysSet,
+ shouldForgetPrekey,
+ shouldRotatePrekey,
+};
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Nov 14, 7:24 PM (11 h, 27 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2492227
Default Alt Text
D10876.id36498.diff (15 KB)
Attached To
Mode
D10876: [lib] move olm utils from keyserver to lib
Attached
Detach File
Event Timeline
Log In to Comment